From 83dea87c62a44e8d180811e4d1b5c9da211dddeb Mon Sep 17 00:00:00 2001 From: barbara Date: Sat, 28 Jan 2017 19:29:21 +0100 Subject: [PATCH 001/643] 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 eb54bc8544f0d482336878e211269ea43da9a7a7 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Mon, 30 Jan 2017 11:38:32 +0100 Subject: [PATCH 002/643] 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 003/643] 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 004/643] 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 94c9b5f2b0306e9924c01486889b69934f34575a Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 19 Feb 2017 16:46:31 +0100 Subject: [PATCH 005/643] 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 cc973dcb62d310f1af0d08d408c782a57e3523cb Mon Sep 17 00:00:00 2001 From: barbara Date: Fri, 3 Mar 2017 21:01:11 +0100 Subject: [PATCH 006/643] 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 007/643] 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 008/643] 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 009/643] 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 010/643] 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 011/643] 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 012/643] 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 013/643] 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 1c43c804633f9fd36e67f9988d17e8402ac258d8 Mon Sep 17 00:00:00 2001 From: Arkalyk Akash Date: Mon, 13 Mar 2017 17:00:42 +0600 Subject: [PATCH 014/643] 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 55c11cadd38ee59e89a3128860b53f63e8b0457d Mon Sep 17 00:00:00 2001 From: ph1ps Date: Fri, 14 Apr 2017 21:37:24 +0200 Subject: [PATCH 015/643] 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 016/643] 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 017/643] 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 018/643] 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 019/643] 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 020/643] 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 021/643] 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 022/643] 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 023/643] 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 024/643] 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 025/643] 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 026/643] 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 027/643] 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 edafd431fab46087ff805f6ad419b076a076bf82 Mon Sep 17 00:00:00 2001 From: ph1ps Date: Mon, 17 Apr 2017 21:15:01 +0200 Subject: [PATCH 028/643] 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 029/643] 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 9fafc9278d72240fda1117d010b1544ff106dccb Mon Sep 17 00:00:00 2001 From: ph1ps Date: Tue, 18 Apr 2017 13:47:17 +0200 Subject: [PATCH 030/643] 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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

~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 034/643] 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 035/643] 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 036/643] 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 fbd5d6ea149cccd61c93530a772bad148e3a45e1 Mon Sep 17 00:00:00 2001 From: barbara Date: Thu, 25 May 2017 14:04:49 +0200 Subject: [PATCH 037/643] 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: Sun, 21 May 2017 21:46:01 +0200 Subject: [PATCH 031/643] 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 032/643] 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 zcmY*;1yGcK)b8%Gz=Cu)OE-&j2}>y*QY+ovAdRpfQj&s%v~+_Y2q+;E(kVzwNS7cD z_x1mMcjn%md3WBO{pE@0ob#L*ZOte6xHPyR5C~sIS@9_d1cm_bl`t&eJDw+{8w6qy zS5cJH^EcZ!#ZDquB0XSH#saG_bLK08<-${R3fGw{;BwGZ7G)w<6#@!sMI@8;`QguTmsJ+;M24I zjDSwsKZ%5dWb21{D0yBSC4&8$->h9cM>-(oWMlA2z@JU>WtDr=B4y&h%}jggwimfA zbOb#QiTW*z-h2)|n>K8GaT|DC{uqo-kj_CDE-zb7z+|_d)mhsI+iaNvDJ3?<^9uQRZO$7D271gxvIm3 zPo$u1QVvb+NL+GGmTv{TiMgo)3+^kiQ%!z9)Zm5scx3!bM7YhWwR@)g#sx$ z3%Ezr;lShlu>uToUX=FD#Abi8LIibWUUwRgA(Uw4ujP25($CR!4ysHHJZN%2(P>PB z?chWw8spLBZmj9hYigk_;D>5JPfq1;K#+k9*z~JgOdib= ziTiuFtflsr*VEtT?Ca;7lR>@rkMRTl42w+@_Od8%0Q>3rzBRU*a2jutgvP7JF`=C)iYP|w@P{9_e0zxV*^N_RY zjC!05OKQBRO2gU`5;oP0fb2ZafA=MTfkxzB#Qpsebk1+vpM<`<{LP3hKBO@FZ);P6 z#}0(DU^?vfU?qn%r6Yv@TD+Lz7}=X8K&slDjQ)5twdTujM&ui2A)^W}MG+<~+6L(h zi4Xz-B2EkL)}99*SEr5%vn(WCx>~ZgjkRE%*k^Q$p63z*z zd*7f>+X{0~WSY&5P|)_fV(9&CbNTN}CVPoaBs_DupEs4yShPANR@tm@0&J=pmV;p?cg{^w^TeBK4%TAhQ1_#VFcrezN+rP#tk9yt2Hom8k ze!J+$9lao?(tMgn# zaS?-c^E+}LgR!4Y&W@KS8})6J zHF);v2>Q?Akm2m`(auK4Nryk1!z6)!o=`sDnPM_&`f~9r?haMAS!n}Lg6HQx3W`m! z$xiE&7P247RskO3XGxh0|I8aoO~$Dm2Kc^$Aa06kMgm8xxZgoG=VsvFy=PiOVlx~A zNDJL=<=^q&6$Qc`D)pgfs*U3WonXpVUg>~6iC!l9m<+z)alFzxFP+lp5yZ^?YlrfVsl0 zKZ!{+=)~L`%E-j+dAc=zXWVYbV+XI}N&-+br^29G)wI>8e(uf9rtJOAhuQMZ<_@#Z zfiF?83#l!6#?YIG`}56-GFMwHrX}n10Rlv`WVdRF&x)S|&kA4R)BfC3ar?9U;#xy| zKOc|U3a;%B_50iMaWWFXM@7aL7fh}TEjsC3m%a?ZrIgIS1P2(^S%8_69&^Zx6tDFq zVw>FnxE)JLAVtZlIgS<|tS5NdB8!a$dDqaNj$mBHedxZ_E*g|F-|qaQ=H(5HQvgy* zpWU~%w#Ef$#0$G&oc4qS?sA=O{z7HuL4vUC-33e65707jVoqSdK(F$GFbM#R%$}Ux z%g)mkX)Phwf5qP|D!VVW`MFy%W(eBG9t8&PH~lD6dBgrox<(hbX=l2U>yh11h7O3rm%rJ4xdez5ae=YwJK~*4i#N@Zhp;0xC)9eqv*TDk_+Q{@upf2v zp7zS3m4Z+`EM7oao+OYN#@6A(tFAA9=W*=O zX&c=A8I|RjN)blNaeOV6u4$Ph#XxI(SyNJ&Hoy6`qa1p7S?XWDqMJXc*}0<2IVwMk zcl2w`h@vl|sPXyk42To%fYbI82#LG>fm*{cfC0CN&vZ&+eEmk#`4L??>LJ09w1e07 zGDpfU))Znz;i1q?_6Sg2;qPY+6m%gDIp~H$!dmkVeqWr6&OD5^54hyqsJsk9V?jV5 zR|N`DJn}5dijrujruX0CDoGwG$YD`n%VbLXi zBSEktNm@^cgM+h4qj*VnqRjj)c(L{Q9M3rPkP4=7ge95_*$M_C zQTMA(vTVS$Q-oPUu1=xv(=?CoQr@zErkxV%f5S0~!T)UnTXlkIVwmL|OsQ`P*Dkl8 zD$$_r{wyk^zA6z$mq;t>k`KVTzhE|^0&!?$1G`7ypD{e8 z6f#b}6M_~E@m#p^8}(5IsGoj~NoE3_1ao(BHAL>|(n?v33~>T}+jl^p7|5eVzvYj_j-l!5>J0eZga04$){hjaz0g#c!daRrwVB zl54uozaO;=dA6f^*Iqgl{E-Zo6BKUdrh z29Mm8p)LIjm>*+uZKROoK5P(L%}6FwPx%|4de#qeO`VU3-vNBm>c<&yA6$1;EJ%72 z-a!>89EX&>MVj6T8GkbQz4yV6hMl^;t2SXga4Up+CU zIA=k*fji|k-fBO^TtLcya!+94WJmpq-;i+qsu`(>B&Q!WeB5_eX-T%QnSdg;$#@T} zC)~nCI_WCOVekdiD^H?G2P{H{>>+$wgxHA$O*0nZqf;XN3cZ*HyJ2o_FP8VBNHBqM ziy07lx%A(KY-erEZZ@ckL@_fn>)Lbh=#_=9YTGSB$?VX@%dzzy(-rzmi&NmT{tro0 zi6HBOZ2ER1{BS=Wyn>7SU}1sciV^AcK4a*j8;-n6U{5r0s;H~cDrntSp2mNHYQ?Ts zb%mDp0ezCpM@QJ>@ZnCx%M}JF1v#IQ-Y%PUbGQYoBKuV)6^t%LrrUg#{?!MQDpF)E zkef_Z=<{gtk~579&|H18gJ7T|DsXv3Ufb1S^>KHxhoc^3YkijIqN>sy36H9-Ud9vN~tzO_WYP6AZSk2`C7kSj^+Z+@#N!lqad*ai z-qT>cl2aV&BB$s>dz|4G?#vcMt=hsOm`r^BTU42W*m1hjkV8C>3QDQdE-mnM0590n zLSo=mCpps$mbRJ`Rq)Mm-#2m!U!+<7<9M2wN=<*-t7PCpNs?y%dh0lEI~a95>Wsc# z_B%uE3xHAz^Ncj?7(dw)1Va!lJSSw7;oaf?H-SuzUWLV@`2nI{`z4YXRds!Sc!)D7 zVuhWAN9OlqRT_&!Gn>;($iHitMkm+<65d?E7=uO@OabYZbMhlB<8|eivrrJYVRHqu zJ5ygQoX-NNj|wYDnR$nM2v%l6@G#@5gLQj^HWnoE=jG8?!Ut_gVXpTjnmOFQgh&2D zs#!eQh1)fj3yL`PKnPbNSA9(n-op&NIgZ+{UkE(j?(vj)1;z!# z4PgAWWg`)k2oog>o{%S#SQ1$E52yqz!ZwEFm5skRPO@8ajA#DKLW$Q1G0OhUMfccp z-3`AJ`=-_sbnXUJD6Ar`KlO?#pJpBs4hSVvJUHm;&xt|>ge5ON+=sk}JjC25Ar8hS zWFWgEdclkZ8JIArCx6_HBfdq2;A~$3;a^oe z-L>3DMk@SO*DVe!coMHG$7}2PkFF2eTVO&;Q`9d8}JiB(MnWtwwlBo_kX5*CSwwsdr)3bJ0 zN}F&hy#JlT>RKx?rfl@F*sWUv^=wDmi-j)6LilC<4@3_Vt}oo+o7?$wc!QRB<|CT|`pBTvTb!*R-7w zk&8b~8X7kx-MjSlj#RO*|+CYgOCy ze0Pe8d*NF317Bzzxj)x^p}w3T5o#s-;CzMR?Rp?7{jGons8^r)7r#}G2{vTm2Rkb( zRC*1d4><2!gDDYaCVH>C{^FtGucES#-Tiw9s-BXnth5I8DrI$yg!+9I5=yx%*2*&@ zBcE2f*Bclmha=fgEd7|{uF5o-CzxVpKEb8Xs3IiTJb)}hICx`sy0SFZa2?Y;z&6gW z%$mbWq`e}PTWJMGbaQuo$jq=9ovUD}z4lEh#J}w&^INRCz1ez}XQw80SEmMjf8wVTPl0zk&uNYm1Cm|5S{a`{rcufBKimOjzkh zBvJeQ-8J)XhLico!G+zPUnvRbOE@Kc7>bF;Cq?x7`w~;|5ZqWCvzSw1qiL3?vRCF=f0%l5C5$5*{@t&dvXQNzm zYT$4JddcWm(Tn2YWR@sh?`G+d|A$Oqy7pX?96TwsYAndy{fU~Eg?)d^r-p$| zAbhsFv)(=QI?_CuTF7n;je*VJZ}J42Qph>>n|-&0$G3_*3BD(T$S_JwhZW{&MTCz}z!`Vq{)kkDnqSp!o@uVq{1ORKJ~!cOL9=pa${4OXdeD%z+P};@ zw{nx#F{J+JyhzThz9!VIpT`NFA>#a&Gw_qm0EyUUrH^{*QFuJYbd30T^iu=l9XiWp z52V6=Bx<^YM#L#PI7U-f4+$a?_uWIO|MpU7oZGGKIBY$3E!HQWALvRAPc-KsEQ?i|Sw=ijBHg7Z})NAx4AF8^sCy zFJs5J6IaZ`jQn9)R$fuS+9O-$D0o<(0ie4_+q|r5uB!pjW1Eo=D8KKdTt6HD&&ZPG z)@p8}%{RgaFT!b@{sTsfL!6i$X)-CifI{WqjPQ>YXKLG%!m8B7eO zBjV%>()mrFJ|a864<)F(yDh~9Mrp&te!v@A;Wp{pGT21gX|ka&h%E<--U4SKJTYv# z!^DKFgI~^9ClvHJ=?nNAwmj-jFuG<|grBFezIK8=4|g4&v` zx5gwQhVW=O$lF1Bm#Kv6l>VS@~#a|igeLZEo$qHHn5?oVNh>$gsl@V2Yvmzxjx zaHm8O&wZg zraD>x!h((8_~UDXY9m`$Q5m=CLZt^g0G5fkFD>+$)HVAQMOfc{=vBzPq7-wUsp`=! z)g%_|5mf2}&+66Dda&I3_y|p(Z_j<5-)Qh3GsKSaii-P)P~Oh#UB7GMrT zhA@NF7$tqmqIYb7Ya|MuA!^jp`D1_+6!V+5D$0_6<4Y1EA~uBGM!qMlpe)sRXK-A$ z*>-=imguB6QFw4_ogc;MO{`Q>t8Q;f+mI)}+UVGr#&aXgv39@6quyg_`DnJs3H71{WFdtA5 zL8yJ0U8n(>(9imQZC%Kh!$_9VNVi}d@p3V@{+^D|lH6i^y;0X4VbLrQwi1Wc>(I=Z!vd$6u>IO;G9N{Wn1KFZXWFNFac;G z1``6TT6B9dh>%q8d*l6&Y}qaf1rU#1HWrHr1kVoww8Lbh8E!1`^m?r$*=bQD1(1S> z^UTdZLc!CGpL1b$HmfUcC&zDz_=kFH8dD`8`NEN#N&TAMcAqtKRruCon;1aB@q+LG z=7eG;(R9dr^wDq0AlqZDd3vxo-d7Evq~r8ESYRfQZ(fU2SM)V~Z;};uAQk?}`**D3 z7x9X45VVfcW%*0a3h_4kz?7`3D|D9s*G;r35^%Gox``69)*+#+ceopyv#ql*JcgnL zVk*&afV+r(&utRKV_2gOP%uS+Ww#AT0>}TkL}Q`$HYo{Cm*XKV0Gk)4uW=J#%rr1I z6#4$G>-i@U7$(&JIJu9MI0d+9(U*|x2>=BZWpF_e?^t#38&6r3)z!&f;FtNnN%c@1 z1INTm47B$>*DY9}GZvE#PZb3pVYP(=)E7*YoZkd>ksy82&*Ijg@tO}%$}0l;tmul4 zUh4j{=>P|a;G;I_MwfD3dQq2*GRf+;JEjj}B;hN4%9N#|nOA-FSfW!#CAH1*j{dD& zeKaV_JoVePErne#c;>jdXvyk!2|$UM1_MTau+kL~15jzDKH zLg*xYqEYu%$66(KF?dRVfsy(Bbz6=zvW}9fPRfMU6SmA*H1vUII<_u3jPIdDJ$-$; zF(hn|CEanY!BD=WN}}!znUL0d3Piv+08fPU{^7}NgY5&2OhKiEG{MX@kS|7^PsdUB zgH4(vT_%anE6UGa{WBd%(}>gU$;q?bA2^pAncdzXG)KV6dciv}cfm@a0Rcc5%YR6> zB7hc9XCa%sX}mdSUC0%4nMDFFe75|HygCCIWc}YDfJ>G)Zgyjv%D2WHMH`w0L;__w zv*5JAz$$1rFF>YZ>>oUP<4z}?A1=GUcq|h_Vp$d~qfi~lE&(8%(C8ELD@qVV9b?Wv z*#+#_l@ab8_Gop=5o_1nW~pN0UzBKf{lC0Kk|*T=pOD>9KX1wqAeeqU{o>GpFwo@6 z=|n*!x^d(DV3CyCHFN484%6QTfnWmo>rh1kQ1e>#bXiuDSy!UVTtf_=h`JLXjB|LX z{_ekM=S@5T*T|KAR^9VxN{ZwuTuv!ZCPZ4;*`?Ag`AkPXGRzTvKtmnjz43iR z!!agrEi zlWOv3u=TkK$8KI=c?JZcZVgcEKtzz#@nD_7$&V`J21uINv*JLz5Fm9?vZVpUlnQ!+ z$(*D5X3&n1dr=Rl>sz1ivbQ-OjIsj(#zjy-{ZCmK=oV-hMEM>pP`{DF*n{rOR1d=Q zHJ4q^hpz13MaoG<)4*O^Lv9Xq2sP75HhgC>zQR>a6KTZ~5;1(KwzZAvNKyCeg7YLq z7Pvs!NrWK$F1s4rSNW2s8z6NbXj^~H_bckZ;xIILi|)+8N?|?SnN|~L42WN;0(fTW zzobW5D=9zohLWm^Fl(23p*H;J|T2TBuv^ zOqC1!A6d{mw1O5)RP#gENK~DHZeff<%yZ({@PN9zXVw)yaDkGC!51Dnm@ouG#m82q z{^M7sonc@M@efJH@*b8ZfX`;s-~nPK19koX6)D&ds7Svt0zDigfx2gy0vU$Ew}lfJ9;pJ&5uD3H7F;6Z8*QWx(30ggZEakB{_cl+GGLhJ)aSB( 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 zcmY*=WmHvNyS9`xlG4)M4N@ZAUDAzoC`fmAcb9ZG2&nW1r9n~}B&3`DO`hj{&pF=@ zhhuEko^$QF=De@CuN9%9B#n+jg!1g!Gjv%Q3AJa>VA#PwLZs*56HFZs^k>h=pUFyy zX?!v~%t4*kR=*t7mc;5nW27!cE%9JXRGCOZBcjAYXDpYJm2rn^6n^02=CMg;O@8}c zAxM^}ggx4vF(cCD&sW@}Qu>FyALDF2SBE~UtL@NBfu81EtK2!KaS1O=}c{I6F1j;CC+GIhFIPn(F_8gudSPt*=CY=3g^`qne({f_8XNt$6| ze-!@cWQqJ%RpWS~=f!?T&rGFun!2*ECZkrB^$^NrU>7;Z5SrRz$Hz+V+r6>|-v>|K zM$4Eg{r1Uw`^n-6ZrfP})}DJ8ft_sEb%e+-_T!ZK@GpZ3pjSOm7G>d!WJm_rV7zM7 zOO|4fvu&3NN&I2wLDHR0MCik@-`2&PQJQ4b%i*sfsOWpm@28|3I`(MGRf|H8FPmW` z$(iAkd%wQr^>@p7|8NrLmuxYbI?U3#M9H`EsfgQdp4~q+%3-~_btQ43(P}iBkgM2v zW5DI^ur(_qBa_mY7*@`>B_=%lev8d7LA6L~m~YjaYPsWM(s+)b)gcR=axOCttwMZ* z#i-ozO7|9D&yC{jiX>ST(x&tqWC&#*If1D4Px6H}=c4nRb{wg7R8rCL6`GYJ z@f6|;e~lEehIqjw3$Ft5a$h*dyb^vFib2XK>~-0+S&iWrQ*Smn(i;F*qFrkkIy8+N zU5i(E_Lln9d>km?Qu`p zkMpED0*5a1jmJ_ndT5P7CyH}}QqJrC!;1?a9Djdooz&;`%6THRdA1|T3@%6QJC=Ja z_oA0M?kfqgq=K0SBMDT}w~i`$D)9Q``S9DYRr#zmG=Zd2up45V&IlKVhKm$&(ddY7 zjI!M->hOhc-ykzH7W;XQ^UUc}ZH=a-m8+LY-EaOSbN^G_Is!&Cf4sl>Evk^0j}#t` ztrP6<%tNz6W0<;(b|!qwexX59mbo0xPPZqymy!rGHAb4mS%T8a@P@*iw#9K(#6U@E zQ?LD=fTj*fD$oBRjLerF^(Axo+Iu&lLhx+W8Z8yk4;DE{B79J3>f*yvH6o^MPLGbe6X0Q z(1d9vfo|_lms5QUd!eoR{rW`-kFW|X>L>b4UV9r{T03kiw6>_+tc?S@5j^=+=98t+ zmCs1URN!dki{`WT9sKFOT0yOwG3WVsxnPy0n{IPJXRF^hLrhcmEP?Ja#L}CW=K$_N ziC&Qd&Mc$4zD{LrtX(Rl7naCHF3-TJ58-r1+X!LW)Fn&ccQB55eNmn^}idR0XF+|nk}p9~zx`}{OFwv_sb>&QX}vp2Qb&6b}9 zBTNzS`etxpM3LwNZp4nuyadkXTkQ3cJZiVmU^vgL#xhH+sB`*CwDAJLDnF~?0Ec(s zi%%yjnSt>z=jnGG z@{I_%2Uw>FwGz3EywfGFM2ozwePqF>H-JdLpqOJAp zO(>p~O`;_nW9O0VMFl6;P({8Iv0rmqD@n&n}k(TWaxMvEmf3yZP)P0;o4>t3+F zwv6Z(N6UiQh}3N}VBck+NSO^p%Q~?&+nP}3bFt^`x_E!~xx1XK&}7PE*;+X~+a61L zKUKO{U${hk+v`~czl|f;bd;djqI;J6ZOe6MJOz==TO|^o?Wl3EZ#mXdWhv4p zF;Hz#ZQfsLl&kfB@3qr3e7Ib63^DcqOP6Dg;qAWrlOjFLhA9FRCdiJ{F9Nv5Myoh|ufyhskAJkp7^p1p z7&X{SRz}j;jvMFtmU1Hlgl~6?wwW2Y`af(8!X(-*cQh|ZYO2GZg2S^tMQ67fQtb6- zu9lD5SPzZa2R|`KEwzn75PWBAgsGPML@+hgCi0Eg(>^|r;@=FQaQ9iXZ_TiI!;5e- zb=GU>b;yHLW`^uBtty=nlQ2;vZELTX_n2|Mn9}PVTW7iMg~;wlDOiSZZ|7D@hEcsA;DK02F3j#miYkvX zyO8c)mE>6lju%yBWYv+_dBsqs2(ftRj&{#&%3atW(g?88nEeYh6uqy=Z)d*GEu?!v zl0JojFBDa1Ml1ypNN7^##Iz3zzjvn(KwvL?hd(JCE;bu74KBP-asd~!?Mc^$PwVX#8elEO^lW$sIEoQaU&1eU zwOA2?vj>BYH29IVZ4FkPOs(1)UL{MX-ZW(Tvnmzt=kyq{L=sug`;$S%iIieO%J|Q* zb#T5AjzQ{buh_dH_-%p;2);{I`2JFkp!>MDbF3kU$EmpqBKF7mx){QhBxMnXsWRoX zDAo@8ronnUQhulW^W#;cSm8?@?H?2-tpGT`G6dgC#Zqw1SdL{P7c2bUT<&zw+R0x_ z;2dvnu-pEn&jm`T^gW)mSkG4Jo-VFF&eBg64q-JF z?7ScpJ^v}5TM{{2t>-R-o1{xc6Em@U!w$p6+itFy$1|L%}Gi9)zaL)Fgv8Qw~6rH#ju&LASEXQ|67cU8h z2#M5SQ3>9sN<+Rn*)(?{)oGYs_Hzo_cs*RqZ8eOtChg>Uje8%65pmH}Fx}uqne$41 zWU_RHdyd9lo33P>M61Y&V6HYQZE5RK*AI-56Too}rf6D71pb5Z;JWo3TtD zbZ5Y3`9`G4E~^G#c`4-j-o9@{B}&GVG~UfHaPG%DJsoAs8dMd>U6tXh*<0!E)aB)L zRi^7ZZ(+#4@5eVn^68zA*i>MU*WE`1dz`26S1cM4w+zzwc&@PE&P3bE0C5Q9jzTE z74=^+83-j4cAS>Nn6{XLg?Zkm5eow6*x%{8H*WvbvSAXXwhxl|dFKkT=Z5TVtUg}0 zieLSV0|Ft_ua<*7tBV=tIM9@-Q|i0O(8e$x74Nrk{kT`c#p-2BT5eex==F4|ZO)BP z8o?4VaZ|J5#C3){oUCu?YHw=r{`Jn}f)FDbRvVdsi#a@!mlwQX;S16Gy5T&vC^~Sy zv0{i9uk2!!b6)cl(pesJ*d1~SrgNA{T^fG7v?CRp{_Y-A1vbhF!ap@I8EI^* z7L$%IZ_%*2VeEJPjSTV}t_*&9Jq$2~U^6KfrbI#brX+qGv+e!?1ZToTtqo&A_ap8A z7tW=m&+o9pIR2i+${G9qbag(4KCD7B%qZ-Z8?%Flu4k0r8t3WKSe=uzrp9FRQRnUT zA(DLvP`PBapQ%WB!VpXS>GcpW4g7}WOJ3w~^WCI35m@um-GPVq{Ej|JjA9r#``G3F z4=whK3IoE@2J4u5l;{EeBGRA!{oWAxo?Ex)1%zVz-i5VT$En7C{d+{cf*Xx&%9+P! zp-ttKwV&K!zqD)g8NlLW5L)<+aRr%Q4o#4>dKy0FR=M9v0$gJYBs`L~i;Y_cn#m_X z8=H#~zg#Ybaobv+WL(LmrQZE`CGh3!^~naRqFVQ#nob4F8ysaJEY6X~tT~HfKeWb) zKy01x&&pZ6W0?5VDZ~7N0-opAgs(q*o?(3XSuS7XSEV+av=#9}o&ONOpLOFN=j8ST z!~Jq{?^_~1>c9v%tQ|_KaeILkic8xjBYG?qZYf2h4mfCtFX{-y!*VAa1wIx zI|!;%e=ALn!+w4{a;)$%kdg}d;PgWk78OH&N{v9C_HlhH0xF6nN6Iv)?n*|L~ znJq}H?-fc$ng9M8B30N14y7eBvBn-3oBY0i7_FIWM>GT};Uhjc_CnO~)vCti$4qEu z;{F+g(jRqF3v4AbpZlq9nd3K__D8DK=nEu$c}6JaS?n7B@e5!YCiqyS?%c&Pu4`rcmT>L%Z0M1+wjIf&+4rcs~;E!P9uvfLnB8Zb;zmZI^@Hv@TW83H^#mo%mKO z{^ce@gqUSKQAE>jgLb8sqRmW&Mc_%cQS=CBNs7e9s}N!7w1kCMFz!FJVO_(t3$zCr zoVoH@y=+Q9e>YS{f9|brLny0ei#dAcZ={?x`gAy+vGzrWS&$$$Z8&|P^=G}a2`thi zxwpK@eEn{#vd`af*228kKXg7DT)8%I_}Ar`!R4~V?Qgf$7=$H%Rw}sX+~2p8d%Xik zRf*gXHz>(A8ao44##tFVb4W@WhCdL#pR&e%V3ji#8HijHke5zmue!zMagMR4rSYp{b@N z=(-|mztDnpMVRZ0vR{=v`&m-8V)}=bb#%zKrhNdHPOA|I(Au;OQ?FM^qenWf?J*u7 zvJrCl9CI0)-)+!@^~lU3D{u|7T*ihQDJpYHpnZaUg)b1Wr~3u|lVZ5R&&Fbkz^vX< zDhhT@b(#E~;AtAoGbH5sU|wRzfbv|;x81ax4&}M;hMv)VzEMF^z>~z;q|n`uB!l^0 zd}EXvO8znqJ-Jt7O8BMOtEjYdO8;~TXjH$k#R&}@6?=6>QopLgZc%fE`ddWaUWXf6 z_G(*#HEV12Fp7BDXB@+iWk>OZFh=mDDJ5KRRod6$J{uRDtT&S`LJ)P?l$m-F+mg>35ZZ}?Yw2e#&>h@k0XJdRUU(L-FnEezoU^pLoI^ot=NWSjEm(| z6f?wIWRd0tN#Cb3#t`vvYPJY|+}}Ls?PfKGpN39DBVEcVk)!?H06r>0D8|dN4SN{W zn8PEw?~XcYovL24!0!9)`(+5#$iQ|2RUebh8qlxL!^=$nx6b?KR6m5=_CX7Z(`Zuq zsNIJ8QqDNrUcc2L2Le#u7Q=2d$g%50O5hB_Wib>_(bA>1zAFB3yhEV{b(J+X7drbR zz4kb*uB>=Jm{=Z^=X+a@yvv0;bsLxQ^Ax%|13fkU{J4|YJ9I_)zRv1L?qfFx1xqxk z;4F2kO`^#)T*ae1|G>TDrR-h!F`PsZ5cZSwtOw&L#p5w)$$%%|LK3moQTw<>K^ zpF_4Qwd?ta*HQbR%#nY_J9h9O1qM|gYM;Rh{;6t=o|O0&ik?H2QKbFlVpcEEv_F%_ z)&)0Ut+N^orhd`m4L^|42mmw_;>BZy6rUk#JIgFgwTD(iS*r$heNlM3Dh7dIyUf>_ zH2B=P8HjZJr7At4%l%Y{M!??NZ{Yb}3{2R5g?iD$4Qsp7)&4A;*7~(OwHsvwKI^-t zp&La{i-4yq+|iz{VA8BeUhsj?bhBNtCS75if1OAF)#+ZlTI%xXdm(zon*Vr(6VMF= zHe$zzy~5$jBOe(V#%%8Qi4$n*XQ9vDx$gU|)Tu*p7bcLK6MXXoc=JDN6LnR_F4i?UyrG$E39UY?glYFrSGNv>T0@#iV0fL`F4|rIL zB}`ym{t9RWZs+ZO<%=fARl|49He0XyNP5gxx;!}Te{l#deV*=n~GuG->Ji?JS{cw8w28 zXO?<~3~tA&C31K;aE)V7nYi}zN%sJ>AqGsrypE4^ik+2W})d zgvw8j^9!NB{>}u{zVUUxe>!GxT2whv`erB#Y~kJj2c!B^9{(43v-d^NWv6fGlZBF~ zja~ge*NFsNit8AA+3eY$Mx~KU=6}PQ#1fR~5)DK_ru*xSXf8-krhscH8tH2dty)8S z#^6QcyQ^b-m-Nr;)!XPW1CvtFpx)OXcFDE%okRBKm)cz|z6K+o?pM~zovinFf8<^3 ze0nw!NM#YQp}cL|P7Wx4)N(Q!!!)exhk={%+@H5wt!kxT>s~6Ffa0ktYa4n=t~!g-~EYNgSjjY zoL-w#0kXyXdepw(%j36~yA$HP4omcLK&R%Og${+!ufOR)-OTH?TMp?0eDBHZ53S?1 z|7AWMY4qtgf&ldX?7{tY{!1|77#vmUG=LJ1(_y+ZG#+``$ivf7>!A0qVxg*aJTDG_ zyYNzj^BSu^{+ia_kcoVVD&pEWmT~<(UFE$=S-XC_%cCH%6Y9Pn z@F>#c_jI|9{$^xdFc-U{%|JC`zII-P6Bu}F7X3vi_zdice-1$Tt8{lnHDTK0`H~|I zVfJH!3g|;|L~UgHQH~5A$FiB$Jn6pQQN0FKFg$}{zaVq-h*XAW`2Tz^53m(wV&6!$D1X=_}MMjI9(HWaJ&cA9@t`fucfP_50)aDI2&B6vJJ~0 zcW@c7p6V4R2m9mkT3^ssmgAR+^%ji#@I9}E1`Bjcn?CYz3f_!+C3sY6 zal=jr>Hljwh!>zB0Sw!DQvt<$V|>pP`%xvQ6IgZQ6OekQgf>e=Bm??pV=NWuXmr`F zkzq6j3&qWxwZjE)6{412{+6bGfk7s+G^AIF5aoYsWGOTQjU;D(RG%tU978)O&2kut zwv06hpvCR+2QKb#eXjJJ!9~y4dM&6RNtO^7`y zjVO-=%ofJ%&Vv(X_S6xO~-r{Y6Mg=Wan2^s~+w2htmnB5T+h}7_?4qYF zTBGTBFTM8@%c(0PK!>s=&!$@9$Eo?c`38%qZLg3Q&41`NBcV^A@OEYHeOV4|S)Ol) zW;4CPi+4kOZIpGm5vn@85nLRWhJtPfDyJw5d-vQgB50POh8|mZ4622}`5!Kp-B*$K zasID&$(syH)EeTz_oY9Xy=tSfP2c#lQi6L$V7$hC3r|W$rS5#Pw#*YB;v&zjeGiw~ zxqcX9el3`H0CnEtXsP}3g$BIiZbYwIfX_5ssX_+!A6!&5n%8az*3&fH#$*A52ZDxG+vhn2^?kvyEmKO4*OBP)=}o){@bIf75_(uRsk8> z0N{d9)VGVad?2n9quV+0;ke^ZO%lG5x2jw!Gs6$zt85DP=pIl-V^2OKT$IGa)nU)r8ZU2RI_xW00mMyh~v@gxce%z z=lihBGAtFlzl7v7Y1r#8K6meEB8Ni1g=0|_1N9WzrlCpcQIjVD{R2$?1!gloPK!$I zTHYl1@WWWaqxj024#vx%;ca+gu6Z`!6V$;6qFIoPdf~~u9GdNADSOp6Ex%LTP3#xy}|8Wat?kqK5{vw;x-PXD*(eH2dSVQ4^1hH z+Vcm%zAe|l%$)&8O?)nC;V)>IVl@37$6yYgt>U#*Ugktc~S-@ZnI zm&zPE_Pr9MTIh#bm1jEy7hb!eW)7Da;Ufo>h{hXG5x4<>ZuqdLrjFHR*zLK^mN9T( zs#T?{`Hshw z3`Qfbm3t{z6U&ROH;>Pr;r)8b0x(8ere#vDAp{iO$Mp)x6UiLRo5eM+K(8r8fswbl zm1e}Nrs5l2C<57MKmU7usW#v)i-Ii`OSHp-+JJBPsV_Uv^5b`SDhmeKAY9NgFy$gN zp?SW7Nw_LHkeEn>>kSRjokeEG8EUi~<8%@6gWj#asQ*yvb>71S>x*UV@hxmrZ5#Ac z(g3B`JnDh^{=vx=D7pu}>nK3NJ!IIxYoMT#q+fY_hvXuy@8qF#EEx9(pWru)_DsZg zl;%^P;0DxlZ`oOSMjuA8ePREx!H>7KW{>j@PgLL26U)`L!K2QcoayWVHKmT zdaVT@Do6==1g9Ce>FU(3bsBJ9XDly)7E;YG)4hTE*GRn4q@wkP>1J z0o?42z69dTRW*32rKmsQwFzi>4)OF{BNCVdq@93Gj-4hRYVt^uqruZEW||M7u8)vu zC=9Wb4Ub!vKlm*M zX24kx+cJm1nR(p_l6y*gEIy8}le8l7iXd1TMY2QaCwL@|>|4XN@yE?{k?jN{Qf=EcHf_@Vp)>5_Qv^ zz~DBp7hfNi8I~cDg!(7Z6yeOPs95kmFW_)BzOf8)UdtkX-L56uJdZ^HC-z9dRe!(O zC`(FxsQnkI&4BZ@2i&>{CSmzA$WTL0+z`e-^zo`k;?GilVy_deVy)Au>>kez*55|+ z50Tq#&Kr=)L}r)p1JI5A;AxvbhXt|HJ_&jug4AS?MHIyn08?11J-;b;*(0waFGVLz zgO#;FP#6`j(_-3^ZS$Kz*<`p>>DKg&r=FJGf94z|Yk4%+9o1}jx7eN9gOk`y8-r5( zC%K&2x2Wa2;(;hLWn=!JQf-MF+3$aJRhbEM$OFH>;No?0r(~<7J02LAUbevB0ZOmHN+6LdArBwG!JcWDAaQlR zQf3Dhx{G6BJDz|;UnaW5B0V%1osrdIBpLaPL-)NP2mEtSa48;H!+t>vnB6~6iBKZc ziCp5PR{gti$%cq{3DqAGSOiK%dw5DBIp&6D8;KLhljdVMyMyU59y2S92f9rW)R^WO z-0~y=9B;r_+IWX~N4dTTDs+xkL7Tb$sbPL#w1d4na?m>H)e&KrZ_-bpeS5Hm)5dMJzbt`=b4WO@?R z2nt8^h-Kh$DLHV-%eYbh0Qm{&xxwFsfE7F!pJG~HOY~Uf&;}1s3Z+>yJenO@VxUx0 zHMHx6fMx57XJyj1nX{r276Db^9$x)l`Lo0h^AEgQ(?--kl`G%_e7W~fIo&8Gx}{5a z7*bu~2YTOohCCcq%1d3DNt~dEqal-qqrH{qtC&}Z31?i8tuBe8 z_{%~D?S@3A$`AVJK}5Z)yeu7zkz_0&YmAl+Hulb!4s$dI1xyuc5vlCxYl0KDXdzBF zc81qk@T0o0W`AXB*T@fn#7JUKtv?E4CHzMCCC$ip0h4erfgGTFDzeL*oi$CLOJ;8( zyT9`>xT1(qtm#Jgotlk3&~Fh~{19E(BGb{k;~q9Zrc(eDNas92WA0HR@m%il>q(|p zeJhv7%Ca?*!bLM#j$#PnTk5a60db$q7YnlPVjEC)4&*A?h!fZ*=oiR$W<_x|HP`s2 z6zRBw7J!BNX|E*B9H6V^-cUmHe}i0nlV9L@DVSuUU_!r>bIG7f%45ve81<~+S{qA; z^(4zX&Q@h$MUA?V_WIwiYI8+4vRw-;AG~yJ>LahGzIH1_M(ZCf%k`84b=Yj^Gawd| zT^_FLxL0i(v1gmidwi-WIqMy}%q;qCKjRGn7lCMf1XhxFD_Poe+?`!%IS$cq4`AbE zyzIw8(pdpKy);=9V6ylX=l-$tuG>H~;ghna3P_Y7T*Zx#blqkBI1h(=))h}3*-H;X zQYf(C=l_$}l0G&O6;80T;>;UOWw8z3>l(>7uZEKp(s7RU)xbRq0p-GsB1b zi>^l=BSlz_cNIsmr6$$$T9n!t|`l5vr65x$UI=cPU1gjS&!Qmd~QH2zpjO0du9F3STxb>>W z_?Y~^X|1~crzL*NaTV%ehjfr>Tf=d?3i@{!v+7aDZz+;0xXyNd{J7O)9G`d*V0uJ) zrUN_;{c<&$r0h%$s=be38Fgtm`UO0X)gTWh4#EK(%_8gJRM-M%BcdN5-!Bgr(^9sI z*AI@xPhDC~j}V%>u5=WQ;dxZ!^nt?*%^fHXNoCQK13g(P^aG~x3BfSaS7_U_*aVBi zaU!>$yFe#3;>q7-g}nn?BJq{5r$nM@0l##R>+LnucAtp@O+dns_LFFwqX+h`k}MPS zW3f&?Pw2c+`fyF8D>r{xT&?LV=4~x(0=!_*P{kjm)~qc~fr|W}+}7~7U#i*tc4#3n zuCM<_deo)sNgHQF-vOsLp=9`@`15ea5tHm3jcmWm8g^%;E0cbqPmpR#cBPdwRLM0F z3@hSqv^wKT*gvgazATOmSX!`>VOb{MfQeEB#Y=W!({vj57Mg>c^whLFrG2Uj+A{i_+`2^ zYGC=rwk{p}i1>fQUKW=%|7-YuVq7TY7j%Cm%3mfb$?<~htO{oyl(v|GIluz4uXv?v zyFfA^+KnK+ou_|6z|_}C$uH9MmB`bOjAlhAc#_LfAdKTd^N~)qDxb1VPdz(_Y8&z2 z`!mbcgx%2B0X0u?yE~H$eh8AsW1CvZl^EH`Wj9rO8t8ia5b434Zk5st0t>W2&dhBU zMb%q+xUNUgjrhaBk*t>R3x@9h3^Dw7TJ&vQnmV9zP-7E|D`t+u#+FGBB(T}^o2(Ny zi1DljRY*I2qK@w=t3rzUgeu{+Dl`}x@6v-|Nsq!t7fE+R>g8M9j|~UW>BnOWUVkXS z&z{OFOqUMwm_?u7kWXTm$aTi?adwtnMn3+s)!KCFFfiN!Acs8vy20J80-igcRf`l5 zih!y%mw4kmj-*Wm3!T z7K{M1Ki%ciuxQm@o8I=*U4C0B+UEDyCu#+65#EDXlRgMMtVmM_3r;}FVyXSOGOGE- zG4lK#+i{t+ARm6Go5dzPg-_hiESyIDQZXX#Sf;Q#UjKPNnRhHA96GuVss1@)|z^8*&6>YHWOQrD93m zf8oJ361m-_`uzY}$CSV=cxj_fS?C0UR_!A!kljzO*qoxk53f?l;M~Tae`$qq42Ou3 zzVMQ0kM#8icJW>ZGQIupJa!x_J0Rbd;MnuPyTP;&?)sSac+`0e&(UX<>oHJ4*bdh4 z&Kz#r$oHls+xv9bGPGZga%=G(GmS}mJiAPCJF{?t%=>RZeCxn(*A?Nc?U!d&SOmQs z{Vb}561*p`4;Fym!(NOM50H%$HVWJVcd=#EAxK*faTP|o(>CJmoL^b;rNkWuAif%! z&XM_N&lo|TLoz%P#senhhZAYW;z*&8L~OD=U}y^g+txBA;TGmM6j9f!Z`8QGAMCAx z$p9k+y_mTD2)bPM+AvySb%!hngRfHUsMacGeb@DRlm&py?eJv#Z3I!atKbDk^Iz&& z7SlxC(8oK)=1Re%Hh?QXa)nDVm>zu}Z+60N7-N6A1sTmEK|+nn6|6bMy$|XKqqEOI zs&4GV;&azCCJVvwmhmqHR($-6yl@*ne^-4UZihi*fiioHI{XJDXRHwz4DY~Nei4V4 z5<(k3wHqv6HqGUMZKP0&&x=;;kx&+WI4>yYmLt@VE1cH5Io+~fV{7bEe2W%cg4Sso zh0n$dW3dQ9AKyE62y$%fc!IZ+#iz6p^MpFD`;k5loSCH*QrH;oW|iGv=hk$qm|na2 z@?mHn`|kISr@WS{ai$TR1{qR#={f?hx4DCxjoo*F5Q+=d1%$h~o<|EeN_#GF^m;nc z(`x~vp}%UV^c^6y8Ujfa<45;NS-N3hcWtKi+?RBLPi6eYCP^l#8w>HB0DY4`2UH=(;+s?w$koxvSwI0Dft9=-= zmC$O@X$&gj;H1>U$C}<4Y}JZQCVDzVRZW2L&#yo4N_Y2jc9l|gj(z@59i1=%>pg{Y zw}QA3BNw<%0@m`W!abFv(oET>PnA;szfYy`HJc|N-gv2^Xl57n{R1ig6j=?vr3Z4a z2^;PI@6#ris5`MsH5Tdrna>#1?WtcLM~DmZ-EaE^i2hq9wUDD(Z7xiA;10`7oBliF zw?Uylps`ow_~k|_YVkFJZE76gz&tziOPT8jBpm+-SO_R>c5xGKYJlrba`6=P6WG|E z#kJZAzxnqbuhXq^dUq+M+2Wn0erZ)3!}GHZVQk*toC%8;^IL_oBK>n8VNvaP@RyVF zY=qqo82J@=(a(k}L3BC|SW`<}5&#}|1OEl(wkH(*P!Dprmd`_j8{ZkitJoV``mbdh zsb`}~v&;NDT39;|{J?3rE&-*jjR#i#8bTvm>VmJLGb>3Sx${3*_iB37iu_9J}%{a?1%NKc$%M9ARN?+~e9yo%Y*7F>K-r^+uk#sBx;esH;c!HSEu2`f8 zd%B*Y@rQ(t0FAWV*B@=zgSQwx2^>NBrM!H z6zN|gc38qAhLvZbo50wByu*gQgFg_six|-6O^pd@M<12#U$~Rr+EVIYLbc(bs?#ve z!+8XKy@-#I2<6zMf^OXV*s9MDaypR3Ec+K2-u3C1rFRZ;XmQnPT+N3{wVVDYw3Ry7 zY^zw25C3@~q#)b=gUIGe zjYf9&@9iDdejzT;dOG%wAz8oYUK;~3ldX}?Brp_X9@7G{{H!Ac||k+!%y^eW?b zX#HKr5FAP4a@GbfseEtH9HU(%Y)=LZEcEE(w7tah@Z|7;7~(AS=b}WH1wC~?5b4K7 zV9uR7O>^;^B(QZVqLQ0Uk@>8~Nfv-uZL*$to5|E{)0{e+3 zGzMR&-9myy^_-*DNgmkgw-Gs%xdTc%@dO3$Jy{I9bW&LjY#0OQDz$&yR~vSBEc93D z)E6c*X)6H@Y(IoFx%l*A(^9+oljnRu2}G+Qh~83x$T_!P7T^p(cW`l4vzIs)LM6I{ zRh=(Gv+_D!2+y)9>h3WDX9-{?0jn4RzizYfhe#3-;DilKkyHaJ$vupj`LjST5E?q(NreFr^Uy>z#vjpQP9S~z_bB>G~b=^#Mj0q~Aj-3B}kHHr zod~*twYOedHLK^V!p$Y!J+bVM@dNP!2z{fZul1$=UOG+II%L>PS8E`5XE@zYcH{kV zNqQIBgI792$h8ag`8W;AGvgi@KI3{;$nmt`S^VZ$L0?va375;}XiN|hEQpX&lYJeJ zf)Ro12@&;z?``Cy^$uq}vY0HlDEByX?CI_OQ17ypKSwM0raO?@gd?8osrEAAhua4J zm9oF!eB<`-@>by={R6lxNkp)6bq)ydsm1{{Fsss~--(>#mX2RAt`b=Gdd1Moxtm9&8n~7vq4Jw$ePq-_zi525A#wIx!Z{ z^TU{i-%a8xLa9P~{SSY1A8w3fsVDLC+t16?U7v5I3VnaCAOpiBs}|C|pU91E?AJA`y+bah;=u3k_Q#mf_{@Y=i0)!uUnn zs$$zQsz@+q$fnE1{ev1jU(n0I;YrYcpbcuZ2> z==kQ%6&s7^JuRRjVY*fE@)c2BfbIBug;xUhv&sAxp@l|u{1mw1^#sBG-E114RGPi6 z*7tJ=X!}y-d;&Bq_UJH;Li0?Uo8YfpqK!{duy7NkJElx3UJ>z3h~V(0AE}_B#;4Aj z4Gv44!&TN3GA5x81j2Vq2a_HuKP!5^@+{Vd9SfX1=2Fl*v`kj$?XSYNI3;6Js_It* zpTZ@{Tog8m#XM+-4L~c~hZb0xMIt#|SYN%D80h3S(7JL62h1 zk@_?XmbWI}b@?I8>$Qcabsaqxle@1Q$@!@& z>%K%jvqbDx>o4*{QV?qm9KxwDb7FSJoDkKWkljLU3~j{eUVKVvcyXPPT*Gp z@@xd-IX!YB&GXnGF?(gxh`agHv8wM?q>3Jb$k>c!d+0&lJ957rT2YdbB>$fhy8BUh z;x>s9uls~Nvxdc`$dK>Ox+6LYG~?$>W{DxA#@%uU=(OQEUZ+ z!H_D{<8f9IclhMK*M63GSI#NVkGy+zaiUjN;Y$;U*C7w~;oBaCZ(-qm$`BrL@#zt- zwjnnYlh5$RbCU9VT$%MQF7@JF7ayHGn`(_`jX0A1l!DZL|#fVVJ-J*6xB@n%h$xx0uA7j0Mkb={W@!(l> zP^kU{2y@F8G`L|wj|3iC4(jq%fJhRG0ZBfehhTMc_}lO!`u%nxFFq@xZG9^%ER;3H(S>9dAsZf?#2tIkWZ@H$<<2xDltq-M3hT>Q0WYr(D@hOk{TWA=3KTB@Z`2=&Uv1s+RWBJ z1=%mpPT;fCplGPM*VziSC~`Z|LEL6rKcs!m!-qD09wF0HYQussd zz|Q#d8AJn?83&9J5$tI2Ep@c0=2yNtKCe5)r45f^bzx}W&k|GVB^$JIR6WcT{D$TS=g>}2ejG$Z6G`wQa2bFUS5OqLE0Rzr)Rty>6! z#pPkQB}WcUpoHmC&8Uw*v22%?l=dBj?c_t(u*!-V(W#524%5}P+C|R=kN)0y)FHYT z&boNFp>%=;5$qXg{3*>vk7zhZPf=Yho{KeA-1QlwtXbP@&p}_yN~tw;;5Rmi`1ZZ+ zw#&txd;%c?J%KG&n$C74vBVNWyo-BVP!)|ZU7%P!`A%)hF>>2x499g$Y=D0$oLKFw zk9R5Dvp-$eKY%W4teQ_R)!3zcHF1QGMlR>CxRcma*L^iX6|~lK+ladC`hsd?YvBg1 z4>dz8JH?X$gi*ULc~B&+99kN z8kMUQGvcW^f7&2g2W3|32BAdP1FE)w*K$`oTb%~;6$KM135cgZ-ur$ztfj;w!9V56 zc@({T^x1t^ORrZp+io|%$f@ng>P|JaLyZf>96${8TAHkJRdqyPHjpnSfnbh|D^^x27IWdD&;dv6jMQ`3d%FH+Q zLGL*ygU6n)^Ul=Mde`5(eRjkXqb1GP@9Qph8?I7beK~)>nq-Mh&(!TD&xjR5in@&1rtrROh#e<1XT(URQ|_1hBH|;&DRD$A|ZW!QLoFDHL^uy7j&sFE9gs{%MFLrA9 zT{d-}(tTz^(O{0KN6-p(Shocwbedl8Q`h}&x^Q-GtKd)bzOHK{H5E8z3aN)zs24r2 zG6x`2J4Z7$x4reu8ZOgzz4L0bujygCd+pWnG>$L~L_4cf6;TNt zaFeLz(18!Mx1;&k*_G+NP7!B+x)>f);zHVgiy+ta(-k0fi=p?HXPkaKorwG){ntbB z7y78pXkm;PmNr#0i%i~ZkHfCOfHc_DQXX%P^~J5VoH)!ESP!O%zH!xH#HzZ{HM<6R3V+~in zDsJ3Yv&i?g49eqwJp?~;@t2>@#d}#Z|HWaZ)K2B(X*1ab zcJ6JIWYDWNZu^yv3Cfv!04_j4BlcVx6WkhzL#gZUZzr@;!=}N(h6%is^Lv7YSjmFw z(x5aV*rE{SVE_w%fl;1j497PG1=sS$@8*PZi@x*8s--6Tq}z=84j9y(sY1wck=Nhr za3owg6k0ez_c`4(&q>mzYaQxd|74O^PW0A~k~+_=?~D>*=Z*5Ig&Hyw;>Mi5X_+8K z(QaW;KRVr#2H?S0A4WVZ0ieoik*XSV{n={rm@MGh$5^}|uvuggWTImcdf1*XypUpr$9*^vrw64Ohdb6N02 z;B?~1LfwLA8qg}cQOTLT08f~cyfHp>2q4cQe{GCj?C*E|;8z2m1a)e7ckn;JTO_bx zo@r8^!=ISRjyE<&a_*6kCd#I;Ft}~z<>=n0=?{~`b_Vm_`aL$uW#+*)+{mGv%o;q>jz~W++QKn7kt%gk$2i__vk2=QQ zT#)L^g|(+7O*9tyYj@CL5|jEvVP5xqwKr+on#Y?}Di-i2P=szmN<8xJgoz=as`ttHa-HZC|K z_TyX&DjLGUne7oo4yyKFf>SCpP_c9#t}t*=TR5C2@Kpi8h&KO$aGjLCeIi%)@!Q7OUs7>Wf#yiZAa z&noHmYs5zx8FrKJn#Hec^P^<6c)L1^H`zEEVuegc2O{nh%2TxsA$Y06z7i}Ql&YYmZrSZb z{#+f#^J=MoRoU+IAW^xU72%F;gBald>_jU=BAXD-PVc9v?tss-O@UddlS-qr{pEZ4 zA5s<81zGeVPbjTi+c9D+DRu}qnt3=dHUJkf+Kjq?Vl~2oaBtl2Ki}bNf!cgFSYxhT zZ`Mc(*!eltzIChBou8jycTwM5g3mbG0S96MY7NF(+Ek8qHL;m~^{&C+e^?*6k-oY* zfLX_$Gb7wfX@5vv6!xx5nspM!=L){|!>;+}enMq_`!}fbnidY2f@um2(27~STWK`w zId3UgY!b>C1YSq?J`k}Uzi&14#ka5MVqyjW9wt#yQLcmqKyB!D)pA9wyLZcW2Vh?p zDW-oW#m5lkM`T2@O5jyoXEFRai~{Iyk#_#m=?&gvdn;UyY!DGp)?jR*;15XP)KOwR zx8P+`=6(OXht}ra_W2rTG^SNbz|OGTtn-M5HYfq&iSOC?RX!~Z@vBXWZfP7-6fv}+ zuwNy8b|r2KBRDISu3xlSr0_KNTeNW~f!nV+n* zioI{rC=&S0?`f5B15&%-S&Q3X0FI=b=Juq^kJizrl(mKD;tn8}$J#tq%HDOcvy1EvD)pD$Gq&FOQ5|Zx$Qak2{w|4yp^SxD1tA z_huB?H9lo>kL+ptpKPgLiPJ6RZZJR$4@BknP8j8bx3(VxiYH-Ap? z7Az=hr=Z%oa@)8^)AP#LUzzq8t8cSPW1&+0y1jlk|CRds2M-MR@4*@mhitd#J(_-W#YFF8T8Z>g0$Vm5Q*~ecUp?uPVQRc z9r1`}YyFfaLy{Sz%PqnL-i)do|DH=TvSu<#_c+@xe}D9*r@ud3gltzM?K~&Sg5oeL zAXR}uDg4e?IX%tK5(cJDOwY@`|6X%p-{Z}w^~X4R%+STL&Hxb)kutZi$W!r{oSZ!W zME>)`yLa#WP+kBGp*XO1A18y(tZq6pMoGb6$phdxI-nFvk5zjn;(hJWdFQ8p!I1W- z^aVV~80>1`ddK?D42!uYPk~^xo86wl^RIF^Gyri&Jikv%g1MRI`3;`JmP>ryCPj** z-ygot*HCPdI{MLsA8<1$#2M74?#J6bef-C1G_9;bNe?aa6DKJw@t*umSqOTL7zdqU zeUnilF^`3qQN3A<@-xwJ3x(g)h@zJ~gaoeW_xY_HZzJ)kvD%isC2p}1pt%dHkxl^=&S#XLl>Q6Cyk}ZgnfcF)0$a{$v53y z<f_Cn_nvi!(>%n+^#HX_soEyuLx91}hYCCZ2xhWWqwl`|Hg_orGkO59(8`M8 z6Gl!EV#^N|qaoO4Gi7GMobvcHBI;w(wbmx?J5@IjVdG&nSs~6ve$~>h#{14uXyW9*QbD*pRkF4btt#eBC@I>B~KTNIPWtj`~>h zv|WS7RJCnEe;{c`I=!%6%6tLIdn>S^ICV(xgZby|Ofth43fzOx`JGKThKYHB2$ZgXg1oh5uP_ zu4kDlP*FfDLGkarC3Q;z1iK>OqcdN+!u=~%Uy6CLAt>M8&t4QpZtEurT7PUj7!(K5 z0a`WPv|Zjeidn%KKqR5@o#*K{W(2NHaKu7e^)FDv-q0~{7=#-?kp=N<;WV%!Pu#{s zaMpFsb5ll&P575vhE@RGt1D&%yBn596=T~g;}R3es)EinP9#~jYN9R53t^jo&FE}b z=eV*A#*8InRpWpie_(wSXEjJ+OjrTVJGq2!_UGY~t%=9gZ|Asmax@31OKu@pHQv2w z^HBRujY!V-KAH1w-kxpHgB}Xcd1RFHeFIS1aV1{w97ki=>pw@S?`=B6eVa{?p7sHM zwG0zfXHFKf)fQ(UXX*DU^;)n_zeenudLG5YL*YV1qyavGJk^}ZIN_ZAAVO*GVee-r zIlaL@(0I6(i!QJ#ziw3u=lHmX%>}rsZy{$-#QtgaMJ9Y@{;~((=|1jFGu5k#;DjpY zfA7Yf2Lorf$X8!m4QiF?#hzP|@K|r~Zh;`;Yr;!kc7V&){|A+t@v?;N=m)*Y`0zhB zkMVtLIKwf+r&7zy(kRpcEeICq!2bjbY^Tjh?-y;Kb$&=O4O&0>yKP2|1Pe`_PTv3A z_OCC*ef-S@N~A>gsv^o54Q{6~N)wJ{0Ai3iI8Vnnx6|Giw}#gN7W;t~3-o*XPrs_p zO!w|RT5;(g9IP&pgcigkB(RHo?K-ju6$cmn&>`Fp>`3f-I||CYJoHtb|J}a1=RnA7 zRgcJzAY=Q`e5b?C^*$F-k_A^z^$;@zlavQjxPc>(`N{uK)?{1>Aoy?GqQL?4wO+qf z3^Db-I&wUjb+wL*dY^f^zs`y=-z&en0~CXU=tHygDaf1oWEfqZ72 zxy}|8t{~B|c0J^}*`s2De1$No2cyIdPHTgo1k-g0`C`i2-~GKh$#`g$W~p}dh|nz# z1mmK!`2{D2hHaOvajS8ZW*J~Q3uXoTmHu~1s{Z5A`Vrmu&gmVX`D{n=U4N>^vi0CH zc*smwk@VeUxaFG+2h!#7*;?8oa9N+0`w;Ln4k-=TQz^cR0>WBP{?md?z?CheWXe{g zU$2;k|C3->Z;1l=%H_ZTNMu6RK_w#mRZFiXyJMK!g+=8p6|OEk5$QJx7MFw#ISGJ8 zJRp`ubLk?vx<5%;4&JS5$UY4N`A2vB_@C}tD}wHjfKr^g>C}PcuuVW zb|hyHgM?Ns zi`|(zMB1AdtIAgd{n~Z>PspkXcuhQy#(E90a2XMlcT0DFeM`O`zs=2iS#eLVSpDju zz3mJ=8DyFH&8F!H zO3%#WIO5T0xj;XF7?RtN@^06#KmM%CLPu_1trQM5dJXh9yq{wr)Kk7rkgnZbSzgXv zcb9lEs!Mh&RO>IHJ~m0POxrlN>-x}FE)i*_Vc$%%Od=*zaJricChhCw%$tEEh`sMf zWb+3==x5N=_4=GV_-)FJYnsYC+$4bkw&X)ML0SyC?G{>Twi@j>Fz+Z2lK%fHuuH#_ z+!c9(1fYE+TVpBfPI5g$+hH?JwP4|wKKSTT1ymo*u2zNTE(W=XjXv3xv zd=vLm>zeck=)wQUo1M4IzLIBCXI&>X$sKnBq}6dxY5eWCqmQ8%gnCUNKR$`hqxs`T zK<*Yd-}^-9?#9vFj{Q(+|%5-l{pArTJ z?DmZppxQPI$n0DN5iqZry$mIx#F-f*gL3nbo76n{Yr!xzDT&6YXr%;!DSQgz55(yA9_|)KNo3CF_iEQiCEj_>Iw&6oJit3jayj5M zem3#Ga(M@0_exn8{SwYS=@#mkfPe_$^{NSz0;zZQf;7J83r?2+u1}SF?@re|{yysi zC)~Kn)7zDM>M{+rs=>4Ko+q<8Hbv{?dER!7f0T}>f|D?W^rXuh5>>`=LTJs6v(zX9 z*(EdqA``U8;nqqIc+AyqmyW_vp*4?Ce*}oexyP~?v+kFFx>i6a?Tz|dzf~N@B+)b= z%82j=lXGmvq2`$8kgE9u`IW5!yTOoVt^$=miwuQV8VF%qK+G?~y8z3m*Xv{Ca{BwT zr2FbEjJHmAKYX9gYY3zuUYVbwI;cPv80YLzD2I1UI-h|u-`us>#b z2|(Rr3u z?}K&8qb5Z{;Z4pV2d6_1Cic{AH2JKts>@ziO-h?gDrfT z4u~M+a#MwS-A>=ilGkQ@v*qTnL+8|5Cj&6cFdyYH4H>qxI$TWWYCR)r)DDJCym)<( z_P0BdeieK@B(pOF#m@WEfd{MR zi@W7O<-xp^g_-uU1_BFCL+^CGG`Ps)w1ZZ;^zY4eYBtR4g{K|7G;LLCDTXLmR?m}= z3O6Mp=2ks1=tdV4R8`Qt8uMRBf*o$~`6V!7Y?2^bSNakrHldl`TSYZoZC!z+=-fYN z#F%C6rsz#pEMaN4fX2)HzFurUYRnld1c`ry`}O5nagxHkCY}>9^0!wgwSq03G_M?~ zd;P^(U4HBDdz9p;-EEMZ3e{Qd=`kGia-Yc7aP?gU$;h<@*$V$kCUy7#?zhPU3`B4f zPy$AGYrnj(3~QHa{0W`F@KJp(%z=m0bfaE887}LuOL|5hnXQG1+}YEVeW@jk zBMxa)*b6I|GYLymuuUbHy=pX>w6FXf2vNYLNpV5cL=4J<$u6ydA1v$ zC^K4C_jC3~!Bb*ngV!e+=NP$K1gY?@?2E357nX4&P!u7eQi@>mO9Q( zlyQEBgEsfAEYidiJ8Cy#BMXSo)vvWWJDz^qQ2kLB{$|U3V|Q(87`K>_Tmvo! zXCi|WvoXT$av1rX&+*lghRBiI03E}){qod?P*Y;2^%q(7=dA^A%OMKX8Z+@24ofm* z*&jG8AK^J$h!(ls3ZB=b z!V?Gt5zJH&&15Jhuhx@%^Dt^Eu#mC4UOmqw(SPZ6$x+0cD*m{ON_Whog~(KuRpm6$ zB$9{G_32kV>}hC|5neJELhSmB$!EbWx_JIzn{4i?ysU}PSA^Sjlt=jmd@Pl%ML{Fx zugeG@h!N1f0==j0dWlVurtl*KeAmA;zi7p(T2jhNjlIZtgZ0xO4@kAT zP~meusyT^wRIXgfnk1V^fD!VnahJ}Vd^ zR+m3K%Ok3^!7WRUx}uaJ^d=QPgk_VFx;{V*~Q?k zn<)vD!K!I`esh&KMA>=BT)gS}1~x765svx`(e{D9=K{X9!QAOCZB0bt!pLbnJZcsQ z5uyt@QOn}*HUY>zZG&Hbx*{2n(NsSQ%Gzd0d|d&NwD6SLMvolxlZ=3GxdEZ?yv$7P zuSh!K4|=$=a`I@t@0~f!A!2y>U3^qQ7#i^FbzH|sZMuFcKJeWzo+fl!B;7IDown=K zrKpvIAJPdCFyVYOytcL0^|y(v_TyzA35Uf1wOqq|UCwwrJenzok+Szkn_S}VsbVgf zK(!-AglY=XrG!!5V*|E6-2`$}#lzX5Rv=cTtEGihJPaoo=OT1M*T!JaIL``wEJc_- zuXoP7Z&Jqw*>21})@%(Y)~>_7d)6Sao^HE&?0`#SXpkANKNBAa|Z0h1u-< zYd-86!2ccj20MqcK}7!RA4lw89R}X1Ar(^3?BXlKM1?%ywy`eL9BoS3A=IWGS^&uA zs(c0V^l<*udlsf##`Vsxvw%b6QjRj%FR?Eco#3R)+xr zn;t;-FunLUWBEM*e~ck4p4<%M`0p^3PIC~L zf+RrbE4Lsg;yO59GxmiHyf1v1cE3OzjxE2VDx^gW-9z|So1j9PHW$Y`_h@KndI_<3 zNJel>*m$G1(Pi?aQC~nQm`!3ZJI^%ui-+9dn10DmlGF)miU%9q0E|lwKmp9rqG)^g zRDy-EO8yOe}0Ve*#0B|afs7-;)&DGhm#?ef z#$!ZI0cP=W*t-Cc3wfrSc@lh*?PioB6(YtJvYlcHqvkpGjvpB{Ye4Q~00(l$yHi^eB|Io$nE8YxJAR~?{h55BEq3Y&sP!D!1~pwqH6@!5C&kz{ zt3TT{$f3a<{RrG#xA(Qf=@hvO?-T2<^(Qd{nZU82XJm?TFrBzOq{5O5nU9dRuO9TP zFUpzbBp2E}di$%)R$7!C_9Jz?IwkdVoZ=`V; zx)Xqgn-qw?jGD(FYp@Z{xP-1<-cwHbHoj~+eS&YfwVpS9>@=dY=h%aotmAkYO^-GpXq_2EtcB*nBJqp?|A;p-Fxk~sj88#bznf(;>I2o zU|MVn;K1dc}2MhAgDXR5#lARV5&D@I*39hqkQ=&cl*CshTwh?>sn6^VPqjUu}C_gtP1yGun(dN78a)L@$Q+_P}#VqtJm6@^1}R8lOh zCYX=>Y;{yUrITR*urR)!ta-~Yz$nDq#jX*EPiYRghN&u4g^+FzKAGi3qG;X%wxzZ7 zsO?3r;Z6U*m_nx8xxuYSg85%HKu=cT|J~m5^SkVQVu-w)@kOaL;Xqb@ij!YJbP;a=!j52y7A_t-%&a&X z3a9Pu(MoWMjW?_5;tmob5XBnkTDDnG##zlZeLFB=e(v-$U6J4Y*rv#OvtzRE1F7X2 zdNR)n*V4LS)K;8hjR)3llw5jaI~=b&H-q{eGal2*pd`Qi{CGd6P98U)cX8#~E6Mi&&&-PQMQsX$^?q3qQF?Yr%=E^G(!T~M=) zJ!tv`l1a(o6)4UQ9XX!c-jcR$6I$5OM;EHI*@%mijW~4D&Ofr=9L?h*ngSfb*jfgJ zj4efD))?0_m~LbaEWZ9{uX8I|8}hqiiv)KxDd)WZev{bmX3oKb9ouA{KRTIA-Jz?7 z9Orx?tENj%3lZr;((-&e9L{?zuV7;XJbGHD0k4?!4qwO{<3j9Rrii^EEGJ9L4uUqQgPTPd9=7(snGUjTgS>qLnI6om4-t{?K@_=QDvpqxjkj8Sm(4h>21uKDLgyp_S za*%cFA9U;F^9l3W>PT`nPPbT@t{);xgv=k?k2RD#G3}e|kS}>iEdfBp^nNq-({c-y zJ3Tnjg}e_{nsOwrPF;W1kt8Cn+>-VQ2@nF)X7#~Q8C_9SnN6y{ExQ*lfDePvy_{@1 z&+152{f>vHO;@{;UOyFr!JeH)4D}FX2_I>}l=TW1a}e~mmN}LP>k(2y7caznd~cwN zC-!CDfBvpL_Zz$7(8owN-uz| z{k20GBXaj&*Q|IDN`yT)QiQ#$JA%v(03Tcz@w5Dn_8BN5qk!tc^ISS1ZAGnpW}nyA zZsJUP@ABnR$eC4AbjG;9o!c$i?8MaDn%2;f3rU@n^(mFURrA7*7NKmgPK?l|Tuiwm zyO@%X+!%8ux3rD|dsV-aSo)K4`$@N$ABA|FDKt^Q>O-$fV(3mi{A0(N^9{n4aQHvy zD@OsXf;(61U=}aOJ}dg;QfscwUG^DXCQ`1GRJh_k`PyYIxutjI?7fttj2ye^k)1d^ zm@yH9l+mn*QRxd`>F4J5JSrK1hN{fUkH_9rKmmcSs&y(+hE=ke-mQ>*RkA!c%b`=dEg z4ynWsRnmho)1o^jHS$q&RR0!e2bU-}FkAd!JXAmM%NNQtT(*vJ0#C2v+`)m5)(Mnx zuwEtWS)@o#P+II%$EEA21iOthjw_wQaq@pGn=MpxprE7l{Xqf>4>gUH)bv-)^hc9Y zukyy>tIbU71c(e~k3GQT|iLwXz$Oi2AU;hlL^8`6@oR1x=xy^Y5iaA|wB zUnIsVZ&XYBS5RJC4L~6mhv0!V7|&opA`L?z|Q0CF=Yt<~tt?NS2nd;isj zTy)3~bQKj9lBQRUjS`gqBMs#(zc}=0;Y7-$=wLso5OWyE?*0B!t91siEwX6(;{(IE zAIIR4mvHyZSq!MLYD{xN93xRT1r}pknL=;K6)tFtr>IJBovFt7t(L z*fJ4W39wn*;K+Qv67B?(_jzIx3jJ?Dcm-v*z)e3DRSCQ=uK$uZjymrSKQ;i5WHD3~ 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 033/643] 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 zcmZvicQ{<{`tFBJ7^2MRQO8UOg6O>)CHgQ*^d3D*^j?Bd1_@E33nn9p5JI#dIuU{> ziC%(;7D;qx*?a%KzkRNA{^GjUnwhoU^*+yYf9`u>4fHf9$(hMPAQ0spO_U+fUACdm4y6{$D<j-ya zkVHf%#w$7ON(c5I3{Xl?2vM9WmIg-6gmrGBLny1L@Kj`Xz|W4qH?OrqN-7(wx3*_z z{ha6IJbupY&z`h4hwezv@AVH13?L-b+q)q7@}W;YkBx1-zc{Nt{MO|EBXuWD@jS=S z(2z$+D4m#?xGV5aq$vS|b(Y&C=z5HUm0vW9Sk1sEc-RhU^bMbkq!}Nsc_SVq9>+R83VscLY?o{e4 z9Chiv*k2tCwOmbQk=*K13^~B_G&}U-#!FO5_y7L=+ZcB5st~$>vnw*2IXZ!w<8v35 zcH>}U4D-@lTsE4Vfgf+)9C^HP^MtxH>y|0rYqqJ*wu6`tT^i@+FM>9XeR9o&CA$Cd z&9Rw!_p5i}sn`es{#1h+EV~Xc7);r3Z3tb?rh_rIT~(Pt*)DcI6m$K2BTqK))!~!w zk;09!%480l&vH+2{aqbQb!Y#>=h*hOk565fMYRnmSPa*Cg8Rc!J-0&1y}Fb*@OnF3!>`N{o(< zj#ru9&Tj5P`Ck`lQ}zU#yf9Pl@9(E$VW|o*&da`-zE^~P%&qIvl?W4@_=xf+6Kpf{ z1S@^k&KAV}Lcd`i4qKExUCp-P+eXkD3uD4cW*`ebj0#Q8mUsN@6SC_4z7HpH#OC7N zJ}C&=z=)@$HpeQ{T<7j&Jz!?hZVue3SXi*F%oar#sB|&9M1%4fUoiOOW@IRcrzuxSFtbwmvLz6dv=8S*RKS{cNy;W<+${7f{~ z6a=R!)P@v%ZS*PofXKzqsXQI@xlW`rQe|3AVDMS;jeXEU)Nys9$~5pWwi`9!@O0*8`c&XQ8AZ`WXq-lQNokU-jecMI^{hJy5>Te`ODYxU(Cw)Tk{kuK) z{%lQypJ!LM9dD*`?W({^Ro5vQwx(J*Wn7%XzE+6dkYK0Q~Iyg>r%&1aNSVRvBp`@h0 zS0&-3YK;yaaES*!h@+vQfe=VNf{~#2-~aslY6R@E?uR;L=4E0L94je64Ij-A{$`4yAcc z2B{;|UAaA7T_YW_q^Tp8yfag^PTHMllVk>g!%@>DSd9`=9mmRRsMlEPW=mwYzqJI^ zHLrkxE}m&$mN0QIR{bn;r}gjp$qi7jqeb>u&m)^w&7_Lhj@@J=m~+f6&Vj`7BrTUQ)Z~X{3~MA2g;R;w(f< zOUu4gh6Qup{2fx~K8Zshk2QzlE}P^?I1yiG1FEN8gX2Z?`O+mp(Yyo_{_ zTHHDG$yg*?0NP%i^GD#b z`65B_G`d)hs6k#cd+9x=6QPn*klrp@2P3c1f$*1f|H6MuSQwpmupo_WBVN@wk5~NlA?QDdIGcUR_;H_tEjw4c_<;=2Tl7 zo4>ue;o-BrxSa-$BaB)LwxgV)p~J;>fpmey-n#3k2u-vsEEf)<$8t z0Y7D0a7;`LWOz5ENZal6-P^{*PNeHx<&~A9=+-!1#$|AHVj_f`it26Xg^=wqEXstY z57;G!+yuYIL-PA@@55a?^Om3*sVYaKc#w(FR;J|rxqK{vLZoeg1wtoinZqt0f*Sej zG{`~(Cdm}Acv7ek&L_AM_^-+YB@oBuPOE$rtD1_US9Wj%wsoE7R|#$cQSYY_U0iBv zIZ^`$^&NS=nhNqAey}x#=F#0v8hE2-1YS6b_3#3kc-|NHt^ufX!aCcEmQyLS514Xp z4Te-twB1_#kigP%b5mSVQeQAa!`boKwbg@~2+Q+*s02dT8(fUZ&KXsVg4iP>B2?@UmBMHzX5MS{ zSBI(7uive6$#@u25NHZ}jRXA|Ez=N12b=W8f|e9+TQ%LF`C~roF{25r$`C!dHTtE3 z>VqxC8#2n{!N1lvrpToUxTGY6i}v)e?$M|z&S%l2McuYNiU>i`2A@Nd41g4O8;X-X5XbA{D8qMxUa1jHonPK=i z=w5x2asdbKFQ5(rW}K}5J$@c4Sz5CGoNYFByeZkdsPX*Xr$Rb*_E-2S9gLdLo|-vl z6kY5TMmqes&cxWwnmY6N$7Hp>Y66w9rR2Y79|HtaZEbafMo(K?bafyptIoK}L@yeLUOXlF8)ml6Pj`nX|h{}JZJqrlv{S_BNgG>+B)i3(o1hmFH>ZiI0H(n9$ z-|XwtjPZ*br5L6F6qa9z-sTG%9n3w*-n_Be!sbNPcw2br@yYx};XU~)q*Qd$c0ez> z+2$m9xP95d&rbgSI*>A)q2?wSK0A~#hDIS4AK%o++jhk04JOwxj&%h1=%bA&oy|8Xfy-^2A(ebc+-U(s}h5KCCes z2J)M|hEE!Z>(BI~euL%PCOyFl7pHzcI-`IPY8Xt!;TZV#;Uu+%8%`rqoqRG8r-u!h z*IOpIxd{#FE53Bd*WQaNO@TXw@SIALXt(s0!@cE8eFOCJ$LZ5UuOwGo*`#+8r2e#p zpTwQmxViB?eE1OChQE80cH(PU-|8y1yeNMZn%+F@Z)eDm=E4z~XbrwvCYyN1p#G>aMve(pVE5 z52BqAJw5ayg#a2pSw&T~n}q7=cZd*LzBgUF?`pJRxfYCdTl)!r|6vdj5jTNRX$3Kd z0^KW5yyf}%8JX%b7dQuRP5dbN=sJ*}7_-P+*Lf*RhGY>pd*ukg<0uisv2AsLM;P%{bKK!p$ z$%kt;cP0Fx!1~5kIccfwN-il|y!CL+RroQA<|eS?pFSI&KV6eNI6v8;6>)m=JQ+l5 zY!#+!(ex<4u;OP66`MopCa7t&O3r5qY$vX^ZzbUge3@IU->Z5hak#wvEc*z>h1p@x zOq=5Qp@Y_)JFur>L_|b?+MU0?hmBZPnF#2Hf>IH6q%=hyGo0MYH@yk&YoS=3W5ZuG6}2je0}43c^_OY913API05fA z$h;{_bS6({^Vb{rx~~z?bX&4g>qJrk09TsTW_DC%XP zf<<0hHJhY&WjWUCT?^PFt|I~`CniES&cBJ@@K)LV3sA>5fta0NP~gEPfSlj6b$-^Y zkE$cNWEl2mk?qu^z737`Q@b%=Mgc`*`7X8kw+OKg<~FD)_?I)YYyiJ<*R}rSu&}Te z143YOdj-9T>5HVk*%*}e@Yd>Jwu&Wl+PKFtq8;@c8o8oJcF8eWuyKm*|3#S9>ChXq z-RexN+tUYXz;zRyb8>Rh(bJc^`0p1p8+&ydwbwcgvMPK&Kc0NgK$hPW@ROi*W{GzP zcBs_{ZA;2k|7R~01Gn=JB?yaWZ>(EG5Ki(m{L>UWZ`#`05N(;dRKRW$#9eu`VLt|W z{FNd;(DZaFDic7T|5CEU6tkkb9Kd-Lt4Z{?c%-Fsy)Eq|RGqh|6;BP)50<)la~0u8y0sQ-Z)uIyjp%y6J8iAC}mYin!8n8)XPnXuLt`OrB81cc$yDyy+fsfLS1a6F~2b6I3AF64npqI;r$~5>atKX;ZUv0#K zXvG;9gp@ND`W`3JO7^NYeT7;Yw1)U=U)c5w@#u_Osz-}voKa`W25uVw?PVR%{USrA zgKwj;c@FD~{$OL0xVW0L6c91hK-R6Bh`6Z(Sv%`|hf08$72*>`Q?b~RSW@bJF?1s6 z5yLW1m0B_b`Odlz!iiankS-NDKg&1p_O`Vv}5V~ANEKAmN{EnN2J zOucsaGhLG_aqj@DL*J_Df$-f=D_gj7Y?JS*mX@wA7Y{}4yLiytMok{VhVS1W1;~yb z&1qDjgXVC3JOTP1hME}46CZSxfBZ)F2{)gZ2aC8H3J~g#ydIpN?L;PLv72`SeTw@K zvD{+HVDUaeo{NiXRB}EHsr^`ImP(tp-l{o(?)vpR0HtKPrAMCbX)I!*#AtVw)r&#H z{674MWX{2_dE)Lo3JTUwxO1D>o^ZPXSMK^Do)WC#mrLPx3h1b}w7OX*_Kv4!V#=Wz#P-8;&`vC1tz;@jM!3#k8!>TL=URe| z@+5NKaROic#`$9{4J~cCHnjr4AA1o^L3{R#;=hl+7a8^9*t$=Ob!dcZm+q-|n&;s~ zs_{E*C$GXa=&Q~viz2jmd3jfMc5Zjet$5U5%b8k_=`gNVjwLxr zi#&~mCm>??WC{Pe#(}0E&45dlp|> zk_l$&T#1vZ6%Lhn3@~^DWl@iOkCd}*-Pa_Gf8 zQd4=Cn>DL zyd-FUi#r;OT?4!S*?e6~iMVle# zaSSxwkI}OE9B|QEmr+ExI;zvWH|4r2{VkJc0D)*v$+(MQv3Y}1*}O*T5E~@b_-4dbmsaup46}vPS=E zw=v055vUjfEJZaGOg7pj`t2{79K4=T?UJC-&c4h|+!s?|RKRhpLf&6`Wvh%|0J5)h zug!OLz+|KL;LNd>j9$8E4BZ>BS%MAZS^08|_#s!&IbrwxKT;`p1KlYqJlE zN=;y$fHKq&ok!1OP(c_5OV9 z$J@`g&0gCQB@lvHEK>&@O4~?eWMs_2DYq>fM;zAC444&V3P<^|!D62{;|HgQdoPBH zC*eWQt-1MNz!24Hv6-PE4ZUIk!NlH}l73}g&*#56ey7ia@LUq?mGW(m%0FCa?E4c7c;}=~ z4jzOzK5PB(8Ks8%Bxu#-!t9rqo^E^71XxU7Br=xx$`!VV*V;eUAK$i7kO}?sqTn$9 zn!0&m@He4B8v4h~X)SPqb--fhRV{68KTQ;>W&!pEmT}9N&~eqiJ55Z6+T^OW1@=D zsx@R{#~4tx=5ACW)0lf5QHf}t@}E!%7oNeOm5}PzaQhHII%OY ztYl$ZsgCNvFVjPXSkb^7y-}B%?i`Z}dreLpkKm&bR}N%6Zw8KML4_#Lv49=q%1tn? zaxULnY!e~wng0D7=sMUu=&PO{h#8D%))a$Z2OOfWSK9zC^xu{KYg14=mk|@RxM68ms|_e8>SM%q=o9GHviXF%wZM z%peO-&7nZ&%C^9trVD?X6xtDU)%b_xL57DbTe>&X=VHwt2Bj#niOrRm>qPZ1gH${K z{1x@?ljM)qH{|0a7J3l~M9dmsPDm75Djvi3O* z^gx)%h^k@q%3pz$rX28slO5X>6cj!$M(N&q@d{u%&J_{0B|G3rKp;U6@n^@sky1Bo z%lYosK07#zkK+MC4+ko-?1;w3=sD;D6&V@K&RN~EV3+Q-$Fzuy-x`HJiMo;-_?tC4 z1N-9tmvbN%g;Ek7zP=%8%Q8xf|0W9lWu5ARVw?Bn6qA=+Pz%X438-EcmYI8^xd9<4C{1fqaFbcxM z&Bq?NSmxf7CHB41>j3ccO|UEZ!-&=ulTynR!jE&-3NZb)_71Lpw`b{CSzoO9 zw#CB?=!w)&4}Yncm^>j+X1v@@Nul5~deZa=6#(g0o4sw^FrgKIAN9`J8@)) z%{w{dAqg+cTXP)Xd$LmIjzCjS$BfAe^;G5uCx1NatCse!M_a=BvhceyF??54I;SGk zK}4h@o+@!r7G$wF@jDuN8I*U`V_}T0dz8m-yT1))HTDPltJ)#Ez_*tQ!laQ4 z3dHxJ^sW>?#-Eo}^<<_=FuC~-h310N=_P%c=-Ey;lek}dZ%$x^CZJG%n#`f|&)zft$YpeVI`R~;P+ zHn|{!{k4Iy7C;=);A+k5TsZa18o4Uel%W1AeHn;Va1}ET$9DjQjm*vS41^sWz~kyl zQ2Jnv_ZR1(`|6$C^(_3_N0ZeyH*YipXq(5cyA+VaL{ubtZ`e_Jnw{l_$1Bc}*3iHV z?kiL$K!?eL9B$3j-*P|s^AkuB1jT;{J52*Rz5M*_#3)8r&a(`H=Mr%Ya>S|~l>fYVLxygg*|9@fBod~x>;KMovd;|UG} zOr^{TJQ~R?=8`_+|ISiDEE!r8Ga@2ouVmLTIXSuNJKkgm6lZ2;CTc$HSE{+O_q&uR zrS?npcQ+#=WBjeB#dElH#HrLGDfmXv#o1ri!`;QDp?zRlKdC4H#(J^1`xgViGZ6D! ziqD}XDjFFXc|pk{0cHK@RQueh(h$f5ex_w+kVgHgZMYFq*{6~*e0Iw&+-nsheCv-UziMCkhJ;0p23qZm$RALfp z`{~By?o!pPM$}~(q1UxjTU|{G+JBh@TUfu|ZO|IdsqrZY#6G`CL#zO7$d5qeEcnyJ z=9w=D1cqO}3-ImTSUJm)J|Y|R3<0LiS&@&;a*-U z%z%YRdHml21^2%(!TioYm>^8d4u>aRasrT02rH+i1B79wTVn)JnV*y7u5n5fDP+n& z{6D0CSU;%+%IzR*@QHx7evyLHf6A@?zbL^g^&d(|iQ`;=Hu?`GSJw(oE*)*EMSbdM7OgXp-URz# z5ulDdNzE_h|Ah;KGbpcY>}9iDza3Loa+na;Y9jeXz4n-5JKd1af9J^ z29%l_*%`Nj-?CM;l=v~x6_P~O;yyEH<5($a-(Hn~hpDiUYteGpBy~Hk4D=nF zYwdc4a=eJ7DKgZxx_7u1sJ9m8n@6{m?cA!=N9kU)76x2A~Ja8roAx^?3ox{7~bX!hZ;p?9H zq}1#>04`Jl=4MEj|iLGTw!9Kl@*BfJL(YHyrfg%UsR_nsqTOVvtf?N($XDOkFgey4s=v z_vucmgg1jnbua3w^JNUt*0J1^N;_Z65*FxSZ@&(-yDgs^C$>H(U}9@dKJu9VO&%1E zj*qoSh3C|O7fE<(iQy`V;eq8W2(R=j;1+d^#S!3Sm)v>GJqo-DatZFAL23W1`0t4F zeS?-mf(r0&lgi4<9wx~pM!&cha$OAfItj<2SeSMF00`_S9l#hQpZWirE?|uALzbq1 z)=aw{3FW+Y?Ha8jgWH#lJsxkOlqgy-hKumhE3u-xxA!aA_-i{=W%DpT41Qq`&Phtq zho#0PdniKKWFFYw(N7y)C3aL&qAgw9a#2xfk~@cIzwj+!3om5Oc5{{d0Pa{>SW 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