From 02d583e8be5267707a8d37a8e2b3cc68d6bae1c5 Mon Sep 17 00:00:00 2001 From: remlostime Date: Sat, 29 Jul 2017 08:58:05 -0700 Subject: [PATCH 01/65] Improvement of Red Black Tree * Add count(), allElements(), isEmpty() functions * Make the config right for RBTree in workspace * Create a separate class for RBTree --- .../Sources/RedBlackTree.swift | 1347 +++++++++-------- Red-Black Tree/RedBlackTree.swift | 795 ++++++++++ 2 files changed, 1491 insertions(+), 651 deletions(-) create mode 100644 Red-Black Tree/RedBlackTree.swift diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift index 59633031d..fc0411b42 100644 --- a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -21,730 +21,775 @@ import Foundation private enum RBTreeColor { - case red - case black + case red + case black } private enum RotationDirection { - case left - case right + case left + case right } // MARK: - RBNode public class RBTreeNode: Equatable { - public typealias RBNode = RBTreeNode - - fileprivate var color: RBTreeColor = .black - fileprivate var key: T? - var leftChild: RBNode? - var rightChild: RBNode? - fileprivate weak var parent: RBNode? - - public init(key: T?, leftChild: RBNode?, rightChild: RBNode?, parent: RBNode?) { - self.key = key - self.leftChild = leftChild - self.rightChild = rightChild - self.parent = parent - - self.leftChild?.parent = self - self.rightChild?.parent = self - } - - public convenience init(key: T?) { - self.init(key: key, leftChild: RBNode(), rightChild: RBNode(), parent: RBNode()) - } - - // For initialising the nullLeaf - public convenience init() { - self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil) - self.color = .black - } - - var isRoot: Bool { - return parent == nil - } - - var isLeaf: Bool { - return rightChild == nil && leftChild == nil - } - - var isNullLeaf: Bool { - return key == nil && isLeaf && color == .black - } - - var isLeftChild: Bool { - return parent?.leftChild === self - } - - var isRightChild: Bool { - return parent?.rightChild === self - } - - var grandparent: RBNode? { - return parent?.parent - } - - var sibling: RBNode? { - if isLeftChild { - return parent?.rightChild - } else { - return parent?.leftChild - } - } - - var uncle: RBNode? { - return parent?.sibling - } + public typealias RBNode = RBTreeNode + + fileprivate var color: RBTreeColor = .black + fileprivate var key: T? + var leftChild: RBNode? + var rightChild: RBNode? + fileprivate weak var parent: RBNode? + + public init(key: T?, leftChild: RBNode?, rightChild: RBNode?, parent: RBNode?) { + self.key = key + self.leftChild = leftChild + self.rightChild = rightChild + self.parent = parent + + self.leftChild?.parent = self + self.rightChild?.parent = self + } + + public convenience init(key: T?) { + self.init(key: key, leftChild: RBNode(), rightChild: RBNode(), parent: RBNode()) + } + + // For initialising the nullLeaf + public convenience init() { + self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil) + self.color = .black + } + + var isRoot: Bool { + return parent == nil + } + + var isLeaf: Bool { + return rightChild == nil && leftChild == nil + } + + var isNullLeaf: Bool { + return key == nil && isLeaf && color == .black + } + + var isLeftChild: Bool { + return parent?.leftChild === self + } + + var isRightChild: Bool { + return parent?.rightChild === self + } + + var grandparent: RBNode? { + return parent?.parent + } + + var sibling: RBNode? { + if isLeftChild { + return parent?.rightChild + } else { + return parent?.leftChild + } + } + + var uncle: RBNode? { + return parent?.sibling + } } // MARK: - RedBlackTree public class RedBlackTree { - public typealias RBNode = RBTreeNode - - fileprivate(set) var root: RBNode - fileprivate(set) var size = 0 - fileprivate let nullLeaf = RBNode() - - public init() { - root = nullLeaf - } + public typealias RBNode = RBTreeNode + + fileprivate(set) var root: RBNode + fileprivate(set) var size = 0 + fileprivate let nullLeaf = RBNode() + fileprivate let allowDuplicateNode: Bool + + public init(_ allowDuplicateNode: Bool = false) { + root = nullLeaf + self.allowDuplicateNode = allowDuplicateNode + } +} + +// MARK: - Size + +extension RedBlackTree { + public func count() -> Int { + return size + } + + public func isEmpty() -> Bool { + return size == 0 + } + + public func allElements() -> [T] { + var nodes: [T] = [] + + getAllElements(node: root, nodes: &nodes) + + return nodes + } + + private func getAllElements(node: RBTreeNode, nodes: inout [T]) { + guard !node.isNullLeaf else { + return + } + + if let left = node.leftChild { + getAllElements(node: left, nodes: &nodes) + } + + if let key = node.key { + nodes.append(key) + } + + if let right = node.rightChild { + getAllElements(node: right, nodes: &nodes) + } + } } // MARK: - Equatable protocol extension RBTreeNode { - static public func == (lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { - return lhs.key == rhs.key - } + static public func == (lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { + return lhs.key == rhs.key + } } // MARK: - Finding a nodes successor extension RBTreeNode { - /* - * Returns the inorder successor node of a node - * The successor is a node with the next larger key value of the current node - */ - public func getSuccessor() -> RBNode? { - // If node has right child: successor min of this right tree - if let rightChild = self.rightChild { - if !rightChild.isNullLeaf { - return rightChild.minimum() - } - } - // Else go upward until node left child - var currentNode = self - var parent = currentNode.parent - while currentNode.isRightChild { - if let parent = parent { - currentNode = parent - } - parent = currentNode.parent - } - return parent - } + /* + * Returns the inorder successor node of a node + * The successor is a node with the next larger key value of the current node + */ + public func getSuccessor() -> RBNode? { + // If node has right child: successor min of this right tree + if let rightChild = self.rightChild { + if !rightChild.isNullLeaf { + return rightChild.minimum() + } + } + // Else go upward until node left child + var currentNode = self + var parent = currentNode.parent + while currentNode.isRightChild { + if let parent = parent { + currentNode = parent + } + parent = currentNode.parent + } + return parent + } } // MARK: - Searching extension RBTreeNode { - /* - * Returns the node with the minimum key of the current subtree - */ - public func minimum() -> RBNode? { - if let leftChild = leftChild { - if !leftChild.isNullLeaf { - return leftChild.minimum() - } - return self - } - return self - } - - /* - * Returns the node with the maximum key of the current subtree - */ - public func maximum() -> RBNode? { - if let rightChild = rightChild { - if !rightChild.isNullLeaf { - return rightChild.maximum() - } - return self - } - return self - } + /* + * Returns the node with the minimum key of the current subtree + */ + public func minimum() -> RBNode? { + if let leftChild = leftChild { + if !leftChild.isNullLeaf { + return leftChild.minimum() + } + return self + } + return self + } + + /* + * Returns the node with the maximum key of the current subtree + */ + public func maximum() -> RBNode? { + if let rightChild = rightChild { + if !rightChild.isNullLeaf { + return rightChild.maximum() + } + return self + } + return self + } } extension RedBlackTree { - /* - * Returns the node with the given key |input| if existing - */ - public func search(input: T) -> RBNode? { - return search(key: input, node: root) - } - - /* - * Returns the node with given |key| in subtree of |node| - */ - fileprivate func search(key: T, node: RBNode?) -> RBNode? { - // If node nil -> key not found - guard let node = node else { - return nil - } - // If node is nullLeaf == semantically same as if nil - if !node.isNullLeaf { - if let nodeKey = node.key { - // Node found - if key == nodeKey { - return node - } else if key < nodeKey { - return search(key: key, node: node.leftChild) - } else { - return search(key: key, node: node.rightChild) + /* + * Returns the node with the given key |input| if existing + */ + public func search(input: T) -> RBNode? { + return search(key: input, node: root) + } + + /* + * Returns the node with given |key| in subtree of |node| + */ + fileprivate func search(key: T, node: RBNode?) -> RBNode? { + // If node nil -> key not found + guard let node = node else { + return nil + } + // If node is nullLeaf == semantically same as if nil + if !node.isNullLeaf { + if let nodeKey = node.key { + // Node found + if key == nodeKey { + return node + } else if key < nodeKey { + return search(key: key, node: node.leftChild) + } else { + return search(key: key, node: node.rightChild) + } + } } - } + return nil } - return nil - } } // MARK: - Finding maximum and minimum value extension RedBlackTree { - /* - * Returns the minimum key value of the whole tree - */ - public func minValue() -> T? { - guard let minNode = root.minimum() else { - return nil - } - return minNode.key - } - - /* - * Returns the maximum key value of the whole tree - */ - public func maxValue() -> T? { - guard let maxNode = root.maximum() else { - return nil - } - return maxNode.key - } + /* + * Returns the minimum key value of the whole tree + */ + public func minValue() -> T? { + guard let minNode = root.minimum() else { + return nil + } + return minNode.key + } + + /* + * Returns the maximum key value of the whole tree + */ + public func maxValue() -> T? { + guard let maxNode = root.maximum() else { + return nil + } + return maxNode.key + } } // MARK: - Inserting new nodes extension RedBlackTree { - /* - * Insert a node with key |key| into the tree - * 1. Perform normal insert operation as in a binary search tree - * 2. Fix red-black properties - * Runntime: O(log n) - */ - public func insert(key: T) { - if root.isNullLeaf { - root = RBNode(key: key) - } else { - insert(input: RBNode(key: key), node: root) - } - - size += 1 - } - - /* - * Nearly identical insert operation as in a binary search tree - * Differences: All nil pointers are replaced by the nullLeaf, we color the inserted node red, - * after inserting we call insertFixup to maintain the red-black properties - */ - private func insert(input: RBNode, node: RBNode) { - guard let inputKey = input.key, let nodeKey = node.key else { - return - } - if inputKey < nodeKey { - guard let child = node.leftChild else { - addAsLeftChild(child: input, parent: node) - return - } - if child.isNullLeaf { - addAsLeftChild(child: input, parent: node) - } else { - insert(input: input, node: child) - } - } else { - guard let child = node.rightChild else { - addAsRightChild(child: input, parent: node) - return - } - if child.isNullLeaf { - addAsRightChild(child: input, parent: node) - } else { - insert(input: input, node: child) - } - } - } - - private func addAsLeftChild(child: RBNode, parent: RBNode) { - parent.leftChild = child - child.parent = parent - child.color = .red - insertFixup(node: child) - } - - private func addAsRightChild(child: RBNode, parent: RBNode) { - parent.rightChild = child - child.parent = parent - child.color = .red - insertFixup(node: child) - } - - /* - * Fixes possible violations of the red-black property after insertion - * Only violation of red-black properties occurs at inserted node |z| and z.parent - * We have 3 distinct cases: case 1, 2a and 2b - * - case 1: may repeat, but only h/2 steps, where h is the height of the tree - * - case 2a -> case 2b -> red-black tree - * - case 2b -> red-black tree - */ - private func insertFixup(node z: RBNode) { - if !z.isNullLeaf { - guard let parentZ = z.parent else { - return - } - // If both |z| and his parent are red -> violation of red-black property -> need to fix it - if parentZ.color == .red { - guard let uncle = z.uncle else { - return - } - // Case 1: Uncle red -> recolor + move z - if uncle.color == .red { - parentZ.color = .black - uncle.color = .black - if let grandparentZ = parentZ.parent { - grandparentZ.color = .red - // Move z to grandparent and check again - insertFixup(node: grandparentZ) - } - } - // Case 2: Uncle black - else { - var zNew = z - // Case 2.a: z right child -> rotate - if parentZ.isLeftChild && z.isRightChild { - zNew = parentZ - leftRotate(node: zNew) - } else if parentZ.isRightChild && z.isLeftChild { - zNew = parentZ - rightRotate(node: zNew) - } - // Case 2.b: z left child -> recolor + rotate - zNew.parent?.color = .black - if let grandparentZnew = zNew.grandparent { - grandparentZnew.color = .red - if z.isLeftChild { - rightRotate(node: grandparentZnew) + /* + * Insert a node with key |key| into the tree + * 1. Perform normal insert operation as in a binary search tree + * 2. Fix red-black properties + * Runntime: O(log n) + */ + public func insert(key: T) { + // If key must be unique and find the key already existed, quit + if search(input: key) != nil && !allowDuplicateNode { + return + } + + if root.isNullLeaf { + root = RBNode(key: key) + } else { + insert(input: RBNode(key: key), node: root) + } + + size += 1 + } + + /* + * Nearly identical insert operation as in a binary search tree + * Differences: All nil pointers are replaced by the nullLeaf, we color the inserted node red, + * after inserting we call insertFixup to maintain the red-black properties + */ + private func insert(input: RBNode, node: RBNode) { + guard let inputKey = input.key, let nodeKey = node.key else { + return + } + if inputKey < nodeKey { + guard let child = node.leftChild else { + addAsLeftChild(child: input, parent: node) + return + } + if child.isNullLeaf { + addAsLeftChild(child: input, parent: node) + } else { + insert(input: input, node: child) + } + } else { + guard let child = node.rightChild else { + addAsRightChild(child: input, parent: node) + return + } + if child.isNullLeaf { + addAsRightChild(child: input, parent: node) } else { - leftRotate(node: grandparentZnew) + insert(input: input, node: child) } - // We have a valid red-black-tree - } } - } } - root.color = .black - } + + private func addAsLeftChild(child: RBNode, parent: RBNode) { + parent.leftChild = child + child.parent = parent + child.color = .red + insertFixup(node: child) + } + + private func addAsRightChild(child: RBNode, parent: RBNode) { + parent.rightChild = child + child.parent = parent + child.color = .red + insertFixup(node: child) + } + + /* + * Fixes possible violations of the red-black property after insertion + * Only violation of red-black properties occurs at inserted node |z| and z.parent + * We have 3 distinct cases: case 1, 2a and 2b + * - case 1: may repeat, but only h/2 steps, where h is the height of the tree + * - case 2a -> case 2b -> red-black tree + * - case 2b -> red-black tree + */ + private func insertFixup(node z: RBNode) { + if !z.isNullLeaf { + guard let parentZ = z.parent else { + return + } + // If both |z| and his parent are red -> violation of red-black property -> need to fix it + if parentZ.color == .red { + guard let uncle = z.uncle else { + return + } + // Case 1: Uncle red -> recolor + move z + if uncle.color == .red { + parentZ.color = .black + uncle.color = .black + if let grandparentZ = parentZ.parent { + grandparentZ.color = .red + // Move z to grandparent and check again + insertFixup(node: grandparentZ) + } + } + // Case 2: Uncle black + else { + var zNew = z + // Case 2.a: z right child -> rotate + if parentZ.isLeftChild && z.isRightChild { + zNew = parentZ + leftRotate(node: zNew) + } else if parentZ.isRightChild && z.isLeftChild { + zNew = parentZ + rightRotate(node: zNew) + } + // Case 2.b: z left child -> recolor + rotate + zNew.parent?.color = .black + if let grandparentZnew = zNew.grandparent { + grandparentZnew.color = .red + if z.isLeftChild { + rightRotate(node: grandparentZnew) + } else { + leftRotate(node: grandparentZnew) + } + // We have a valid red-black-tree + } + } + } + } + root.color = .black + } } // MARK: - Deleting a node extension RedBlackTree { - /* - * Delete a node with key |key| from the tree - * 1. Perform standard delete operation as in a binary search tree - * 2. Fix red-black properties - * Runntime: O(log n) - */ - public func delete(key: T) { - if size == 1 { - root = nullLeaf - size -= 1 - } else if let node = search(key: key, node: root) { - if !node.isNullLeaf { - delete(node: node) - size -= 1 - } - } - } - - /* - * Nearly identical delete operation as in a binary search tree - * Differences: All nil pointers are replaced by the nullLeaf, - * after deleting we call insertFixup to maintain the red-black properties if the delted node was - * black (as if it was red -> no violation of red-black properties) - */ - private func delete(node z: RBNode) { - var nodeY = RBNode() - var nodeX = RBNode() - if let leftChild = z.leftChild, let rightChild = z.rightChild { - if leftChild.isNullLeaf || rightChild.isNullLeaf { - nodeY = z - } else { - if let successor = z.getSuccessor() { - nodeY = successor - } - } - } - if let leftChild = nodeY.leftChild { - if !leftChild.isNullLeaf { - nodeX = leftChild - } else if let rightChild = nodeY.rightChild { - nodeX = rightChild - } - } - nodeX.parent = nodeY.parent - if let parentY = nodeY.parent { - // Should never be the case, as parent of root = nil - if parentY.isNullLeaf { - root = nodeX - } else { - if nodeY.isLeftChild { - parentY.leftChild = nodeX + /* + * Delete a node with key |key| from the tree + * 1. Perform standard delete operation as in a binary search tree + * 2. Fix red-black properties + * Runntime: O(log n) + */ + public func delete(key: T) { + if size == 1 { + root = nullLeaf + size -= 1 + } else if let node = search(key: key, node: root) { + if !node.isNullLeaf { + delete(node: node) + size -= 1 + } + } + } + + /* + * Nearly identical delete operation as in a binary search tree + * Differences: All nil pointers are replaced by the nullLeaf, + * after deleting we call insertFixup to maintain the red-black properties if the delted node was + * black (as if it was red -> no violation of red-black properties) + */ + private func delete(node z: RBNode) { + var nodeY = RBNode() + var nodeX = RBNode() + if let leftChild = z.leftChild, let rightChild = z.rightChild { + if leftChild.isNullLeaf || rightChild.isNullLeaf { + nodeY = z + } else { + if let successor = z.getSuccessor() { + nodeY = successor + } + } + } + if let leftChild = nodeY.leftChild { + if !leftChild.isNullLeaf { + nodeX = leftChild + } else if let rightChild = nodeY.rightChild { + nodeX = rightChild + } + } + nodeX.parent = nodeY.parent + if let parentY = nodeY.parent { + // Should never be the case, as parent of root = nil + if parentY.isNullLeaf { + root = nodeX + } else { + if nodeY.isLeftChild { + parentY.leftChild = nodeX + } else { + parentY.rightChild = nodeX + } + } } else { - parentY.rightChild = nodeX - } - } - } else { - root = nodeX - } - if nodeY != z { - z.key = nodeY.key - } - // If sliced out node was red -> nothing to do as red-black-property holds - // If it was black -> fix red-black-property - if nodeY.color == .black { - deleteFixup(node: nodeX) - } - } - - /* - * Fixes possible violations of the red-black property after deletion - * We have w distinct cases: only case 2 may repeat, but only h many steps, where h is the height - * of the tree - * - case 1 -> case 2 -> red-black tree - * case 1 -> case 3 -> case 4 -> red-black tree - * case 1 -> case 4 -> red-black tree - * - case 3 -> case 4 -> red-black tree - * - case 4 -> red-black tree - */ - private func deleteFixup(node x: RBNode) { - var xTmp = x - if !x.isRoot && x.color == .black { - guard var sibling = x.sibling else { - return - } - // Case 1: Sibling of x is red - if sibling.color == .red { - // Recolor - sibling.color = .black - if let parentX = x.parent { - parentX.color = .red - // Rotation - if x.isLeftChild { - leftRotate(node: parentX) - } else { - rightRotate(node: parentX) - } - // Update sibling - if let sibl = x.sibling { - sibling = sibl - } - } - } - // Case 2: Sibling is black with two black children - if sibling.leftChild?.color == .black && sibling.rightChild?.color == .black { - // Recolor - sibling.color = .red - // Move fake black unit upwards - if let parentX = x.parent { - deleteFixup(node: parentX) - } - // We have a valid red-black-tree - } else { - // Case 3: a. Sibling black with one black child to the right - if x.isLeftChild && sibling.rightChild?.color == .black { - // Recolor - sibling.leftChild?.color = .black - sibling.color = .red - // Rotate - rightRotate(node: sibling) - // Update sibling of x - if let sibl = x.sibling { - sibling = sibl - } - } - // Still case 3: b. One black child to the left - else if x.isRightChild && sibling.leftChild?.color == .black { - // Recolor - sibling.rightChild?.color = .black - sibling.color = .red - // Rotate - leftRotate(node: sibling) - // Update sibling of x - if let sibl = x.sibling { - sibling = sibl - } - } - // Case 4: Sibling is black with red right child - // Recolor - if let parentX = x.parent { - sibling.color = parentX.color - parentX.color = .black - // a. x left and sibling with red right child - if x.isLeftChild { - sibling.rightChild?.color = .black - // Rotate - leftRotate(node: parentX) - } - // b. x right and sibling with red left child - else { - sibling.leftChild?.color = .black - //Rotate - rightRotate(node: parentX) - } - // We have a valid red-black-tree - xTmp = root - } - } - } - xTmp.color = .black - } + root = nodeX + } + if nodeY != z { + z.key = nodeY.key + } + // If sliced out node was red -> nothing to do as red-black-property holds + // If it was black -> fix red-black-property + if nodeY.color == .black { + deleteFixup(node: nodeX) + } + } + + /* + * Fixes possible violations of the red-black property after deletion + * We have w distinct cases: only case 2 may repeat, but only h many steps, where h is the height + * of the tree + * - case 1 -> case 2 -> red-black tree + * case 1 -> case 3 -> case 4 -> red-black tree + * case 1 -> case 4 -> red-black tree + * - case 3 -> case 4 -> red-black tree + * - case 4 -> red-black tree + */ + private func deleteFixup(node x: RBNode) { + var xTmp = x + if !x.isRoot && x.color == .black { + guard var sibling = x.sibling else { + return + } + // Case 1: Sibling of x is red + if sibling.color == .red { + // Recolor + sibling.color = .black + if let parentX = x.parent { + parentX.color = .red + // Rotation + if x.isLeftChild { + leftRotate(node: parentX) + } else { + rightRotate(node: parentX) + } + // Update sibling + if let sibl = x.sibling { + sibling = sibl + } + } + } + // Case 2: Sibling is black with two black children + if sibling.leftChild?.color == .black && sibling.rightChild?.color == .black { + // Recolor + sibling.color = .red + // Move fake black unit upwards + if let parentX = x.parent { + deleteFixup(node: parentX) + } + // We have a valid red-black-tree + } else { + // Case 3: a. Sibling black with one black child to the right + if x.isLeftChild && sibling.rightChild?.color == .black { + // Recolor + sibling.leftChild?.color = .black + sibling.color = .red + // Rotate + rightRotate(node: sibling) + // Update sibling of x + if let sibl = x.sibling { + sibling = sibl + } + } + // Still case 3: b. One black child to the left + else if x.isRightChild && sibling.leftChild?.color == .black { + // Recolor + sibling.rightChild?.color = .black + sibling.color = .red + // Rotate + leftRotate(node: sibling) + // Update sibling of x + if let sibl = x.sibling { + sibling = sibl + } + } + // Case 4: Sibling is black with red right child + // Recolor + if let parentX = x.parent { + sibling.color = parentX.color + parentX.color = .black + // a. x left and sibling with red right child + if x.isLeftChild { + sibling.rightChild?.color = .black + // Rotate + leftRotate(node: parentX) + } + // b. x right and sibling with red left child + else { + sibling.leftChild?.color = .black + //Rotate + rightRotate(node: parentX) + } + // We have a valid red-black-tree + xTmp = root + } + } + } + xTmp.color = .black + } } // MARK: - Rotation extension RedBlackTree { - /* - * Left rotation around node x - * Assumes that x.rightChild y is not a nullLeaf, rotates around the link from x to y, - * makes y the new root of the subtree with x as y's left child and y's left child as x's right - * child, where n = a node, [n] = a subtree - * | | - * x y - * / \ ~> / \ - * [A] y x [C] - * / \ / \ - * [B] [C] [A] [B] - */ - fileprivate func leftRotate(node x: RBNode) { - rotate(node: x, direction: .left) - } - - /* - * Right rotation around node y - * Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, - * makes x the new root of the subtree with y as x's right child and x's right child as y's left - * child, where n = a node, [n] = a subtree - * | | - * x y - * / \ <~ / \ - * [A] y x [C] - * / \ / \ - * [B] [C] [A] [B] - */ - fileprivate func rightRotate(node x: RBNode) { - rotate(node: x, direction: .right) - } - - /* - * Rotation around a node x - * Is a local operation preserving the binary-search-tree property that only exchanges pointers. - * Runntime: O(1) - */ - private func rotate(node x: RBNode, direction: RotationDirection) { - var nodeY: RBNode? = RBNode() - - // Set |nodeY| and turn |nodeY|'s left/right subtree into |x|'s right/left subtree - switch direction { - case .left: - nodeY = x.rightChild - x.rightChild = nodeY?.leftChild - x.rightChild?.parent = x - case .right: - nodeY = x.leftChild - x.leftChild = nodeY?.rightChild - x.leftChild?.parent = x - } - - // Link |x|'s parent to nodeY - nodeY?.parent = x.parent - if x.isRoot { - if let node = nodeY { - root = node - } - } else if x.isLeftChild { - x.parent?.leftChild = nodeY - } else if x.isRightChild { - x.parent?.rightChild = nodeY - } - - // Put |x| on |nodeY|'s left - switch direction { - case .left: - nodeY?.leftChild = x - case .right: - nodeY?.rightChild = x - } - x.parent = nodeY - } + /* + * Left rotation around node x + * Assumes that x.rightChild y is not a nullLeaf, rotates around the link from x to y, + * makes y the new root of the subtree with x as y's left child and y's left child as x's right + * child, where n = a node, [n] = a subtree + * | | + * x y + * / \ ~> / \ + * [A] y x [C] + * / \ / \ + * [B] [C] [A] [B] + */ + fileprivate func leftRotate(node x: RBNode) { + rotate(node: x, direction: .left) + } + + /* + * Right rotation around node y + * Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, + * makes x the new root of the subtree with y as x's right child and x's right child as y's left + * child, where n = a node, [n] = a subtree + * | | + * x y + * / \ <~ / \ + * [A] y x [C] + * / \ / \ + * [B] [C] [A] [B] + */ + fileprivate func rightRotate(node x: RBNode) { + rotate(node: x, direction: .right) + } + + /* + * Rotation around a node x + * Is a local operation preserving the binary-search-tree property that only exchanges pointers. + * Runntime: O(1) + */ + private func rotate(node x: RBNode, direction: RotationDirection) { + var nodeY: RBNode? = RBNode() + + // Set |nodeY| and turn |nodeY|'s left/right subtree into |x|'s right/left subtree + switch direction { + case .left: + nodeY = x.rightChild + x.rightChild = nodeY?.leftChild + x.rightChild?.parent = x + case .right: + nodeY = x.leftChild + x.leftChild = nodeY?.rightChild + x.leftChild?.parent = x + } + + // Link |x|'s parent to nodeY + nodeY?.parent = x.parent + if x.isRoot { + if let node = nodeY { + root = node + } + } else if x.isLeftChild { + x.parent?.leftChild = nodeY + } else if x.isRightChild { + x.parent?.rightChild = nodeY + } + + // Put |x| on |nodeY|'s left + switch direction { + case .left: + nodeY?.leftChild = x + case .right: + nodeY?.rightChild = x + } + x.parent = nodeY + } } // MARK: - Verify extension RedBlackTree { - /* - * Verifies that the existing tree fulfills all red-black properties - * Returns true if the tree is a valid red-black tree, false otherwise - */ - public func verify() -> Bool { - if root.isNullLeaf { - print("The tree is empty") - return true - } - return property2() && property4() && property5() - } - - // Property 1: Every node is either red or black -> fullfilled through setting node.color of type - // RBTreeColor - - // Property 2: The root is black - private func property2() -> Bool { - if root.color == .red { - print("Property-Error: Root is red") - return false - } - return true - } - - // Property 3: Every nullLeaf is black -> fullfilled through initialising nullLeafs with color = black - - // Property 4: If a node is red, then both its children are black - private func property4() -> Bool { - return property4(node: root) - } - - private func property4(node: RBNode) -> Bool { - if node.isNullLeaf { - return true - } - if let leftChild = node.leftChild, let rightChild = node.rightChild { - if node.color == .red { - if !leftChild.isNullLeaf && leftChild.color == .red { - print("Property-Error: Red node with key \(String(describing: node.key)) has red left child") - return false - } - if !rightChild.isNullLeaf && rightChild.color == .red { - print("Property-Error: Red node with key \(String(describing: node.key)) has red right child") - return false - } - } - return property4(node: leftChild) && property4(node: rightChild) - } - return false - } - - // Property 5: For each node, all paths from the node to descendant leaves contain the same number - // of black nodes (same blackheight) - private func property5() -> Bool { - if property5(node: root) == -1 { - return false - } else { - return true - } - } - - private func property5(node: RBNode) -> Int { - if node.isNullLeaf { - return 0 - } - guard let leftChild = node.leftChild, let rightChild = node.rightChild else { - return -1 - } - let left = property5(node: leftChild) - let right = property5(node: rightChild) - - if left == -1 || right == -1 { - return -1 - } else if left == right { - let addedHeight = node.color == .black ? 1 : 0 - return left + addedHeight - } else { - print("Property-Error: Black height violated at node with key \(String(describing: node.key))") - return -1 - } - } + /* + * Verifies that the existing tree fulfills all red-black properties + * Returns true if the tree is a valid red-black tree, false otherwise + */ + public func verify() -> Bool { + if root.isNullLeaf { + print("The tree is empty") + return true + } + return property2() && property4() && property5() + } + + // Property 1: Every node is either red or black -> fullfilled through setting node.color of type + // RBTreeColor + + // Property 2: The root is black + private func property2() -> Bool { + if root.color == .red { + print("Property-Error: Root is red") + return false + } + return true + } + + // Property 3: Every nullLeaf is black -> fullfilled through initialising nullLeafs with color = black + + // Property 4: If a node is red, then both its children are black + private func property4() -> Bool { + return property4(node: root) + } + + private func property4(node: RBNode) -> Bool { + if node.isNullLeaf { + return true + } + if let leftChild = node.leftChild, let rightChild = node.rightChild { + if node.color == .red { + if !leftChild.isNullLeaf && leftChild.color == .red { + print("Property-Error: Red node with key \(String(describing: node.key)) has red left child") + return false + } + if !rightChild.isNullLeaf && rightChild.color == .red { + print("Property-Error: Red node with key \(String(describing: node.key)) has red right child") + return false + } + } + return property4(node: leftChild) && property4(node: rightChild) + } + return false + } + + // Property 5: For each node, all paths from the node to descendant leaves contain the same number + // of black nodes (same blackheight) + private func property5() -> Bool { + if property5(node: root) == -1 { + return false + } else { + return true + } + } + + private func property5(node: RBNode) -> Int { + if node.isNullLeaf { + return 0 + } + guard let leftChild = node.leftChild, let rightChild = node.rightChild else { + return -1 + } + let left = property5(node: leftChild) + let right = property5(node: rightChild) + + if left == -1 || right == -1 { + return -1 + } else if left == right { + let addedHeight = node.color == .black ? 1 : 0 + return left + addedHeight + } else { + print("Property-Error: Black height violated at node with key \(String(describing: node.key))") + return -1 + } + } } // MARK: - Debugging extension RBTreeNode: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "" - if isNullLeaf { - s = "nullLeaf" - } else { - if let key = key { - s = "key: \(key)" - } else { - s = "key: nil" - } - if let parent = parent { - s += ", parent: \(String(describing: parent.key))" - } - if let left = leftChild { - s += ", left = [" + left.debugDescription + "]" - } - if let right = rightChild { - s += ", right = [" + right.debugDescription + "]" - } - s += ", color = \(color)" - } - return s - } + public var debugDescription: String { + var s = "" + if isNullLeaf { + s = "nullLeaf" + } else { + if let key = key { + s = "key: \(key)" + } else { + s = "key: nil" + } + if let parent = parent { + s += ", parent: \(String(describing: parent.key))" + } + if let left = leftChild { + s += ", left = [" + left.debugDescription + "]" + } + if let right = rightChild { + s += ", right = [" + right.debugDescription + "]" + } + s += ", color = \(color)" + } + return s + } } extension RedBlackTree: CustomDebugStringConvertible { - public var debugDescription: String { - return root.debugDescription - } + public var debugDescription: String { + return root.debugDescription + } } extension RBTreeNode: CustomStringConvertible { - public var description: String { - var s = "" - if isNullLeaf { - s += "nullLeaf" - } else { - if let left = leftChild { - s += "(\(left.description)) <- " - } - if let key = key { - s += "\(key)" - } else { - s += "nil" - } - s += ", \(color)" - if let right = rightChild { - s += " -> (\(right.description))" - } - } - return s - } + public var description: String { + var s = "" + if isNullLeaf { + s += "nullLeaf" + } else { + if let left = leftChild { + s += "(\(left.description)) <- " + } + if let key = key { + s += "\(key)" + } else { + s += "nil" + } + s += ", \(color)" + if let right = rightChild { + s += " -> (\(right.description))" + } + } + return s + } } extension RedBlackTree: CustomStringConvertible { - public var description: String { - if root.isNullLeaf { - return "[]" - } else { - return root.description + public var description: String { + if root.isNullLeaf { + return "[]" + } else { + return root.description + } } - } } diff --git a/Red-Black Tree/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.swift new file mode 100644 index 000000000..fc0411b42 --- /dev/null +++ b/Red-Black Tree/RedBlackTree.swift @@ -0,0 +1,795 @@ +//Copyright (c) 2016 Matthijs Hollemans and contributors +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files (the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included in +//all copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +//THE SOFTWARE. + +import Foundation + +private enum RBTreeColor { + case red + case black +} + +private enum RotationDirection { + case left + case right +} + +// MARK: - RBNode + +public class RBTreeNode: Equatable { + public typealias RBNode = RBTreeNode + + fileprivate var color: RBTreeColor = .black + fileprivate var key: T? + var leftChild: RBNode? + var rightChild: RBNode? + fileprivate weak var parent: RBNode? + + public init(key: T?, leftChild: RBNode?, rightChild: RBNode?, parent: RBNode?) { + self.key = key + self.leftChild = leftChild + self.rightChild = rightChild + self.parent = parent + + self.leftChild?.parent = self + self.rightChild?.parent = self + } + + public convenience init(key: T?) { + self.init(key: key, leftChild: RBNode(), rightChild: RBNode(), parent: RBNode()) + } + + // For initialising the nullLeaf + public convenience init() { + self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil) + self.color = .black + } + + var isRoot: Bool { + return parent == nil + } + + var isLeaf: Bool { + return rightChild == nil && leftChild == nil + } + + var isNullLeaf: Bool { + return key == nil && isLeaf && color == .black + } + + var isLeftChild: Bool { + return parent?.leftChild === self + } + + var isRightChild: Bool { + return parent?.rightChild === self + } + + var grandparent: RBNode? { + return parent?.parent + } + + var sibling: RBNode? { + if isLeftChild { + return parent?.rightChild + } else { + return parent?.leftChild + } + } + + var uncle: RBNode? { + return parent?.sibling + } +} + +// MARK: - RedBlackTree + +public class RedBlackTree { + public typealias RBNode = RBTreeNode + + fileprivate(set) var root: RBNode + fileprivate(set) var size = 0 + fileprivate let nullLeaf = RBNode() + fileprivate let allowDuplicateNode: Bool + + public init(_ allowDuplicateNode: Bool = false) { + root = nullLeaf + self.allowDuplicateNode = allowDuplicateNode + } +} + +// MARK: - Size + +extension RedBlackTree { + public func count() -> Int { + return size + } + + public func isEmpty() -> Bool { + return size == 0 + } + + public func allElements() -> [T] { + var nodes: [T] = [] + + getAllElements(node: root, nodes: &nodes) + + return nodes + } + + private func getAllElements(node: RBTreeNode, nodes: inout [T]) { + guard !node.isNullLeaf else { + return + } + + if let left = node.leftChild { + getAllElements(node: left, nodes: &nodes) + } + + if let key = node.key { + nodes.append(key) + } + + if let right = node.rightChild { + getAllElements(node: right, nodes: &nodes) + } + } +} + +// MARK: - Equatable protocol + +extension RBTreeNode { + static public func == (lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { + return lhs.key == rhs.key + } +} + +// MARK: - Finding a nodes successor + +extension RBTreeNode { + /* + * Returns the inorder successor node of a node + * The successor is a node with the next larger key value of the current node + */ + public func getSuccessor() -> RBNode? { + // If node has right child: successor min of this right tree + if let rightChild = self.rightChild { + if !rightChild.isNullLeaf { + return rightChild.minimum() + } + } + // Else go upward until node left child + var currentNode = self + var parent = currentNode.parent + while currentNode.isRightChild { + if let parent = parent { + currentNode = parent + } + parent = currentNode.parent + } + return parent + } +} + +// MARK: - Searching + +extension RBTreeNode { + /* + * Returns the node with the minimum key of the current subtree + */ + public func minimum() -> RBNode? { + if let leftChild = leftChild { + if !leftChild.isNullLeaf { + return leftChild.minimum() + } + return self + } + return self + } + + /* + * Returns the node with the maximum key of the current subtree + */ + public func maximum() -> RBNode? { + if let rightChild = rightChild { + if !rightChild.isNullLeaf { + return rightChild.maximum() + } + return self + } + return self + } +} + +extension RedBlackTree { + /* + * Returns the node with the given key |input| if existing + */ + public func search(input: T) -> RBNode? { + return search(key: input, node: root) + } + + /* + * Returns the node with given |key| in subtree of |node| + */ + fileprivate func search(key: T, node: RBNode?) -> RBNode? { + // If node nil -> key not found + guard let node = node else { + return nil + } + // If node is nullLeaf == semantically same as if nil + if !node.isNullLeaf { + if let nodeKey = node.key { + // Node found + if key == nodeKey { + return node + } else if key < nodeKey { + return search(key: key, node: node.leftChild) + } else { + return search(key: key, node: node.rightChild) + } + } + } + return nil + } +} + +// MARK: - Finding maximum and minimum value + +extension RedBlackTree { + /* + * Returns the minimum key value of the whole tree + */ + public func minValue() -> T? { + guard let minNode = root.minimum() else { + return nil + } + return minNode.key + } + + /* + * Returns the maximum key value of the whole tree + */ + public func maxValue() -> T? { + guard let maxNode = root.maximum() else { + return nil + } + return maxNode.key + } +} + +// MARK: - Inserting new nodes + +extension RedBlackTree { + /* + * Insert a node with key |key| into the tree + * 1. Perform normal insert operation as in a binary search tree + * 2. Fix red-black properties + * Runntime: O(log n) + */ + public func insert(key: T) { + // If key must be unique and find the key already existed, quit + if search(input: key) != nil && !allowDuplicateNode { + return + } + + if root.isNullLeaf { + root = RBNode(key: key) + } else { + insert(input: RBNode(key: key), node: root) + } + + size += 1 + } + + /* + * Nearly identical insert operation as in a binary search tree + * Differences: All nil pointers are replaced by the nullLeaf, we color the inserted node red, + * after inserting we call insertFixup to maintain the red-black properties + */ + private func insert(input: RBNode, node: RBNode) { + guard let inputKey = input.key, let nodeKey = node.key else { + return + } + if inputKey < nodeKey { + guard let child = node.leftChild else { + addAsLeftChild(child: input, parent: node) + return + } + if child.isNullLeaf { + addAsLeftChild(child: input, parent: node) + } else { + insert(input: input, node: child) + } + } else { + guard let child = node.rightChild else { + addAsRightChild(child: input, parent: node) + return + } + if child.isNullLeaf { + addAsRightChild(child: input, parent: node) + } else { + insert(input: input, node: child) + } + } + } + + private func addAsLeftChild(child: RBNode, parent: RBNode) { + parent.leftChild = child + child.parent = parent + child.color = .red + insertFixup(node: child) + } + + private func addAsRightChild(child: RBNode, parent: RBNode) { + parent.rightChild = child + child.parent = parent + child.color = .red + insertFixup(node: child) + } + + /* + * Fixes possible violations of the red-black property after insertion + * Only violation of red-black properties occurs at inserted node |z| and z.parent + * We have 3 distinct cases: case 1, 2a and 2b + * - case 1: may repeat, but only h/2 steps, where h is the height of the tree + * - case 2a -> case 2b -> red-black tree + * - case 2b -> red-black tree + */ + private func insertFixup(node z: RBNode) { + if !z.isNullLeaf { + guard let parentZ = z.parent else { + return + } + // If both |z| and his parent are red -> violation of red-black property -> need to fix it + if parentZ.color == .red { + guard let uncle = z.uncle else { + return + } + // Case 1: Uncle red -> recolor + move z + if uncle.color == .red { + parentZ.color = .black + uncle.color = .black + if let grandparentZ = parentZ.parent { + grandparentZ.color = .red + // Move z to grandparent and check again + insertFixup(node: grandparentZ) + } + } + // Case 2: Uncle black + else { + var zNew = z + // Case 2.a: z right child -> rotate + if parentZ.isLeftChild && z.isRightChild { + zNew = parentZ + leftRotate(node: zNew) + } else if parentZ.isRightChild && z.isLeftChild { + zNew = parentZ + rightRotate(node: zNew) + } + // Case 2.b: z left child -> recolor + rotate + zNew.parent?.color = .black + if let grandparentZnew = zNew.grandparent { + grandparentZnew.color = .red + if z.isLeftChild { + rightRotate(node: grandparentZnew) + } else { + leftRotate(node: grandparentZnew) + } + // We have a valid red-black-tree + } + } + } + } + root.color = .black + } +} + +// MARK: - Deleting a node +extension RedBlackTree { + /* + * Delete a node with key |key| from the tree + * 1. Perform standard delete operation as in a binary search tree + * 2. Fix red-black properties + * Runntime: O(log n) + */ + public func delete(key: T) { + if size == 1 { + root = nullLeaf + size -= 1 + } else if let node = search(key: key, node: root) { + if !node.isNullLeaf { + delete(node: node) + size -= 1 + } + } + } + + /* + * Nearly identical delete operation as in a binary search tree + * Differences: All nil pointers are replaced by the nullLeaf, + * after deleting we call insertFixup to maintain the red-black properties if the delted node was + * black (as if it was red -> no violation of red-black properties) + */ + private func delete(node z: RBNode) { + var nodeY = RBNode() + var nodeX = RBNode() + if let leftChild = z.leftChild, let rightChild = z.rightChild { + if leftChild.isNullLeaf || rightChild.isNullLeaf { + nodeY = z + } else { + if let successor = z.getSuccessor() { + nodeY = successor + } + } + } + if let leftChild = nodeY.leftChild { + if !leftChild.isNullLeaf { + nodeX = leftChild + } else if let rightChild = nodeY.rightChild { + nodeX = rightChild + } + } + nodeX.parent = nodeY.parent + if let parentY = nodeY.parent { + // Should never be the case, as parent of root = nil + if parentY.isNullLeaf { + root = nodeX + } else { + if nodeY.isLeftChild { + parentY.leftChild = nodeX + } else { + parentY.rightChild = nodeX + } + } + } else { + root = nodeX + } + if nodeY != z { + z.key = nodeY.key + } + // If sliced out node was red -> nothing to do as red-black-property holds + // If it was black -> fix red-black-property + if nodeY.color == .black { + deleteFixup(node: nodeX) + } + } + + /* + * Fixes possible violations of the red-black property after deletion + * We have w distinct cases: only case 2 may repeat, but only h many steps, where h is the height + * of the tree + * - case 1 -> case 2 -> red-black tree + * case 1 -> case 3 -> case 4 -> red-black tree + * case 1 -> case 4 -> red-black tree + * - case 3 -> case 4 -> red-black tree + * - case 4 -> red-black tree + */ + private func deleteFixup(node x: RBNode) { + var xTmp = x + if !x.isRoot && x.color == .black { + guard var sibling = x.sibling else { + return + } + // Case 1: Sibling of x is red + if sibling.color == .red { + // Recolor + sibling.color = .black + if let parentX = x.parent { + parentX.color = .red + // Rotation + if x.isLeftChild { + leftRotate(node: parentX) + } else { + rightRotate(node: parentX) + } + // Update sibling + if let sibl = x.sibling { + sibling = sibl + } + } + } + // Case 2: Sibling is black with two black children + if sibling.leftChild?.color == .black && sibling.rightChild?.color == .black { + // Recolor + sibling.color = .red + // Move fake black unit upwards + if let parentX = x.parent { + deleteFixup(node: parentX) + } + // We have a valid red-black-tree + } else { + // Case 3: a. Sibling black with one black child to the right + if x.isLeftChild && sibling.rightChild?.color == .black { + // Recolor + sibling.leftChild?.color = .black + sibling.color = .red + // Rotate + rightRotate(node: sibling) + // Update sibling of x + if let sibl = x.sibling { + sibling = sibl + } + } + // Still case 3: b. One black child to the left + else if x.isRightChild && sibling.leftChild?.color == .black { + // Recolor + sibling.rightChild?.color = .black + sibling.color = .red + // Rotate + leftRotate(node: sibling) + // Update sibling of x + if let sibl = x.sibling { + sibling = sibl + } + } + // Case 4: Sibling is black with red right child + // Recolor + if let parentX = x.parent { + sibling.color = parentX.color + parentX.color = .black + // a. x left and sibling with red right child + if x.isLeftChild { + sibling.rightChild?.color = .black + // Rotate + leftRotate(node: parentX) + } + // b. x right and sibling with red left child + else { + sibling.leftChild?.color = .black + //Rotate + rightRotate(node: parentX) + } + // We have a valid red-black-tree + xTmp = root + } + } + } + xTmp.color = .black + } +} + +// MARK: - Rotation +extension RedBlackTree { + /* + * Left rotation around node x + * Assumes that x.rightChild y is not a nullLeaf, rotates around the link from x to y, + * makes y the new root of the subtree with x as y's left child and y's left child as x's right + * child, where n = a node, [n] = a subtree + * | | + * x y + * / \ ~> / \ + * [A] y x [C] + * / \ / \ + * [B] [C] [A] [B] + */ + fileprivate func leftRotate(node x: RBNode) { + rotate(node: x, direction: .left) + } + + /* + * Right rotation around node y + * Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, + * makes x the new root of the subtree with y as x's right child and x's right child as y's left + * child, where n = a node, [n] = a subtree + * | | + * x y + * / \ <~ / \ + * [A] y x [C] + * / \ / \ + * [B] [C] [A] [B] + */ + fileprivate func rightRotate(node x: RBNode) { + rotate(node: x, direction: .right) + } + + /* + * Rotation around a node x + * Is a local operation preserving the binary-search-tree property that only exchanges pointers. + * Runntime: O(1) + */ + private func rotate(node x: RBNode, direction: RotationDirection) { + var nodeY: RBNode? = RBNode() + + // Set |nodeY| and turn |nodeY|'s left/right subtree into |x|'s right/left subtree + switch direction { + case .left: + nodeY = x.rightChild + x.rightChild = nodeY?.leftChild + x.rightChild?.parent = x + case .right: + nodeY = x.leftChild + x.leftChild = nodeY?.rightChild + x.leftChild?.parent = x + } + + // Link |x|'s parent to nodeY + nodeY?.parent = x.parent + if x.isRoot { + if let node = nodeY { + root = node + } + } else if x.isLeftChild { + x.parent?.leftChild = nodeY + } else if x.isRightChild { + x.parent?.rightChild = nodeY + } + + // Put |x| on |nodeY|'s left + switch direction { + case .left: + nodeY?.leftChild = x + case .right: + nodeY?.rightChild = x + } + x.parent = nodeY + } +} + +// MARK: - Verify +extension RedBlackTree { + /* + * Verifies that the existing tree fulfills all red-black properties + * Returns true if the tree is a valid red-black tree, false otherwise + */ + public func verify() -> Bool { + if root.isNullLeaf { + print("The tree is empty") + return true + } + return property2() && property4() && property5() + } + + // Property 1: Every node is either red or black -> fullfilled through setting node.color of type + // RBTreeColor + + // Property 2: The root is black + private func property2() -> Bool { + if root.color == .red { + print("Property-Error: Root is red") + return false + } + return true + } + + // Property 3: Every nullLeaf is black -> fullfilled through initialising nullLeafs with color = black + + // Property 4: If a node is red, then both its children are black + private func property4() -> Bool { + return property4(node: root) + } + + private func property4(node: RBNode) -> Bool { + if node.isNullLeaf { + return true + } + if let leftChild = node.leftChild, let rightChild = node.rightChild { + if node.color == .red { + if !leftChild.isNullLeaf && leftChild.color == .red { + print("Property-Error: Red node with key \(String(describing: node.key)) has red left child") + return false + } + if !rightChild.isNullLeaf && rightChild.color == .red { + print("Property-Error: Red node with key \(String(describing: node.key)) has red right child") + return false + } + } + return property4(node: leftChild) && property4(node: rightChild) + } + return false + } + + // Property 5: For each node, all paths from the node to descendant leaves contain the same number + // of black nodes (same blackheight) + private func property5() -> Bool { + if property5(node: root) == -1 { + return false + } else { + return true + } + } + + private func property5(node: RBNode) -> Int { + if node.isNullLeaf { + return 0 + } + guard let leftChild = node.leftChild, let rightChild = node.rightChild else { + return -1 + } + let left = property5(node: leftChild) + let right = property5(node: rightChild) + + if left == -1 || right == -1 { + return -1 + } else if left == right { + let addedHeight = node.color == .black ? 1 : 0 + return left + addedHeight + } else { + print("Property-Error: Black height violated at node with key \(String(describing: node.key))") + return -1 + } + } +} + +// MARK: - Debugging + +extension RBTreeNode: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "" + if isNullLeaf { + s = "nullLeaf" + } else { + if let key = key { + s = "key: \(key)" + } else { + s = "key: nil" + } + if let parent = parent { + s += ", parent: \(String(describing: parent.key))" + } + if let left = leftChild { + s += ", left = [" + left.debugDescription + "]" + } + if let right = rightChild { + s += ", right = [" + right.debugDescription + "]" + } + s += ", color = \(color)" + } + return s + } +} + +extension RedBlackTree: CustomDebugStringConvertible { + public var debugDescription: String { + return root.debugDescription + } +} + +extension RBTreeNode: CustomStringConvertible { + public var description: String { + var s = "" + if isNullLeaf { + s += "nullLeaf" + } else { + if let left = leftChild { + s += "(\(left.description)) <- " + } + if let key = key { + s += "\(key)" + } else { + s += "nil" + } + s += ", \(color)" + if let right = rightChild { + s += " -> (\(right.description))" + } + } + return s + } +} + +extension RedBlackTree: CustomStringConvertible { + public var description: String { + if root.isNullLeaf { + return "[]" + } else { + return root.description + } + } +} From 7cb8185679cdc3acf38e9123ef7503fba5b4d116 Mon Sep 17 00:00:00 2001 From: Alejandro Isaza Date: Sat, 7 Oct 2017 15:50:19 -0700 Subject: [PATCH 02/65] Add A* algorithm --- A-Star/AStar.swift | 153 +++++++++ A-Star/README.md | 7 + A-Star/Tests/AStarTests.swift | 57 ++++ .../AStarTests.xcodeproj/project.pbxproj | 291 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + A-Star/Tests/Info.plist | 24 ++ Hashed Heap/HashedHeap.swift | 13 +- .../contents.xcworkspacedata | 23 ++ 8 files changed, 574 insertions(+), 1 deletion(-) create mode 100644 A-Star/AStar.swift create mode 100644 A-Star/README.md create mode 100755 A-Star/Tests/AStarTests.swift create mode 100644 A-Star/Tests/AStarTests.xcodeproj/project.pbxproj create mode 100644 A-Star/Tests/AStarTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 A-Star/Tests/Info.plist diff --git a/A-Star/AStar.swift b/A-Star/AStar.swift new file mode 100644 index 000000000..41a9fac6c --- /dev/null +++ b/A-Star/AStar.swift @@ -0,0 +1,153 @@ +// Written by Alejandro Isaza. + +import Foundation + +public protocol Graph { + associatedtype Vertex: Hashable + associatedtype Edge: WeightedEdge where Edge.Vertex == Vertex + + /// Lists all edges going out from a vertex. + func edgesOutgoing(from vertex: Vertex) -> [Edge] +} + +public protocol WeightedEdge { + associatedtype Vertex + + /// The edge's cost. + var cost: Double { get } + + /// The target vertex. + var target: Vertex { get } +} + +public final class AStar { + /// The graph to search on. + public let graph: G + + /// The heuristic cost function that estimates the cost between two vertices. + /// + /// - Note: The heuristic function needs to always return a value that is lower-than or equal to the actual + /// cost for the resulting path of the A* search to be optimal. + public let heuristic: (G.Vertex, G.Vertex) -> Double + + /// Open list of nodes to expand. + private var open: HashedHeap> + + /// Closed list of vertices already expanded. + private var closed = Set() + + /// Actual vertex cost for vertices we already encountered (refered to as `g` on the literature). + private var costs = Dictionary() + + /// Store the previous node for each expanded node to recreate the path. + private var parents = Dictionary() + + /// Initializes `AStar` with a graph and a heuristic cost function. + public init(graph: G, heuristic: @escaping (G.Vertex, G.Vertex) -> Double) { + self.graph = graph + self.heuristic = heuristic + open = HashedHeap(sort: <) + } + + /// Finds an optimal path between `source` and `target`. + /// + /// - Precondition: both `source` and `target` belong to `graph`. + public func path(start: G.Vertex, target: G.Vertex) -> [G.Vertex] { + open.insert(Node(vertex: start, cost: 0, estimate: heuristic(start, target))) + while !open.isEmpty { + guard let node = open.remove() else { + break + } + costs[node.vertex] = node.cost + + if (node.vertex == target) { + let path = buildPath(start: start, target: target) + cleanup() + return path + } + + if !closed.contains(node.vertex) { + expand(node: node, target: target) + closed.insert(node.vertex) + } + } + + // No path found + return [] + } + + private func expand(node: Node, target: G.Vertex) { + let edges = graph.edgesOutgoing(from: node.vertex) + for edge in edges { + let g = cost(node.vertex) + edge.cost + if g < cost(edge.target) { + open.insert(Node(vertex: edge.target, cost: g, estimate: heuristic(edge.target, target))) + parents[edge.target] = node.vertex + } + } + } + + private func cost(_ vertex: G.Edge.Vertex) -> Double { + if let c = costs[vertex] { + return c + } + + let node = Node(vertex: vertex, cost: Double.greatestFiniteMagnitude, estimate: 0) + if let index = open.index(of: node) { + return open[index].cost + } + + return Double.greatestFiniteMagnitude + } + + private func buildPath(start: G.Vertex, target: G.Vertex) -> [G.Vertex] { + var path = Array() + path.append(target) + + var current = target + while current != start { + guard let parent = parents[current] else { + return [] // no path found + } + current = parent + path.append(current) + } + + return path.reversed() + } + + private func cleanup() { + open.removeAll() + closed.removeAll() + parents.removeAll() + } +} + +private struct Node: Hashable, Comparable { + /// The graph vertex. + var vertex: V + + /// The actual cost between the start vertex and this vertex. + var cost: Double + + /// Estimated (heuristic) cost betweent this vertex and the target vertex. + var estimate: Double + + public init(vertex: V, cost: Double, estimate: Double) { + self.vertex = vertex + self.cost = cost + self.estimate = estimate + } + + static func < (lhs: Node, rhs: Node) -> Bool { + return lhs.cost + lhs.estimate < rhs.cost + rhs.estimate + } + + static func == (lhs: Node, rhs: Node) -> Bool { + return lhs.vertex == rhs.vertex + } + + var hashValue: Int { + return vertex.hashValue + } +} diff --git a/A-Star/README.md b/A-Star/README.md new file mode 100644 index 000000000..cafd5027a --- /dev/null +++ b/A-Star/README.md @@ -0,0 +1,7 @@ +# A* + +A* (pronounced "ay star") is a heuristic best-first search algorithm. A* minimizes node expansions, therefore minimizing the search time, by using a heuristic function. The heuristic function gives an estimate of the distance between two vertices. For instance if you are searching for a path between two points in a city, you can estimate the actual street distance with the straight-line distance. + +A* works by expanding the most promising nodes first, according to the heuristic function. In the city example it would choose streets which go in the general direction of the target first and, only if those are dead ends, backtrack and try other streets. This speeds up search in most sitations. + +A* is optimal (it always find the shortest path) if the heuristic function is admissible. A heuristic function is admissible if it never overestimates the cost of reaching the goal. In the extreme case of the heuristic function always retuning `0` A* acts exactly the same as [Dijkstra's Algorithm](../Dijkstra). The closer the heuristic function is the the actual distance the faster the search. diff --git a/A-Star/Tests/AStarTests.swift b/A-Star/Tests/AStarTests.swift new file mode 100755 index 000000000..87f674cd5 --- /dev/null +++ b/A-Star/Tests/AStarTests.swift @@ -0,0 +1,57 @@ +import Foundation +import XCTest + +struct GridGraph: Graph { + struct Vertex: Hashable { + var x: Int + var y: Int + + static func == (lhs: Vertex, rhs: Vertex) -> Bool { + return lhs.x == rhs.x && lhs.y == rhs.y + } + + public var hashValue: Int { + return x.hashValue ^ y.hashValue + } + } + + struct Edge: WeightedEdge { + var cost: Double + var target: Vertex + } + + func edgesOutgoing(from vertex: Vertex) -> [Edge] { + return [ + Edge(cost: 1, target: Vertex(x: vertex.x - 1, y: vertex.y)), + Edge(cost: 1, target: Vertex(x: vertex.x + 1, y: vertex.y)), + Edge(cost: 1, target: Vertex(x: vertex.x, y: vertex.y - 1)), + Edge(cost: 1, target: Vertex(x: vertex.x, y: vertex.y + 1)), + ] + } +} + +class AStarTests: XCTestCase { + func testSameStartAndEnd() { + let graph = GridGraph() + let astar = AStar(graph: graph, heuristic: manhattanDistance) + let path = astar.path(start: GridGraph.Vertex(x: 0, y: 0), target: GridGraph.Vertex(x: 0, y: 0)) + XCTAssertEqual(path.count, 1) + XCTAssertEqual(path[0].x, 0) + XCTAssertEqual(path[0].y, 0) + } + + func testDiagonal() { + let graph = GridGraph() + let astar = AStar(graph: graph, heuristic: manhattanDistance) + let path = astar.path(start: GridGraph.Vertex(x: 0, y: 0), target: GridGraph.Vertex(x: 10, y: 10)) + XCTAssertEqual(path.count, 21) + XCTAssertEqual(path[0].x, 0) + XCTAssertEqual(path[0].y, 0) + XCTAssertEqual(path[20].x, 10) + XCTAssertEqual(path[20].y, 10) + } + + func manhattanDistance(_ s: GridGraph.Vertex, _ t: GridGraph.Vertex) -> Double { + return Double(abs(s.x - t.x) + abs(s.y - t.y)) + } +} diff --git a/A-Star/Tests/AStarTests.xcodeproj/project.pbxproj b/A-Star/Tests/AStarTests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..cacd1e5ae --- /dev/null +++ b/A-Star/Tests/AStarTests.xcodeproj/project.pbxproj @@ -0,0 +1,291 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 611D099C1F8978AB00C7092B /* AStarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611D099B1F8978AB00C7092B /* AStarTests.swift */; }; + 611D099E1F8978BC00C7092B /* AStar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611D099D1F8978BB00C7092B /* AStar.swift */; }; + 611D09A01F89795100C7092B /* HashedHeap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611D099F1F89795100C7092B /* HashedHeap.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 611D099B1F8978AB00C7092B /* AStarTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AStarTests.swift; sourceTree = ""; }; + 611D099D1F8978BB00C7092B /* AStar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AStar.swift; path = ../AStar.swift; sourceTree = ""; }; + 611D099F1F89795100C7092B /* HashedHeap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HashedHeap.swift; path = "../../Hashed Heap/HashedHeap.swift"; sourceTree = ""; }; + 7B2BBC801C779D720067B71D /* AStarTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AStarTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7B2BBC7D1C779D720067B71D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7B2BBC681C779D710067B71D = { + isa = PBXGroup; + children = ( + 7B2BBC831C779D720067B71D /* Tests */, + 7B2BBC721C779D710067B71D /* Products */, + ); + sourceTree = ""; + }; + 7B2BBC721C779D710067B71D /* Products */ = { + isa = PBXGroup; + children = ( + 7B2BBC801C779D720067B71D /* AStarTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 7B2BBC831C779D720067B71D /* Tests */ = { + isa = PBXGroup; + children = ( + 611D099F1F89795100C7092B /* HashedHeap.swift */, + 611D099D1F8978BB00C7092B /* AStar.swift */, + 611D099B1F8978AB00C7092B /* AStarTests.swift */, + 7B2BBC941C779E7B0067B71D /* Info.plist */, + ); + name = Tests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 7B2BBC7F1C779D720067B71D /* AStarTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "AStarTests" */; + buildPhases = ( + 7B2BBC7C1C779D720067B71D /* Sources */, + 7B2BBC7D1C779D720067B71D /* Frameworks */, + 7B2BBC7E1C779D720067B71D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AStarTests; + productName = TestsTests; + productReference = 7B2BBC801C779D720067B71D /* AStarTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7B2BBC691C779D710067B71D /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0900; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 7B2BBC7F1C779D720067B71D = { + CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0900; + }; + }; + }; + buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "AStarTests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 7B2BBC681C779D710067B71D; + productRefGroup = 7B2BBC721C779D710067B71D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7B2BBC7F1C779D720067B71D /* AStarTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 7B2BBC7E1C779D720067B71D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 7B2BBC7C1C779D720067B71D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 611D099C1F8978AB00C7092B /* AStarTests.swift in Sources */, + 611D099E1F8978BC00C7092B /* AStar.swift in Sources */, + 611D09A01F89795100C7092B /* HashedHeap.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7B2BBC871C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + }; + name = Debug; + }; + 7B2BBC881C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + }; + name = Release; + }; + 7B2BBC8D1C779D720067B71D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 7B2BBC8E1C779D720067B71D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "AStarTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC871C779D720067B71D /* Debug */, + 7B2BBC881C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "AStarTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7B2BBC8D1C779D720067B71D /* Debug */, + 7B2BBC8E1C779D720067B71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7B2BBC691C779D710067B71D /* Project object */; +} diff --git a/A-Star/Tests/AStarTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/A-Star/Tests/AStarTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/A-Star/Tests/AStarTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/A-Star/Tests/Info.plist b/A-Star/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/A-Star/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Hashed Heap/HashedHeap.swift b/Hashed Heap/HashedHeap.swift index be7d9ab78..106cdacb0 100644 --- a/Hashed Heap/HashedHeap.swift +++ b/Hashed Heap/HashedHeap.swift @@ -57,7 +57,12 @@ public struct HashedHeap { public var count: Int { return elements.count } - + + /// Accesses an element by its index. + public subscript(index: Int) -> T { + return elements[index] + } + /// Returns the index of the given element. /// /// This is the operation that a hashed heap optimizes in compassion with a normal heap. In a normal heap this @@ -141,6 +146,12 @@ public struct HashedHeap { } return removeLast() } + + /// Removes all elements from the heap. + public mutating func removeAll() { + elements.removeAll() + indices.removeAll() + } /// Removes the last element from the heap. /// diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 4cab8e2d4..28fb4f1a7 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -38,6 +38,29 @@ + + + + + + + + + + + + + + From cb26964f1ea032be9fbe7b64f1f6e849d1fda5d5 Mon Sep 17 00:00:00 2001 From: Alejandro Isaza Date: Sat, 7 Oct 2017 15:53:59 -0700 Subject: [PATCH 03/65] Add to .travis.yml --- .travis.yml | 1 + .../xcschemes/AStarTests.xcscheme | 67 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 A-Star/Tests/AStarTests.xcodeproj/xcshareddata/xcschemes/AStarTests.xcscheme diff --git a/.travis.yml b/.travis.yml index 7cd02c9bc..30b54f140 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ install: script: +- xcodebuild test -project ./A-Star/Tests/AStarTests.xcodeproj -scheme AStarTests | xcpretty -f `xcpretty-travis-formatter` - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests | xcpretty -f `xcpretty-travis-formatter` - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests | xcpretty -f `xcpretty-travis-formatter` - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests | xcpretty -f `xcpretty-travis-formatter` diff --git a/A-Star/Tests/AStarTests.xcodeproj/xcshareddata/xcschemes/AStarTests.xcscheme b/A-Star/Tests/AStarTests.xcodeproj/xcshareddata/xcschemes/AStarTests.xcscheme new file mode 100644 index 000000000..5473b4c0c --- /dev/null +++ b/A-Star/Tests/AStarTests.xcodeproj/xcshareddata/xcschemes/AStarTests.xcscheme @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 2c2ec49e225861e9aa0da42b54e35c90f81ddbed Mon Sep 17 00:00:00 2001 From: Alejandro Isaza Date: Thu, 16 Nov 2017 22:17:19 -0800 Subject: [PATCH 04/65] Add example to README --- A-Star/Images/graph.dot | 12 ++++++++++++ A-Star/Images/graph.png | Bin 0 -> 20882 bytes A-Star/Images/step1.dot | 12 ++++++++++++ A-Star/Images/step1.png | Bin 0 -> 28753 bytes A-Star/Images/step2.dot | 12 ++++++++++++ A-Star/Images/step2.png | Bin 0 -> 29088 bytes A-Star/Images/step3.dot | 12 ++++++++++++ A-Star/Images/step3.png | Bin 0 -> 30158 bytes A-Star/Images/step4.dot | 12 ++++++++++++ A-Star/Images/step4.png | Bin 0 -> 30130 bytes A-Star/Images/step5.dot | 12 ++++++++++++ A-Star/Images/step5.png | Bin 0 -> 29802 bytes A-Star/Images/step6.dot | 12 ++++++++++++ A-Star/Images/step6.png | Bin 0 -> 29596 bytes A-Star/Images/step7.dot | 12 ++++++++++++ A-Star/Images/step7.png | Bin 0 -> 30012 bytes A-Star/README.md | 38 +++++++++++++++++++++++++++++++++++++- 17 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 A-Star/Images/graph.dot create mode 100644 A-Star/Images/graph.png create mode 100644 A-Star/Images/step1.dot create mode 100644 A-Star/Images/step1.png create mode 100644 A-Star/Images/step2.dot create mode 100644 A-Star/Images/step2.png create mode 100644 A-Star/Images/step3.dot create mode 100644 A-Star/Images/step3.png create mode 100644 A-Star/Images/step4.dot create mode 100644 A-Star/Images/step4.png create mode 100644 A-Star/Images/step5.dot create mode 100644 A-Star/Images/step5.png create mode 100644 A-Star/Images/step6.dot create mode 100644 A-Star/Images/step6.png create mode 100644 A-Star/Images/step7.dot create mode 100644 A-Star/Images/step7.png diff --git a/A-Star/Images/graph.dot b/A-Star/Images/graph.dot new file mode 100644 index 000000000..941d66232 --- /dev/null +++ b/A-Star/Images/graph.dot @@ -0,0 +1,12 @@ +digraph G { + rankdir=LR; + { A [ label = "h = 3" ] } + { rank = same; B [ label = "h = 2" ]; C [ label = "h = 2" ]; D [ label = "h = 2" ] } + { rank = same; E [ label = "h = 1" ]; F [ label = "h = 1" ]; G [ label = "h = 1" ] } + { H [ label = "h = 0", style = filled, color = green ] } + A -> { B C D } + B -> E + E -> F + D -> G + G -> H +} diff --git a/A-Star/Images/graph.png b/A-Star/Images/graph.png new file mode 100644 index 0000000000000000000000000000000000000000..c0a4b1cc8fd31a372f6843f858703950a0adee4a GIT binary patch literal 20882 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 literal 0 HcmV?d00001 diff --git a/A-Star/Images/step1.dot b/A-Star/Images/step1.dot new file mode 100644 index 000000000..5785aea4c --- /dev/null +++ b/A-Star/Images/step1.dot @@ -0,0 +1,12 @@ +digraph G { + rankdir=LR; + { A [ label = "g = 0\nh = 3", style = filled, color = deepskyblue1 ] } + { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; C [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; D [ label = "g = 1\nh = 2", style = filled, color = lightgrey ] } + { rank = same; E [ label = "g = \?\nh = 1" ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] } + { H [ label = "g = \?\nh = 0" ] } + A -> { B C D } + B -> E + E -> F + D -> G + G -> H +} diff --git a/A-Star/Images/step1.png b/A-Star/Images/step1.png new file mode 100644 index 0000000000000000000000000000000000000000..a983033a2046b0e1dfc674249f28f08956c3edee GIT binary patch literal 28753 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 LEu|U-i{SqS++pzp literal 0 HcmV?d00001 diff --git a/A-Star/Images/step2.dot b/A-Star/Images/step2.dot new file mode 100644 index 000000000..0c8a9d53d --- /dev/null +++ b/A-Star/Images/step2.dot @@ -0,0 +1,12 @@ +digraph G { + rankdir=LR; + { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } + { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = deepskyblue1 ]; C [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; D [ label = "g = 1\nh = 2", style = filled, color = lightgrey ] } + { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] } + { H [ label = "g = \?\nh = 0" ] } + A -> { B C D } + B -> E + E -> F + D -> G + G -> H +} diff --git a/A-Star/Images/step2.png b/A-Star/Images/step2.png new file mode 100644 index 0000000000000000000000000000000000000000..10b4300f406be65ffb0e356666ed5ce965b5ca32 GIT binary patch literal 29088 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 EA5Jd { B C D } + B -> E + E -> F + D -> G + G -> H +} diff --git a/A-Star/Images/step3.png b/A-Star/Images/step3.png new file mode 100644 index 0000000000000000000000000000000000000000..e195e7e8e11651f774405e1ca5be8bff514399dc GIT binary patch literal 30158 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 Of~umXLX{jW`2PX5&nCS9 literal 0 HcmV?d00001 diff --git a/A-Star/Images/step4.dot b/A-Star/Images/step4.dot new file mode 100644 index 000000000..16db76796 --- /dev/null +++ b/A-Star/Images/step4.dot @@ -0,0 +1,12 @@ +digraph G { + rankdir=LR; + { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } + { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = deepskyblue1 ] } + { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = 2\nh = 1", style = filled, color = lightgrey ] } + { H [ label = "g = \?\nh = 0" ] } + A -> { B C D } + B -> E + E -> F + D -> G + G -> H +} diff --git a/A-Star/Images/step4.png b/A-Star/Images/step4.png new file mode 100644 index 0000000000000000000000000000000000000000..c07f34c80d2d69d1960b66b547c16134541b34ef GIT binary patch literal 30130 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 literal 0 HcmV?d00001 diff --git a/A-Star/Images/step5.dot b/A-Star/Images/step5.dot new file mode 100644 index 000000000..2986b6a90 --- /dev/null +++ b/A-Star/Images/step5.dot @@ -0,0 +1,12 @@ +digraph G { + rankdir=LR; + { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } + { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] } + { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = deepskyblue1 ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = lightgrey ] } + { H [ label = "g = \?\nh = 0" ] } + A -> { B C D } + B -> E + E -> F + D -> G + G -> H +} diff --git a/A-Star/Images/step5.png b/A-Star/Images/step5.png new file mode 100644 index 0000000000000000000000000000000000000000..40a7008da206816baa056fa95d9f69c5b6db89ad GIT binary patch literal 29802 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 Y>gT576&OA6;h``x5{lwgqQ=4h3tFTHY5)KL literal 0 HcmV?d00001 diff --git a/A-Star/Images/step6.dot b/A-Star/Images/step6.dot new file mode 100644 index 000000000..b5e3179b6 --- /dev/null +++ b/A-Star/Images/step6.dot @@ -0,0 +1,12 @@ +digraph G { + rankdir=LR; + { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } + { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] } + { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightblue ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = deepskyblue1 ] } + { H [ label = "g = 3\nh = 0", style = filled, color = lightgrey ] } + A -> { B C D } + B -> E + E -> F + D -> G + G -> H +} diff --git a/A-Star/Images/step6.png b/A-Star/Images/step6.png new file mode 100644 index 0000000000000000000000000000000000000000..9e7baef2622aaea8538f6f4fcfce9fc732f5403d GIT binary patch literal 29596 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 z

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 literal 0 HcmV?d00001 diff --git a/A-Star/Images/step7.dot b/A-Star/Images/step7.dot new file mode 100644 index 000000000..c5b26b6b3 --- /dev/null +++ b/A-Star/Images/step7.dot @@ -0,0 +1,12 @@ +digraph G { + rankdir=LR; + { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } + { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] } + { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightblue ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = lightblue ] } + { H [ label = "g = 3\nh = 0", style = filled, color = deepskyblue1 ] } + A -> { B C D } + B -> E + E -> F + D -> G + G -> H +} diff --git a/A-Star/Images/step7.png b/A-Star/Images/step7.png new file mode 100644 index 0000000000000000000000000000000000000000..0eedd638f24c57f671dc6905bc7910369436fbe5 GIT binary patch literal 30012 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 Date: Wed, 10 Jan 2018 22:18:14 -0800 Subject: [PATCH 05/65] add update to readme --- Red-Black Tree/README.markdown | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Red-Black Tree/README.markdown b/Red-Black Tree/README.markdown index 74fffa415..6db827ea6 100644 --- a/Red-Black Tree/README.markdown +++ b/Red-Black Tree/README.markdown @@ -39,6 +39,9 @@ Tree: * `insert(key:)` Inserts the key value into the tree * `delete(key:)` Delete the node with the respective key value from the tree * `verify()` Verifies that the given tree fulfills the red-black tree properties +* `count()` Returns how many nodes in the tree +* `isEmpty()` Returns if the tree has no nodes +* `allElements()` Returns an array containing all nodes (in-order traversal) in the tree. The rotation, insertion and deletion algorithms are implemented based on the pseudo-code provided in [CLRS] From 027dc783bb15853c40f15bfd11daa9dcb7771120 Mon Sep 17 00:00:00 2001 From: Pragati <44121852+pragatiahuja@users.noreply.github.com> Date: Mon, 15 Oct 2018 23:50:03 +0530 Subject: [PATCH 06/65] final README Add recursive implementation for reversing a singly linked list. --- Linked List/README.markdown | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index 0c8431157..0998349fc 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -471,6 +471,7 @@ This will print the list like so: How about reversing a list, so that the head becomes the tail and vice versa? There is a very fast algorithm for that: +Iterative Approach: ```swift public func reverse() { var node = head @@ -482,6 +483,18 @@ How about reversing a list, so that the head becomes the tail and vice versa? Th } } ``` +Recursive Approach: +```swift + public func reverse(node: head) { + if (!head || !(head.next)) { + return head + } + let temp = reverse(head.next) + head.next.next = head; + head.next = NULL; + return temp; + } +``` This loops through the entire list and simply swaps the `next` and `previous` pointers of each node. It also moves the `head` pointer to the very last element. (If you had a tail pointer you'd also need to update it.) You end up with something like this: From 35ca62c82b39506203e551c8d05938113aec3e2f Mon Sep 17 00:00:00 2001 From: TaeJoongYoon Date: Wed, 17 Oct 2018 04:05:46 +0900 Subject: [PATCH 07/65] Add CounterClockWise(CCW) --- .../Contents.swift | 76 +++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 ++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++ CounterClockWise/CounterClockWise.swift | 50 ++++++++ CounterClockWise/Images/Pentagon_img.png | Bin 0 -> 20639 bytes CounterClockWise/Images/Quadrilateral_img.jpg | Bin 0 -> 9081 bytes CounterClockWise/Images/Shoelace.png | Bin 0 -> 77353 bytes CounterClockWise/Images/Triangle_img.jpg | Bin 0 -> 10346 bytes CounterClockWise/Images/pentagon.png | Bin 0 -> 25285 bytes CounterClockWise/Images/quadrilateral.png | Bin 0 -> 22372 bytes CounterClockWise/Images/triangle.png | Bin 0 -> 19654 bytes CounterClockWise/README.md | 118 ++++++++++++++++++ README.markdown | 1 + 14 files changed, 264 insertions(+) create mode 100644 CounterClockWise/CounterClockWise.playground/Contents.swift create mode 100644 CounterClockWise/CounterClockWise.playground/contents.xcplayground create mode 100644 CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 CounterClockWise/CounterClockWise.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 CounterClockWise/CounterClockWise.swift create mode 100644 CounterClockWise/Images/Pentagon_img.png create mode 100644 CounterClockWise/Images/Quadrilateral_img.jpg create mode 100644 CounterClockWise/Images/Shoelace.png create mode 100644 CounterClockWise/Images/Triangle_img.jpg create mode 100644 CounterClockWise/Images/pentagon.png create mode 100644 CounterClockWise/Images/quadrilateral.png create mode 100644 CounterClockWise/Images/triangle.png create mode 100644 CounterClockWise/README.md diff --git a/CounterClockWise/CounterClockWise.playground/Contents.swift b/CounterClockWise/CounterClockWise.playground/Contents.swift new file mode 100644 index 000000000..ffa91ecbb --- /dev/null +++ b/CounterClockWise/CounterClockWise.playground/Contents.swift @@ -0,0 +1,76 @@ +/* + CounterClockWise(CCW) Algorithm + The user cross-multiplies corresponding coordinates to find the area encompassing the polygon, + and subtracts it from the surrounding polygon to find the area of the polygon within. + This code is based on the "Shoelace formula" by Carl Friedrich Gauss + https://en.wikipedia.org/wiki/Shoelace_formula + */ + +import Foundation + +// MARK : Point struct for defining 2-D coordinate(x,y) +public struct Point{ + // Coordinate(x,y) + var x: Int + var y: Int + + public init(x: Int ,y: Int){ + self.x = x + self.y = y + } +} + +// MARK : Function that determine the area of a simple polygon whose vertices are described +// by their Cartesian coordinates in the plane. +func ccw(points: [Point]) -> Int{ + let polygon = points.count + var orientation = 0 + + // Take the first x-coordinate and multiply it by the second y-value, + // then take the second x-coordinate and multiply it by the third y-value, + // and repeat as many times until it is done for all wanted points. + for i in 0.. 0 : CounterClockWise + } +} + +// A few simple tests + + +// Triangle +var p1 = Point(x: 5, y: 8) +var p2 = Point(x: 9, y: 1) +var p3 = Point(x: 3, y: 6) + +print(ccw(points: [p1,p2,p3])) // -1 means ClockWise + +// Quadrilateral +var p4 = Point(x: 5, y: 8) +var p5 = Point(x: 2, y: 3) +var p6 = Point(x: 6, y: 1) +var p7 = Point(x: 9, y: 3) + +print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise + +// Pentagon +var p8 = Point(x: 5, y: 11) +var p9 = Point(x: 3, y: 4) +var p10 = Point(x: 5, y: 6) +var p11 = Point(x: 9, y: 5) +var p12 = Point(x: 12, y: 8) + +print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise diff --git a/CounterClockWise/CounterClockWise.playground/contents.xcplayground b/CounterClockWise/CounterClockWise.playground/contents.xcplayground new file mode 100644 index 000000000..9f5f2f40c --- /dev/null +++ b/CounterClockWise/CounterClockWise.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata b/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/CounterClockWise/CounterClockWise.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/CounterClockWise/CounterClockWise.swift b/CounterClockWise/CounterClockWise.swift new file mode 100644 index 000000000..07c422ea5 --- /dev/null +++ b/CounterClockWise/CounterClockWise.swift @@ -0,0 +1,50 @@ +/* + CounterClockWise(CCW) Algorithm + The user cross-multiplies corresponding coordinates to find the area encompassing the polygon, + and subtracts it from the surrounding polygon to find the area of the polygon within. + This code is based on the "Shoelace formula" by Carl Friedrich Gauss + https://en.wikipedia.org/wiki/Shoelace_formula + */ + + +import Foundation + +// MARK : Point struct for defining 2-D coordinate(x,y) +public struct Point{ + // Coordinate(x,y) + var x: Int + var y: Int + + public init(x: Int ,y: Int){ + self.x = x + self.y = y + } +} + +// MARK : Function that determine the area of a simple polygon whose vertices are described +// by their Cartesian coordinates in the plane. +func ccw(points: [Point]) -> Int{ + let polygon = points.count + var orientation = 0 + + // Take the first x-coordinate and multiply it by the second y-value, + // then take the second x-coordinate and multiply it by the third y-value, + // and repeat as many times until it is done for all wanted points. + for i in 0.. 0 : CounterClockWise + } +} diff --git a/CounterClockWise/Images/Pentagon_img.png b/CounterClockWise/Images/Pentagon_img.png new file mode 100644 index 0000000000000000000000000000000000000000..44d8583036420e6a63fd0c339f65845632ebf28c GIT binary patch literal 20639 zcmb5Wby%ED%r{!JXlZeGm&J-Zl;Xu*7nkDhQly3AS{#Z)aar75i@Up1+`pUldEf7x z|IXpMV0Z7GNhX<0W+usxZwj9zP?7MFUcGvSDkb?r>D4PJ9^h9P0UmhLJA`}#yg)fB zNr=8G9UJntpH9>hW} zh(tJoJGaDNd(1OX) z-Np&*#$@A2@sG&=(D`8EXyjmF=VW1PL;6A&Y-sE3BtTC7!svg0{*BYg!u0=gvT^)R zEI>f!mv5L^K`hMwOB?9Q|MHYq-oe5I;QT^gkd^;$%m3H2|M>7TzcBxQ4CbGtf1d)P z3L^0{|F7Bvkz_k)G+(_EekJumM8ys2C=GFuXyUeag)2oe8&**p!4T1Kg+kJ}B9UI& zx&_1*+{B|xt%?HDwJ6pp56cFmx4F&4GaWJ)-~ILs5{hO2z#O= zdEWU|`e>#;B3D0Y6S~0RV5~6!G8D+c%l2EB9m+?Bo%&CE_JH|_|CgW1s<_D`=bBuW zs}73q-rN5==)wtBWo_x+*Lz8|>h&5;tER*}yVD&P*3P zgr(nMs^43C#qHtL8=d!gTmeavpa?`e+E#F2gQGv=k~mWR&sYG`q1p=KvmzS2pisKj zd8Qvbi+@E=f>L(+_*L7kC$KCHph}LC!;s~m6K9pV=vFn4UsmJrcSbUOa1r7ya7#1L zJ)~Zk53-FhfNoi}GVntle?EW~2%A<%guPh}yzRcIl=vcNAaZ^h=^3?13}atK;fC1) zXD*gf>`maf#-1`~N#Qacf*{;~RqFyjP`GKQyn{f4yn^uj_QurN9<1sA2>C@Ti1Sx; z%TOpsWp(vZl2FHp%UWN;7WIS6jq=7{tnXSJUM3FQ#@N*uzZJgm`6Txe%HB=x*GX9C z%U8f4KcmEL9Kh%(+^v1W)I(24e=9g*`%M%TwaokxV)wD>$X45k+-nOM-_)>QeW6&q zT-D^~72RCL>_KI~RE!L*Jj;rgHHspY0^-rh*Q7tKa-!ED)~4)YFjVdU-p z2|qdeOS3P2H_LoW71F^5mq15BORqbu6f(N?r~;C1K+rUb#kV#Ljr1)2r=B8?&~AWqBYXa1Y-coTq% z#7Ho*5nM@wZqRA?uCTQ&(}Nnfu$$;=Sg;~=0K>sLAjOEVD!YNSJ<(PSBFlYmz4)Gq zlA*li^T`Icr&Y5rVb4AV(+E^TX#fZiXcdLBS2$|`&Lo(TIy3ci3I{WpWF#}*p>k;u z){}T8@m2agg+>&q2xwE%y5|40V$S9j&U8dg-ftG`j%7WA=7RDR2Rx>5K5PU zYzUr{xO`T{y*{6~`4C44qM2Y=qF&7wq$FimE|xq4x05xwNxHf(sfHJv1-*=>U${m3 z4OK9@mLj)GrmeM~UHB=<+N4`bh5a)+=UZHgko&thyPs`gNXo`fl_JJ3i%R$wuTQ;S z^OJ%K3>@Y{ZU;H^z#Fn(46vAUme2{rUxGTJI_JN`7LWZKSdn3-N_W>vLr*sqy-K|r z*1L2(z)TB>;E@zLn`DK5&+*g_CqHpSfcJ74#B_9*A$cb=pns+^Fz82D;#C$PT9t^l zx06&Uv!cJtF+O^2{ck;(zG4{s$D_fdEna6y?HA4vU`7UQ@u_t%FFdT^b^52AFFn>? zEE9P6vOa)^p{fq4iAOrYp>{(d-zS|X&N_HtYTAXfI{9QP=5{pqa;xR*Dv9JHPZs{p za9li;vevCmAcU5=E#wLrF{|cdlC2URb6uuERV3~1zbV>bi7Ja>M-F#i*Tcv|9z~|* zg$;YVHFQlQ1!$@CHPk@*n3`c9Pi zP-bb|O~YqCjR@qA2){|& zkjFM#mgq4lLuW4084@nHQ-keS#`1uLz8l*Cb1%ZfL( zPtuPd_@fvMY*N47fePr^y%%QZj0&iK* zh}9=jAq?FS7HaeI@_1IfuXWGASTc z;i2p%pSg0x1Z83>f3Hu=FTUE-Hs!9J#7OFiw2>XvD9DPM*1|?rvyY{&^PAIZx}TV~w<#s!z)^)|Z?x=DQWTkD98-J`CaVw&D4`Ut1RJ$r-a`bZo zc@r?MP?I+N%WUaaiH@G&xbj%xpInJ?Ewvd)DEPz_hxDI8q>$o!aWYqTLwsIulO^O3 z!RtjwYb8rZ1v?FUeV<#CoI^~TcoVMIa5w!l8P!Y9GrHEEhZVg913aaSM`ST=@in!E zAznu)lPECt_+^@Kb4b-8Z@!12{kd@6GlqAWGfC`&)^=TTe!ketL!wHB?<+7vC9 zH{XI>7;Fv*-XB&$Dl>`^5)rL(u)1~U-ivxwx!?-_4tg}lu0_w>HD9gGsL^yU-Ta=r zudyIzk)GrQ3P zG*4iR_f7csZ=sMFu{B-hSwT2m-fvLFUn&6QT|XN2e7A_tp6HA2NwpSbX22J|K3>w^ zNwIB7n4X?a*Y|yN?gaQv*#Xwl?0!DXrT>#{iSg7|Z=G%XP3}Mv|DA(wsz2ao<*U2WoxA>|v zhb+&tg{dbkhd!<1Mc_C?Ju|DTDd|**3**kQkM3xM{YBe>3SBc|qBor2`VUp2PGw%4 znvA2P<264@{r5SRgHp56bf(HBW z)jJpY??3C{seR|JgxK2b>sE*2vgxFXgkc!o-{qG(S%s+ z_T_NQ=u~NLta+>kP}6C+#?R){{E?0YJKgx?4B>usnEi|@txhL%t#%X83VCB z-g_+wr~J^)7Et5|T*+EhniwkioJAD#UCA78V9lmge1S*p2o1ZNi)jH(r;QbWX#{dU zT&8DxhGAMxe4|N+L@f^x({o+ra!hM%_~^PyWTjy0#7@(4$CYcQAT@BqbhEEYm%1HW zUJiY1hU(VZZ|!`;_qhZI9@T+K#zEEbUG#ALRK78!(&+NnVOj-)=lAiutku%bAf-pQ zWfaVf(rnx#y1`g3U2fBX*pzSOXk=1mh3B=ys!RLnp2zj_ViH>Al`$@=j#%=YpR#E^ zq<(*A;PbpXJhp9pqqzV!7$(OH?N}293~;^ z?+A>#B&*%`i4H887O{uzoF8G_@ZiTob5$)w3ZWfMuxz3aLK*JA6e{NvldE5K*UaeM zi)@9-zjn79&(o?qwKWm{B149PIp5%(T*_ENGxW{|Cus{uNytMd$pn5mU%H)ba$DK=u(azQJMvt1AkN z&p|MO4Mc6`?$;^e%%nYu0m?fN4_@EQfG8c=J<=#54gwbvG6KQ?8eFf$Ei;1GoFAK) zu7Rj*j;AFS(@z4X*((DR-10j;j>0SoDU*e}qc}Y-Z_spX8S~xM(E`86#cqNObF-64 za~!um%=eXP`<{hg#W&Sl4I<_;f^8a<5M$FeeDCd_j@Rn}hG5+g_XDbGQKF=7*@G>)fn$)o(%YoP>8YPV{~S`O zks=oICR}IkdfD@2m7%QZ&+X-mK8d=EnLj61edS%~mn&mySrHsF(&s0(^n^te5=4Du zNE$6YM%Dt4zhKz7J3{Qd^ZBkF(o^r1YMW8N>m~# z`e)Onn(At&nZbAPxOGhRn=x`83=1wN&DRmr+H*n!M^7Q8u1)2TIKrdC?tE|QBKUoZ zG|`N8TF$sB^EFPeyZ@d`lpI`oDQ#oH%7+8Fz*eM(W~&mruczf>>Z`#p{NA@=Gguvj z{`}%xKc_+ctOiY2LPymT%fv!H583!6Gtw(+4vDnB(oOO4f5PB#&vSzp=ZR5Rp3XC# zAEp3T{M0(ot_rP7O!a`b4j##Rby|UqE=zA6rEY3nm<;LNwf}*ie2{C< zbztF{N9Z&OLPFlJnn5ZN_@VFx$CGmEm<<-%Q4Z=*KI)zVo zL_@enXvKJX`{gtP7BgGs2kzJyvP`{lNQ4Hpw609O_@hhZ;k@o#Zh}^k)R$0#%^n+f zz>)u8;M1FNP_I?#u)6UAj%Jwci$v=-jEhW+pwpZWZWEy?cNA-6P+9&&jEu~OWTzV` zR&dKL4(Yli2g7=Lw7W4ZFh|aH&rkQQ4rkps?6J(}Z9kk7Pq%n!c-kWUgfzuCsJOmtDf<-<(xIjZ!yoYrN3XZy3UTYMtTk7Tw51#2U1AnNi+- z!og(-S>;V47i)iKY7K_d9q96#Ixlii{i!Ko`CE0k8+AG@>Ue;Y#C6dgdH2^L)Qpbf z@VUp{pMvq*Z^E8ko~KYfso>0#<&mv3|X zWcg(d$qofnS?ec8Lk%B;FS$geODnWOA}Ga0k{K2{mj{jkuVL+AB(doG{8+d5>oBE( zIK2lwQs~L;BJ;AYQff-rIX5<^lGQ2_{YfE{K7tGLH?Llc{ zZGqU+=ziIJx=5|pry#andh~`$kG=6sTNBS+^{}S+G`g+e*8vRoUTqGH6cI=Yv)1^hL%OA2-aZqL@WbEZag+@?fy9`LJLlz#j_$KX<~zSW;= zy+86iKkFq~IeENZS$UqfD)Y99mE&xWUlJE?uV-LD-xmp0bfB$t!o|6Q_ILVbhMn@<%b?)$`XbTQSj%6^SG?ehwH2_rqmp|GfdwYLU1 ziGWj6G=nE_fD)+M%S%}wIHqS2Z)~jOm?WqFJwF_Cih~w!i_71o6*N`auwOLuUZFO6 z<+X#Dx*$W1qc|fUX&vWXS&2i$AFDVAs~5+ezgryIKkxeU^j)r!PR11?d6CLuO!0WA z6uGuT@nJVwRmA&!5@fjsGTrtq(nPaYk1jDb4!S=rGVU(+Cio4zz9xLbpea55GsyfL zY0B&)(~Cz}?!SIc+HQFDJP;aaiJ|T=rAC3cEwSS0aL)0$`u9hpL`_pXQzCncQehvt zwK^Ym2l`f{<~XlMX}VjnsSS}9MtrU zoa)Zt;gPe1U}?r80<7E}v|99iC@$=r#!BXv8^cbL=bPT^%>ljqP20DN@l5_Zl=53xG-vU1pTVIaVbiM_ee7RMs@543281v8v~ZmusU;Fn*-@|>Q~l8 zz41#dP9`!u9~0j4ls$qc86W$79 zM_}FvMh$FXF#9&rqti3JCbVlS#?f{9t*{iOde)gNo!A;P!>+ETQ@5uc#;?+Fu6C81 zsJCv$52?ITbK$)m|58Ap5Ov=h4kbzVC9Y_*fb`BC9^nMB4tWPj0%7QaMPv0GM5*GC zhpQ~%_2WHE53`tro>>G(GgUQLu$2Db#9*5r9sd)970h>zLYkEUpJI|fEX7x<9m?&6 zfU|AfHBl^I`9j6!7eg-&`4MFgt(q4CWCN;)Nh}z}q9Z;HxPS>dm^=$QY)a~A5TYyg)qixaWwtB%(G9ziocR;5|FS;*O+$QkuOV1qEu^8 zT&)3jqH8?6I4r{f1}rZG-ct zcko5WZlq@`nxMcAN0ZkWRFZ|TN{A{0dL44mLIt;KZ5KT;p5nOFq(a!c`JEqVh(p7Z zt089e{Mw}QdHh&TbWu>mI(CC&(RCb7#_vdYl}NvsL=ZESo5LIBd5^2p3fP%&d^szL zl^2}TnQMJLw<`Ga(-JO%WIvZi5fzRmO2e#eP%Gkh=$+n)NF)s_S|%U}h0!t95#E7% zcE|hcb_HgecO41TEmk2@JQ2kT?gv|tP}DH*UQR4-vt7{J zhDtX{TE14_52Dm`Q{k*s{rV8ly9n%E*ZVTNM85#BtREWU<(zJCczn5KzXa72iyL^w za4wqZ*^T4UEAtiJ!51)OEyc$N%`^?eI#12}h^V?70Y`@c-cJGdupT1BNDG@4Fo0v{gU!gWGaqbiz#&afU#p}9n#iwizT=m2^1G~kO?NAb{uX6nr=JvHk zh7yMkBAhWOuCaKlx%m5zHE^h0_MEhx$R@~YY%JQMYOYd7)77LCX^B6&8ek}Uzv#Y` zHsN!gva*=@pv&CE?4+sADJAoU_~jxjcWIcdcafBzNjLzm=u&b*2bi9uDA|OE7IW8|-0LirZu76|ErDC0Xe86jbB<7`f zfj@l|_9oX5AU^S2WP=i%e#lhaSlM`38RpEq<(#JVUFDlZbG_nmX+l}hm;zoXy9$iI zez+OY8Od~9UG+0=V$}-J?Sx=Wi>B&PM|cF$@)C zs-1fwL@r6FM0lNORu`^rn7SOs!{-WcD1oJn6M|=IF1hh)mb~jf)k!aHV)*kiIhC$Ah{{oWh_f<_$5|0ZF%C zG{gBu!UN37?XxK~ zQw(#j;WeI)4&rbI_HN4C(<1Rt{G&uH1_?yTgF16B7ikm%&hK@VGOcGl1g$YL06|YM zyZA=>wvXvBj_mX{W{Hm!c~#zOf}*{<>SOh3!6^k4GQ~G5TD(L;l<&W}B2bm=_+1=7 zTmq4(P^ft%Z`Zq?A5sDo>Mq?_>Rs_iRO(mxb&C#z7}~bY9M=~u(C5O2ebv)34BGok zZMWvGf|%*#O%xAWv!dMMvsw^+;fEv3&=AVR9^VcB*TgsTK{$GlWc1#c&Ke-07HTMb zwBuQNSX|ZuTwQ+y8=uD)^zQgH>GcW*D_x~s=n1;OVo^r1ZquHJ3q|QwK`4`u;!u84 zFS3U?R7B~Bjkm@*w7W{sFg>kkM0EZiggDq?rd{*rK5K1`)UqDM`qcEH^f>lJlK6&< zG$^@|a}%gz%b>BMG1p9e8&uMjnwUN*LJ8zT9H^}9V1B&-Yp?%KIk1pPAG^D);h@y& z66dk}qm2ZH{B$<@d2Fixdw7TX%GUd(6XF%0`y+dkUc^UOOu~uMciVbpp|$2*-~K4a zDZDMIybf9l@(l6}j0~ayk}TDH0qE5%*hJv%WSClgkwh=Nv5EH{<^`SH_`KOZST%!1 z=IXcD?Hg0CVDb(xUYQ8n%Qu&pYa2(4Cj-Hd9kpTGx-|@We%4#S+MYu~+3d4|uszhQ z8h&wNLw3$Mc~zyGDY!ENG7D~?UQ5T$$*AMh0{8j!cW?7Vp5srm+fdq5Un|69Aon6x z!OAF$B)-A*vx?Js@3aZoh|r$()tG?N_Mue-&ai67C7cT$=0#=jEwy;>%@sQDPg;Fr zL6As4C?nA4Z1+AcR!mvCfQ0R-KiuGIze3B(BDuQFB!&;v3K=F`^+{beagq|0>SJGeS78UQ-eL$J3 zqKUJZcn41Ai8ARZZ9Hr$rTdl-nYeZBSURDY`U#0pdz?MJ;z-B8B}l~EbxRnYlp0x* z%~MMFmgH24$q})lju@Q6c|t2Ue+|rv%3s}xv%Xq6B}OGuBtal*dVd2i7ah-yu8K{^ zN000~G^?16Y32PS|Gt1u@pw21^*BwtRMmK-i0@Q|o06ls4=5UGtOt_5^+jIAmiGg` z&aI+}#=>ekldo~K?PwuCVQ{AI=8IzpT6u~pwJOb|)l!KF2}XI>g-TdIdZls0;OR^{ z!Kv3^r$)a_MnSmq&p5)RSK+ToyiO6kwJ_?7YNDM-O~Tp6o?=9lK|x3n>nhCw6tSh7 z23am$`&I={TjfO`lh~)~pW};N_RCBi@U`sFgdXhB=pe}Px5@U3V%bM|h}Z5A54=?@ zfl4Z&lHW8sPo2q_BrUS({$l}R?L-vJ9mEA3;C4JJ!J*Ei0{@!yQpM+m)3r|P-LKE( zdGPzcrYj3vu$zq$7$HX0gTZvFmomY!IyAYP#rW8=kx-kj$*-k6G3s!SBA+1)^8g#1t_8VDk)7U;tEF^@F zUW?x~h-9R=pFn7dL<6Ym7ChcX)*Ewgxm zS;`Bd(Rc2swkqDclBVfiw&^Ga?TFCkk*MpbcV>*=v74<@k-gQ$=L0*{k3No((w%h zE#kw$@v@9`e^$~iuEZ6N&392coN39<_{VTN8860#fps&!<*6&9wLikEAsm8EImJ^x z0b8h8gdof0fQ^>oK~H8noM5F6!- z*po;Db}Keo$T?;=BcwsqZp<%0O7yTaC9_NKZ61=wx9u2u?nvB1!q?8Xus`yC1tz9fke8r-y-2 z6M85&MGz_hPe-Gic_p$(MMJ#^{Pljdd{wsHUdWXF16!VY7+)*|ENh>2h)dwwD%`MF zTI5oX+2I!)rt$c>f9#!i$5hV815+I`N|!ZA-l|*wOMc>F)~4}j94mFH(Rny#>4Ov| zdWW5&RMm0D8>zPm4B=-Ry%PNUv8Aj)Sh)JRoEiu0)0F0~&<<{wYELWvk_9(Ig-IAl z3HYSQCkk~t7R83yvFPrP;rJ$15x^0B-2K-*CN$g(J}m@eU64CYJ5kY2#bsQ&^q4>a z4%yrpIQU_&hj1JhsYN~FH>+f>?tVES*0#%ArBzK-vcsIUq3i&ucD<^K075{#**I?m zow{((oIk?Lwhs$EKm4*MS>y>dM|!h0P1Ve(?tqsflYdgJDKQ@saf6n_*Zir77bb7@ zA|^`}#=8+n09*m1XezQ+LLyFKTjHt>VEkTlGYNMHABf=rESB{G`%_gxLaef63 z+lXw)loiWAQvx=q#Q0^quyhin<;P>H3KM{6rDu1;U~}n6ha*|zuTPx68QTC~F+Hue zpf1TvT=xl&13Fr1VK8+iaH8WBDESZ*CwfZo0O?wx; zn@;?Nodckdf)3)Ags`!yU`Nv!mfQ@cTq{iuASfB+ryF{!hv7s1pzZcS5~uET98b!c ztEghWgyJ`vRT3$?qsq#{6fO%~2wc9s9SVj$T%rVpq-g(-T$jYsYrk?^yQN#q9<6F_ zm(F?TBO}L?R+(scb&W17oAP$}VwQux63wa$T^}WQ*M0K2gvAen;mVvYysoWu+*PYO z?OXaJd7u9X87(K#GT97(JA}dBU|oMrzh`-afpa}*p>mNdZz|G5*IPlDybFoasu5mb zP?))symwEk<5zYtQqi@;Tq|Boa&mIvvO786N9WV^>oOE29VvOM#_i%&-z3|A6J0R4 zDxMdARg#0{^DO{{tlxdHQ*L@{oJK}kBWd8A;+*|7%iB|{6^S|E!+wCT%4As`-OUFC z=YaGVm5)XzDrH!O>Wt;XW~{u2WR~;EQll%yd8EZsj*%DpLS7=t!%|_cS=|_Zn?<=O4DbY=&xrmI4=G@76&WK2#;-4^qNv*gZ(JJy@`ettNq6 zf#N}CuqC2ZrkICH<8ne#!Gqmz_)ps$fqkrMxw5Eyd!XkvR}?&c-8z~+kihVL6pv#%5X}!{K+)p(GSj3rxGWotf2w zK3fh(yb&MWL4QdN^2R~MuzUr5W;Nk=E|j`cI>NU{2^@3le90OV6#xc39r|#*DsDc~P7xbqv_nxTyZ*wV`&RS;|T- zL{y<|1>J{UU?=|^TNJ;$TBOh=&FNWqMS0bktVS26#B}t1$Q}k9zn4h|@y2YisF_kb zxa=XYJ@vaI?I9^^ee!@KQ1CcFOgRE>%qaz}b{urgw~8K*_t#vxGvv85$)y)MYa;q! zL!>u2mrwU6u5jwO-Ya2C#|~a6l23e+FmP85ZStQXV0Z-DmK7uk#6DtZTkU!)h`VAa z5Q6^Rc^m@7!U%RUe4hp^clW8Sq`YE=gxj4PfpUh5)dJ=_MR#G=uPIG_Hm`}C6gE`V zb*C7`#UFz!zjKyfkmuF`%_O94gRs=T#_5fw3n*sOHgoz$zZ*~B`;0WQoZSGIm{O&~ zYCe=3TCX|CKo%TrSM?yg+TAG+#|ZzHo~NV1x5&lX8y43_G=?(#D=drv(Y5>~pT>;R(b;%Ey{> zcV@53_mIdr|mIA*ulFc=u-{NW48)KSLIp8rz&3NVsWL zLh6pZJv2OkyyDRpPb+EpW9tiYnA~1F?D~eISaiy6F^`^N6TXxHM`X|seCcgaG8Z!~ z2P|AjQvA9!s9WN0ykwOm-FaHmwlMOui1$E{c8ugwQh>6@Qd!I0K0FmTsU8SnNE_!?ch&Q=Kw=XQ*isjCzE@~^=`G?(Eow+14KsM)%$+?sw4k0lINu(QQ zG;%*2L++ZjUg||Y1V`AxblWOY;M9mBftstUS;u~defQ@jM%A1HG9w{-Bvnm)NxkD? z@x)?k_y;C^p>&Woac8*1We@aO7plZp-*PF*a;GVdhgu!xt1Vum;j(1j0>N5_IaLni zPX~PgeA`Jz^x*a_8FAyiGx806aEO=%;*vmCV!;FH z`;K&}a0hzCn`cPg5*puOIoAl^NfU5AyZgC2%BThLFJGNZoRSk0#?M*3QZcMU*m6<~ z8!7wrS=~c(dAXLMd2D>+$eM}183pOs$)2TMcTy=?;mT3B-()8bUE1vazT>#@ zMDNeoI~!8Zeqju`-)m?Avbo=8o zHcHeLR+L9^^xXWRAiY3&gZoP~T*+5w)G#FC?-W^e1q=?z&HML_8)Xd4W_jLMWjuby zI2#E2?vks{B&G%so3aez)a_UOx+|Ng_%kv%;&c600@||2!LOfFP)j9T#p0K}_AqlY z!T2?+Y>IIf`i;3XCet?$=c8tK2Bdef{5aK^1-W|YqHEZ<4 zYG&K_<=#{@_2*R=CbtO*_Dg4o-qnBKllCw`?VVX$1kz5#Q74BlG$?~ zj)C~%F&|*-u+|yJ-gaY3K8W#3^`+a=Aoi-B!N|+r^M%X%_UzyYCt!pAF?S>W(Tin* zyV)f-Uw)T7H^eh++{msnFFsUI4DbbFYLaDRrLgLDb43LX_pwS2i{&YZUP+PV0%8z} z@)75{%@4s+EKZyBs6;#kNm&$&!rR#{BFG~JLp3&a7raS!nYw#x%ROIW?~})W%FFXh zV7$RxUse*@esN>P$wk)?x_-Dg@jT89YL?qAAz13cO$cg;aDO<)+l9pWeGi$9U%jKg zPv><&4fxy@ko@Pe>KLf?I@?Oruia}hO`FNnlsOG?iL~evciu~aYC!Th&5S0mY(N+l z-g}fxD&Sg{mrv!k&nr2q1=OZxHSaJO94x#?h}33oBC1vvQctMZzl|*e`DKW-Lh}i_~yNkUsXKjZ2n~cwCHXTki@v@G+52&!Vty zu*gmUPGtF0o}k>iIEU%d3lI=c`H|dLsk^slCU#CM&`cJ&A164?cMRzS+NoNx;k=0_ zY$aKgUzOkt>+W}4#KcWo6Z&@Tx`!nuVF(@J3FP4GMYc~jMI-zz^D6A`xzEaouhrMzzv+83vm%@2PD742wZjp|knvN*fr2-%-}NM+yU zAw5iPYe22p>LMT=t3g>ECw9DJO;U;V#+Glt!_FJc3dHCAGiH|IJ)LI}pRAx)AD2qU zZ9}Pvah$DI`s0JNeB$6Xu-;rSLDQ2;%*;T*aT1l8-_-KX?I54?K(|rXG8)SCL04*3 z=uMvxQ2oQ7lIIW529x;X;ZPmba;R>Q*?kbBF@ZMG#-Rk$%g5cmiw}`#*IWL zzb^bEknPO9Zh&{GV*;Yi8CEXQRO^J=&8{9${4lxf2JyFXF%9IBBTG}5c-t)}vSyq_ zv-LWvRlwQwt|dO?H9LqxcdI>$-ue-ZZ`Qf(ChmHzq1 zru$JUCgJK4i49#xd)5_!&oK7 zrnB@;&hJ>Xb}3HZ^C`8h&wgMzBcpT-c~gx>bh}?%rd3JDqi#3tWN9<(-QKxyzgCpF zKU74^$)I9d+y)`nqkoVP?$0`W^Y)3@cJw!IT-6%CZDk&?#bId7YbNxZ30j_MSlLk`NuX&LE{=Z44DA|p_QWA zNN?^P)$fkD`viQ|QFFKZT2~vCAf5JMu@GBs7}a*ar6#bctp7Z(le)D&ZtHSqIH!{_ zP}YUU?)2fy$5t*UN+-opfomO|rzJzf^3|78@=Odo;oobn{tA0PL=X0*N4&wrrtbb_w6hsf}q8*Bihm9WW+T0OdRmU#LHClA!!9 zEk_%{O8vcQ1t1o1?OdHp@0T}#7^`o}XeBOhhx!{J7^S;j+LyqCI6 zZ$a+nubF7EwjS^5R+ac~#_h}mHO{ujvwSik6$3%p{&k<=d7_BQ&RRu;eA}Mm}K(4{6jTr;0r0EVY-E8+~ zf=|4Al$eCRZ0sZZzlQXP%`%U1S-9deW}0XiX__bqX-V@A%MU+iS~+Eo;PebeoCCUR zbkJ7Zv}vDm&-FapkATXx{rlps$C^DQ1mP&*R7n+@yXW?)2J{m7|c270%T3(O`s-f zFNUGFc4BgFjSap{?U;M1XbJ%d2?5SjSES{lQ&v2`yntzIK!JHU0B1m|ub8Lp5WZ=; z>iWOMBq(iQfRrjM==BsC`K2%;vW5jcz3+gOT}+YvxSM74q5tU3Y)$_A4wRcXf>)pf z4`ddz$SH>8om;~OKM#~j)17_>a6`fZ>``$sGCN@ZtO4kjbDG$()25k4r8n88Sz$QO(X$ABM0J^nB5(OLi) zu-OZIcyRlp0o1@N{6wMT2!u81S4UYxel6IBR%aDQ{OkOcdA(w zBSEprsDggJ7POF zI(~O}L$4?3gud1X&{V?VY*Bj$!6vHMaSKtIvO}Vk`c2l@lsotV1;kD-$Qx2T_#t!# zDvmh3Q2JCsi;`L)>^$VGBvqVJ#03}Jna+Qe`$K-3D!G(_**W?V&n3$s7MNqDjvi=| z{qvLHIcP(*j9<#0-Y=#!BK!kaQgki~J^?q@=nanBnO%8X8KMN@)wVNDP%lu<@4fz* z+FN!ji1P_uAvhuZKe&j>YZypT)&XBe?XAV&h{)AVYbP^Y9R4)%v*0RMuz?~OVo=h<=xwN!4X5~9X`Bqt7gyxkx#t;0Ubt!3#CWyHX;;1DSnnmhGd%|Jq&FV zlVO%{2Oi`xeDuA2tGI#uvQlFJcb;0Gq|cx%fz+H7?(WYN3eqfcnM&k6!!Z~DS>bG83z+=&<_m$rV4NkBr}O~Os; zMv`0XAD%CB0#DMAg(cPq#3cLn2~+dvnwA7e?X$WC03h55{mp7V2wHX~3`7Y@phm<#0+k0}q0a z>F*akzQDa$mt>s3QXHYJ_@2zh5uL4)J-aXEA#-^ot0N8K^husUBRPAJsZ~ThFcScz ziyKfckFtV>qXdF?5L^%%oX%7swBebOcA-hZO~)hgKl4z8msWM4Wq9i2ppz-p`C&rV z;|d_cgiUa1#rvbhs>Vyoh8@BkHh$4R+WhC3@L_W4c?Kb<$2Hdaf5Br4SSY7|{(~<4 z|3mNmUq}yWAsHo$h2sFLV8odtXK;kkf6S0zfZP}S^Bi12ApJ`-`ydkz*1Fhw1Zqt#Mt-`0aM*FB1M#W!-Xa85^R@g zml$=FqS{FO=o+Z0tpU^wzW_*MOn?>fn*AR%TP}N4PRw9jiXAQ@=#UrseDt?%FRL)I zDZ&ut=Tcj@beG1z)1yELBSp`1U~6QJO}LlRv5uyzj$DUC^sW1ZHiE?Q@5*IJ=&V|B<49aoo!h*_k)WGf*9G!R4oB{!d&_ z`Id&EC~#(AzHO_&BBGm-B2t+hQyFb8W2K{)@B7foVzGUzulf;jEBLPgpe3qaZPmLq z1shUb$j1h&Wa8ese^5l^7anY;p%E8Dm7Q8uV5%JL7+ z;Xliwf#E!)F#8bs0_hwPW?}=p2)5Pm`O9>;1C{+C+amsKU~`%zhbi5pSGL;1WmArL z&(QgC1|rR~pHFDvVrs3D!~gPK_f-#1e{np;Fy;Bo)C9f6V;sfsND&QYYJ3P9(g1Z$ z>86`wiWA-q3ez5q?6^gY(7g_*um>tqDqm_t?(T?pkIGwF;n>nv;!>{Z|(Vfn`=8C|om8?D;1Ss4NxGg|-n^$(x*D=Zv{<6YCoB2lI2kS0fT zrT0=Xa@DjvD8Ws?%1#mOlWUom8Qn}mt#UpGB4C3 zCaS&9Ocfahq|=z+W>{aU$r`$V^xvkX2>+#0Y&Y)Q5<5=VD^5ALzsOCT%l*Ix#`7t-y2Ce*tS>`vgXSBZ*E4GQMjM_@H8GrKp-+ZWeqJR&ha@$)oPCh)a&vH;@-b(>5BN(Nc)>WV;MhNKI! zk*{kHEW?K5%IJz;$cWP8a=^DnsNim-ofwb_+Qg9R?OdtEvfDs(LVUbk#opc|t?wk- zEy~1Zk~IeCLm!5`8Ux>smY|Fr1_(+tS(4SFLsMfX@ZC6L&4|<&e$6Kh9Bql5*us&T zM)Rx^wH>m=?o;z0ncpYfJsuT~BgVJ5L%*MsU_DWfWw__tm9U7Dwsy&s;aq8I3M$>a z^FMxfCBSIslcE~Xv4SBfDN4)zC*EM2^Vx}3oYD3HcW010D`z}4_d+moqWYmHMf{f} zniqD4+!rR*r(#%13_1>h;tb|EY~=}xTn7sarJds$ay`fkGl0jt@gw$S4 zZ6XyGN@(u`a$(08#WFjaW-pv9C++%XJfKaUzbPOk@(M`D-p#4)Qh0$ba3JqOtz{;8 z(5i=n{5!}+3vVfzX(6aV-a&PNl>4bE-|uegU!i?YRFYWyvKY45<%vYJRL7gDyc!eI zJr8ZNBECwcNOw&c8hkeg`g94&_hDHwjMFiLMQ>I;^OrBZ9lt=vXXV63*WcChTfbgEnMYCKSt{WQ#MjtBvXCQuDhunae8yln33=aH_`C(}Hj^?E3li^6KqWCuG<>Z%u*JjzQ+Q!Q+(w-ZpSu=R>O4@Q{QE`$s!+MuYSP~WvdMe$-$f^= z1>CBgX1Dh=E%o9*P?}n6-PN{^aX1@q)jGPfCD2a?_mP12n`WCjh$MF+F2=7d)Rzsp z5G^QGg}{1Yanc&|z{#X{Lb)G>SQE#R%CD8ku8=7#ngb=kz$6)Kg?)7D^_EoQixcBh0a(oZ=yezPhgO zKk)tO^9S75eO>qc`n>PgeSSnJk;@+7{osf7YB#$x_ZTJmIo^43x8na~QpwL&i{EGu z+1iz~1RIyx$x05ui!&$=n-5I%tVcVfphlal?HiZfhlsh^UQLy=AJz46ce1)k4=x@b z2z@p1DL=iLxc+dd(6#GDuJKsp=$4O_>Uc@@1O%&7!YZiA_Ph3=ao`VJ&G)*3JMw`Q zv?OZ6XmX{}t&cVoxM zU6vV=K2^HIH*K-%9uX=vJqb=vulmDpA2antkRu}80-Q$pajw*=Q4)CU1-3M%jPD#R z1-0vg1J^rnnSV@(3l?V`;=dN47M5hgGo!4>DqD+ANTkUDLsHygYl$^l(W+!4zUSvX zoP0oPm4`cVEw=pAE+}XB1kak152ejI3@R}~rq*={2p-~4QLyX9x%{gIezco|mLNKU z&tPc945fOMj!gH;IRNL(H@Lr~)r;p_Z_0AvT3?T6N{X|pSQAzlBlfy_i2){j+=4$8 zkb<7Ef1qx!4{m6VgJsuL?x+^MM{e%YI6$f4c>s}G#SBJi%I&Hz%F)^dC&XgJ14;1D zX3rpSDZ#oblhHs=(@Vax)#ITGt7jLXJVins`H=^IFc}Or45ZpB#x@Ekf%QP1f^Vnk zOaphRd?6$^ln3Ws;b~I7--3yz9un#Zzo0IJlwYCZheRWoEL^n5&0;kD{dohC$_*ic zD(_DoLExRLP45^l#V%>rSP(Xg0SqA zrq}_P{?V>e1^Tt$-{X`GyK>6i0_hpNJ4UK#`O>~AK?R!`QVv@LBm_D&(ivdLdH8*~ zNrJQG-P78E^$(D=!@P4&d_wN#VX^HCiRQ~LPpa8@O0XEpRL)g+r= zOYZZir)?A4BUiZQ+Q#tZM5MBt;evCKF@iO13C0;GOvgx|CYH(Gdh_rU8c~OGEob;s zg!$`$`fD<=p4G-sHuGKCPq5mZ>`COC1TbhLpyl_GgJV=4py%c}0S3#}=RP@WwaJ6H zFm{$S)_9klK)nV+M~IRtTmwJ*+TCC@Ig*>*YFA8XD=^kQ=sI!1+%OA2YZW2Ju~a-} z5kG|j-ZsFbWY%~LuH&Px%T-5;RiG~l)8FIjK9KG^4K!?E6TpuI22G&TFvYx)Fay3i z!CS%Kf=2faLU8sDtreGfHUdi@SX#>WW}hFPD7;aUkwtwMzX^LJ?E3t^F8r07KBp## z&ZfWLv_EZwd5tmXZf5`Epw@u5LTY6He7g&NSJiQn9^z1J5zB+{Vh;0}7d$zRwWe*0 z=0}BdQ0TzN%vkwx)PqtDE%7wSbhfI=gF3~+)H94d?pl?;8pRwJJ(%%3#BgC{jj<}j zJs0N1(doF*T%x6+DnAP{sv(#XMG}S`8v4SYfc^ByDvlhoa2(Ypn7@| zd*WUkoQaDcX>U9+;Ho|B}r17rF9Y4EKZcazzp9@st zj>x}r;IVUjzbv73Q|Z!}1N-gNxGO)4ngKA=cn{`11J1FG9 z^362+(i9eZ0nVKYv)ug{@`!y8ECNf>rgg>)|X(Yl~{SdixPN&vQRt)&5PqR(2r7N%**kn!fCSaA75~`-@2yM2C=V z{UXb6@QXr96_A*&*O2=&E78nFcPpFL#ufrx@_%@ldF6VJeT&T<2;9&o&(;;QU12gK zKW_d8!v;`Zkk?+F%?sYE! zHrd=+IWW1f=C}2Pzn7vHz;Wv%z zQ+q~Y&?DQum$i3mi&isMvpk4v{)Uqcb9Xy8JfgF5l_qsH4z3&Uhy=RHwyl8dQAn~I zvLW}jAK$&=@d{`>c}!TXQC#pX*X#zewX!Irr2KCHGiImqv|e7(t%`8Mewvu0q?(}w zCmwLgVzgSzPiKZU$i4^UF7yM4<8mlS!?pkFYe@7@qth zAr8ND2!vGfjT08zo9;4emXZh=SGM#*@5cQ59B1GAV+B4 zK-jgF)OHtHV&}IFR--#USfUuT&U53$X_<=&S@?kv8{d9-3MM5J> zx6g?d+sSfSBHolQI(zR^KPKu{r@8+m8fy5d79AX7jA%i$Xrh&$smT8-)8x>$^40~m zG<%7?hG7u>f^m0FrKO9j(~H|lSEKOGl8{+wYJzm|F#$yVa^5`K;NP1RA?{W7iTJx6 zjIY+Dr(K(2t13JP9t!Yv-@PrTFg_DgKH=-R3$}=Qt@%p9pfiT}FPN0`L0;gT$+pWj zKF*U|5=UPci+CS8aO4TDJSa)comHe2Eg!8Sqb#3y@y64%-tT?+GnZgT#o;P?CFEBg zyD$wGiH`+z9rIE}5KbFinUX2@g}wtEYFjL2+z*5ya<4poQ(a{4Qhgr4A8RWsJpWW@ z$lXL<6Bey4Hm|+EcWJ}-aKZfgC5q7EPvDAdnib`!^CLmM(ut6lwowmxFHfF?%s>a= zdSh!D>o(1@^7g2D5)-?CqikiYzdb_|OKv|BcYCQ7bC&<5(B0tf7Pd&CKK9#36fKb2 zB-U+aA3RfTpE9M7=OBA*+f9A#dExahs6f7oLLSO070vxPxdneQkaJU;pR-YD9jVc< zO!xD{|2Q0q4D;(vqF#Lp8ameQFR9)!j~WXLKC~D`Fhf(hB0&x61<5^Lf6ZQfZOsq5 ziSS#0Yi2Q4TsoK`C_(p$)Ka;}->F0AKkNvuB)R52G#)^i%VNcQg|T+V4SKEKH6iUY z1Xjgx^($(SzNDAIMRbODR`dWux8ItBh`gqWeCam<$^S9>QYtH#wm^sWUa79;BM-u>n06-gi z0hl!)Nh84d9sua;1AG7g5CC`}N&t-Qfv^_kQ!j zKE?|Bec7-xUq1c&H@E=w_ZbUt{um8XDFFYiPjvYhW)F}tbn@`^@Nx3+ye2Lr0?4T8 z=;L0_j%`2toIkr)rkRsIr2@6MJK==SzM#~?Fz)~g0uT{M1q@;ba40}v3J|6TV8v>I z2m0B5K8C%4aKN~D_z(g@B4X@-hARLL2n@!-1>@me{tYM;`#XS3fk(+Es)~Qr=q`la zi%Kjat&o62t)`3GcmfF(|HV6!kcftsj-G*&i<^g+PeM{kT1Hk*{kn#xmbQ+riK&^n zh2L`UeCCMLmj+iH(a-NY8lkG&Aej^X!*J#U-U><*zDg>*^aC zo0?l%-*@-)_Vo`84oyx?f1H_}`!v4>U*Fi=+D7brJ~%u&J~=%@eLKIzgR-Gk zh-jb^Yn%s{(0(HO?*WVaUm^P&u)pJ40Mr3oF!=I=RUE4~9zGESAKOR?i3o_uNv~WX zCnYDNxJpMwK}kzVMo!H{O-oPD$jEqwikX#}ft8MdkpY991cZx+hmVI(0)db)P>@qF z{Er)E3G0?rn0bH%48l4Sm;z7+zMm)X6yQ8N?59xWsGxOwospEU`qiL12j-HRP>I~N zLK%^^!^NfJ;cahkuQE!o+<5f;-loB{A!O3jn3n`(@;HdW3gCH}@TbCCwaXwr&}F8n z!wryI`FVx$wx`3cB3f;FUbz)ZlAcSq+$ zN_C~J=4qx>oko~_RFn@%Rjt_G-~fR-&%mOmEPi#s*!f+rwM0b)(YCiUY#c;k+V-T- zH_K7KJRRKsEdK#wqk;41;Qv?@%m?fm^QO}f^oh{Flfhl*-c@1xq9iEpl9e4eRi?A& zN3cickn~k6apbBH*~9f~Q8C|i`ec03bOyC}gXy#WgN*t}Vkr!LaKv>K30leJ0dIbulnq%MOFi&(orzFIoV73@-ejzm^&kDzBs&y4yPqG z(e97}<$(e0qnj==77Zc(FF)y*?$FTq`*R%zy9U71S4+nwpQ;F_eCqSEK)ehm;`s}C zt(1#5I$}Xt<&YvB=SjeWS}gXbH&c$bdKoS*St;0{D0DbRNV8N`B&rZC9a0u4BD%n_ zAmPFwAPwibb+0b(8jbAUQ0(=^k~AF%s4?7AJmry>mBXqE9yKH>ZZl7QZ>a_+qD`J-Dw;j}XmW#Q@Yh7gEU0n6{T~k|l6T zN{t2RO+t(K>BFj&H%VoWhg5g0>j5JTs{fmSFcZJMIqkFXS@feYMhq~w;)Vf=&!~6I zwmNA#H#m?h7k%G7esDJzkn6ro-~s+x1`m|uCB`8E!6vh4b#H;=w_>06-Ak|Krj-xA zW6GEVrRxBO5a9#mzN~Y++?e<^0(kpDRvf3){0&O)8bB-8{~89!Gc59O&q?XQrKOq+ zA$MM_j-d_WdVIL}wxM{I+(#DQwe8Jw+dzU{j=@as>4Ohu1~FmG)72gx?Sboh_Zkma z8YAVcc?r06rXohniDRs3h)y%Tq1IM>a|l~FM~NBA1Rkn;I`;kjg;?`dRChN?W^2;ILt@0x7UPEPFkhrLlRzRn z$zB2Z^}k-dpDPQ-O#Y|rQGLw=)pnsUuN=7Q0aY=oa?)xQaoeF1%tCFoLhio{O-}lv`a5N=nc9apzf(Ljls|M7S zt7ih$6c}KFy;V$Hh3YuecGzz6%ZWbA7XOmcDQ@08oNFqzVHtTu5rmk!zm7LyJ>&4Z}&(`v;D4L#C8=<1S2~@Ko8^0#zi5t)_k}i{f zxR)+W%(f}K&0lMyx1?#y1N(Huj;gCQbk2s{h5Fly9pJv)HhoIA8G#>? zBQuUZjAp#E)6&#J?_=|W$`GVMWe8F9#p_I#_$F`TJWC<{eGvMfvq;fbaxCDeZag2LqM43$4bpyxS-JH@t%9X^1;_YR?;SgXN%P7QWrcM>dS4qhX!$8 zu=mXeH(0LtZf^T1M8052lb(n)~>e8N)NU2Jd5y_Y7Sq@ zv)}>V7=S{OF`p3?sT`BX+?=^|FG8r@C>Z?2RbMuq7)NA7-_z`|J)S+Klz08>L5Y!b-waU?_I=^U2*Su5yV& zq)Q7ww!q~Y0Ms?3fr7T-p~N3sHfRjB^bi#k95FLy>3+1csha}RkenbYthxnrcA8Jl zLZj!0X@49)f?1_@XJLT(Z2YXy7dbiFCCcV1`hfGah17&imjJEkn-4?L(BwX|>7*-K zo~pfi8bF|QH(@c7ticD_X_}T?8QnSG&aaT1p_EBrcP(QueJL*KOtfA=hx7G}>m$^w z)wXeJr_9+7x^zZ6S_CcYyd2(0&o@`!@*(>Sre`IZ0gFLOS|cDv7QBP#vXpjF`$|hK z&YEWu{xr4gBlXRiyaJStM`duiRKx>m#|y+SQigJL~_cUOdBRps{kYbK2QMp z$0*CN9YRSW$Nh=in*VjqgCM>eYp{c*h6xr8pJkT2WR-9|yZse`&*Eq?wO9*uO7$|Fb zkSev04F?K$&6k(N9$u5rbuB;Oj;miGbdpPHsa~wid|qb#ws(4Og2O1?Yw;X3s9-^X zoa$~mPbmyu#{dlTlAUoU<&VrCdOsd5-f1CaF8{(DcNyK;yv-%vK}=Td@IM8RcbjJm zWgjjQB+PG$%P|%tFy0Jo z_SCXuf5yUvJn09Ie%CLBEhp)ujxhj;^4}fz2$s;nGX2CkPXg)JG#_HL_HvT5c9mJJ zci_AJ^D{@o!93iWJ_Gu3$2AzGbB73WKdU+*Y}IBbD7W6v}ERlVNu0!{&UG25w(6`058Q=10VjcnZjG|4Hfq#?1b2 zja4M`5}WhI#!KGX_r(BU6a%adRb+#=(MFtBvh%s?ew$*`TH|%{<+O+{vk<^hm%NXa zMc_^rQaGx*TU&J`sIihIO#M?~qYQVsc*KYIswW4%4guEPa`&S`6iX2-ER8hTwz=+& zrxQ4q6+HdW!;zr$Kxlf<%-g@m-h`pg^aPF^*Pb z8|bgUfnx@i<}Rn+Qm*reE42YzqF_~e+@}~ILOA6)`)%!HiOlOB_0Jn?=$#TGVeQE( zEK8SByh&P#`s0k~bDBvV4%WSb#mSpko~b(Q>)t%ahhiuv25`q z#Go#x%W5gBXOD&#Y9qGtC6BWq+S|Rpb|Gm&OOUf=BoXVqPjD>lr`?1KI~pRlCQb8} z17@^KG>2M62C(@QnG=r7zm!eNKg&OCiT&Rz6y6M;l(SD~cG27VnWe*CfQUrd^sX+& zv1yq^%`r?W@{jDd3o12~qNZ-7<7I~W8|L0?$uvNn7~w$4ioQDV71}g+`}6`qrryPE z?M)W*z19#Jj&h}Ag;z8yq93J2%m(`mO1!05=UauMi?m!zc21j)^jH@vjfU~>^=H4= z01KYIXe0BA8XPq|NFH`Q_uGFWfyyy$ns(coEXZ>teRwC6USX4NF|P8dV2V`6n5K&S zMw$a|5kBzP(`Vo_UxkZkW0_zSX>BpF*oz;V0;cN-6?E?}-J~?ETjupWxO>EN|clu@+`EmQt-z9y8u4vvfvom4|B;mp7 zPic3&yDCilnc=h|!+^R1MBUK3pZEEmynQ6+1uxXQ{Pp6mZw@u&`}E3(L)7wG`Xe?-;_S5$8@Q!Fm~eOKfl|NeR0#hXq9>1~)kaA# zkNSu*M-XVM<>Fp`wJ)PHh4bESMAs&6ICw@1QA8tM>mv@ z-FziLOs5C83-#hAO%=_iMbOD&^FzxcBK46xV5VPFL|T+kuMh<|Sb7J4Ady|HndFU# zDm`wH#bdNY{>2q#23KX`o_wb%K{w?_Uwrbnl@CguKdpp<_XUi-XgnFjsC_m?E0t-` z>eC(#J0Xn7zGXqJo^smnx)+Xuj)g@eu`iMW)6<5mUoC#ZOJG~FA&+PWm!epPR;?7~ zV_t{BLru)v+4ifq`lN?Y2nbOWQ36gm@JqNrK(%%ARPn^|lBiDSjEBY>W4D0_9Eo&Y zt?xX^Nl43b1%}GCA7NYT7Sq0xQ!|_s+Y|=!%g>254`So{ECl*x?#y*D(NtC%Xz6Pn z-E6Us7ufKY<={K06~XmYh(ehMAd^dCbA1ZR>pt3kbj$o~9vE*1ja+RSTM-ZG+277k zVJ1kkWPT(Hfj|n6C5I6#0xdK5Q|Ki&BCj{MNA9}yVE~>kuHL(c$wS!Pk|p+q*^~lr zp!3=uufjlE#ErMtLwZF%Mvw4y{YkT7sK9x8^pto3*mD35%K+kW9q4W&yEQd zs^e{GWCpqw|N=)T!`u6p%4 zO2>xrpiD@yYV9mb)~aFv7F*6HnkMc%ufPXwLB6D57Fl<1K+!zmun+Z-Ha2G%^?WVV zzbl+(^tcfNxJ@D7-d?i)YB|+$kK)BcI+laN(&3qw^$;bU9Z+|KiwNbNF20 z>BMC%H(06{kasKBKAEbnjR_B&uJeTl^sP6Lt8QJ;70y-dzm^}J!6+y~WjE@b$VVgQ+)gOSiqsbwVa>IlgiP4^HYMG)Hj&w??cEa<8DF zKKc1vrZ99;ba)t=oSCjEEAT}Jx{GCgqi^nMG`3PhR=o(p~P=b=bNYM%5gP+ zVLs8PTsz(^yLQJTow8IlbuF|zqMsUpt&E@kw6G!gr{hW0C2IK zj|Hdj3$`mBsK58BMswuxPPMx^Gpu9N46N%JjJslAiK$Wqq0DB>0C1wqKTO{DtRB<^ zzaJwxj<+YkaOetaoVy#;IbV79#(707ZcHx1Hli>fQTsqCpQdna)Ogt9*C&ob0{b*h zbHQTiSc}Dtr9;oRA0_b23PO`Ssi`P+3W(2V8p=@qy6qqRhUX;qyUB2<#)Bs$jXxwe=v-pB!LiT=1NkHU6 zcj<&Av)bp69$_oilO6)T!c;pKl2hA_ z0SvP}nJW%$Y!Sv9o3(qZETHg=6wCV@T3z|1evp|;wB3QyKI#45360H9s_vF^2!tll z0*AN5otxk0AP*i(m0k&QUwyZyC{yL!ZsgfIy8KK6IjQRB#^i7tR+(U^^O&@qdTyiI z^Q{xOtf8rU}cQXk7n17PD|DLcI_fCvc zmqMsM;Q9~S+aLVPZ-MGRz&HI9Z4MT zQ?#KccuYAc;Vn6wxwwuO=x$Pa1zixXLRZlTU(Nti)`OZpZ}E57N?3)- ztn3lAeM0DX)QmzvlE0<&ZS+(1VdAv7+uVag$yF8=N!~gxd(>(?W&jTzK!zvym*)te zpUll>y9IZ$G5kXS`%3qb^%Gcqt~uOkPRYW(i$R2gvF?R0-PlbmL97h_ibkPWu@$F> zGHMA3(hscet^P)Umc{@z9SayhXP-9&10;4Ht*^q+q*%9I_v=FI zK|Znmku%WNDw{Qs&sfL0)EDG48LkvfWswtz0cc^{{qHaUiV@rILmXWQVSw?}2n>Lf zI>G?SA0WjOwr<;K8w`-o3dR7dZrd1uv1lCCh5?k6AQ<4?!uW->3QLAYU{n5q|3yd$ zIW~D}%167W{vUc%Z!N=mSH2w}l`rs@VF#@W|E#qyXh-7zYxMu_8aWuxb~Q5e@97Aq zqOa$XMj7Vlr&_cmTbMMZeis2@j~+~qzC7z8U*gm5S8?4Hj+qM4&+dh-xz3|(mp91Y zzFfSy+5FjT8gE+xU)c)yopU2&SnsbD{GvHCBVC(u+lEH+o|0QnK^lJnf=01QTNbLh z9S)N1qzRl>x;&>_`|X@=sk?Az=4?Ee^o5S^=Cc9X$JUH-$J}73x7V0!G^zmuu(8Hq zfK%xO*p4E$q&CB{jd=f#cq{Q9NR_vmtvl~l6cSf5`wO{`~JuM%SjczUJ0N$ZsQf2?C(L^*wj+v(3ul5P;y8l92{N>s2 KKa5kxeEKh=GplU? literal 0 HcmV?d00001 diff --git a/CounterClockWise/Images/Shoelace.png b/CounterClockWise/Images/Shoelace.png new file mode 100644 index 0000000000000000000000000000000000000000..2691ec1294a52ec20b19d331aa40619fad6e9cf4 GIT binary patch literal 77353 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 IkhKc`ALKjdm;e9( literal 0 HcmV?d00001 diff --git a/CounterClockWise/Images/Triangle_img.jpg b/CounterClockWise/Images/Triangle_img.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8a010ca1507f1fcf404a7d9b9e98bc5d08acfdc8 GIT binary patch literal 10346 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 literal 0 HcmV?d00001 diff --git a/CounterClockWise/Images/pentagon.png b/CounterClockWise/Images/pentagon.png new file mode 100644 index 0000000000000000000000000000000000000000..063c77900648abd632cdb26b9e12a01efdd1892d GIT binary patch literal 25285 zcmeFZWmKHavIdF;cXtiJ-G{;5JwR{|!7U6PB)A3(4#7f#ySs(p4uiYP;C_dF_C05> zb-wfO{=Bo^VP58KsjjZ7?tY$v2z6CC3{+B77#J7~1$k*r7#M^l==~>TMCeZ&Y-Kwb z7<46DDJgXYDJg1oS0`&*dn*_i`G{m)ByFufq}c|V3LgWJJ*Nq2^pM>3uqpbmb(Myr>px(RFkSy~$PhK$)sQ+!V3wC&>A&H5xY z;Q8+PTa%j&%y`MVLZR1Bc9^?waQc##jCST908y9N>aZx(;%K1rTURDwQBg#367OfD z6~nL;_3}o>re~pN6B#w?qzhQ_4VqE>!Mi)`7dRN>?$jYv80ve;wyR;d5?r;=d2vMe z5WQc$3!e;s^rn3>EU8vdToZ3ag5i!CNVI~_T}HnumGtM|nrKI<%8;f`fytE$6%6Ot zK%tHe0%`j{yVHk$?xeY3$v*0EvBq?RfEIf6vZ53R&CHv4;{*<0SO;EG9)W%FSi(xNY=Ul>OCBe=v|di-&K0wi#8mR=-P%_f zDSK3xkhdKCviW1fxN^=kp)3e&xJ1s0yl$z;+v^deqofO$A&oSd^qZA@Ze$?tWRt=t z1sO+fgPs7bw_BL!9qfekg}*HNe}3Ia(hIMnu^w{6%b(%@u2L0_Cu~Wl^_Fq7A#mP= zF#=uZ!a}RY5(kCUN59>d(ZoJNemG`k?H8PeW>TmPR!(u`D)NSPUPuSQY@MnsihM~3<8J$A+r8Xlk9c`jTd^~@uvw3b>_ zfr24Bt%r=LA{L1Qj_V72Hw+r1>0g8?2~2FyOa7~FlY<20PI&HkjF3*5e3JBpU!)10 zqB!`$Vl=pLcW15YGe5EMC7+7T%9=f4^?yxB&O{rY5pVcnV?frNzJ5xvoHszdrTEnQ zayA-PwbNBZ{!ko?!N)}!V;-Jb$YZI1&Jc=|AC4m}w}gPz4Sz;FAJ(}O_^{zGHQ`^y z0DR|;ONm>K(~R6u6hZW-{ZH7N{$Tb!8p%YrojIY+&+#*8Sbgv`Vq5)bjVR7t1LA7- zK;rxBpbxR{T&=EGU0>M3Dt?t$nc#iY4ILXvfk)ci?b9 zpmpUZ{(ZN7kMIHpIa^3j5VRM?4uOY3GK3jte)>_vf%paU=IL7O4pl$zLl}!N+@s`v zr@#>LcX+!sn2U3m6>6A}FV38py@7Az5sSK+qt?7r0@F+}^^g@Mg!E8m1DPvH?BQEF zjVq~m1AEp41u;g0mDWfb;dRvnK#2F9WSn29kx}yK(0hri#O-lxdg0Gyg5sUuA}WYa z#-qO_OQ1%z#Dq|2#+J(diZ7F=fbh5?3&m#201^xa;R}$wB7DWUl0r#yt$$JgNUvlT zKJuoAs7lmKkbLC&5X3IWGV#G3YcZTsZY+Opoc)qyF%DK4&B8q8JK9c^OQj$y#ounr zd0;8}@6JzEh^23y$8;;%ONo5q@LUi_yN%XRW4jYwL`C6q!Z><rD+pCs$B*;S&(vt31&1#HzqX3 z%_|Bs9ClIMcX&g}ZIp+vY0!Ao23}vghi}J^elSQf*Jn+!WmoF|5nR zcVK>0uy2o_nslDb8N(HQ2;-X6o%oXEfGn0vnTwUXlpkn5-`D&7vobqRTvJd}j#t*5 zS;zwNHS&6RAswl#A?5k(#{!M;gz=xlA9E)7^0E3^H=Q>PH+A||`frq-@fZ?O-tnmL zr)6^QQ`mBHo4yUOTo`A{|NOW4pX8RE z^O`D+P>l|ZC>yzrEDVX7_?twj9C!eJm%k>C^Tk@cnzox9JX`C3GqSpCV?5cD#<`|r)oYFjlJ>%kH)I!x_#xP9a zS3#>*?KY3d{(1fvPnZvFH#gTDXRD_#x?hyU9Xn6H6k8k*pbj`vJur?l#}hU3RkDN= zB;nN3|74lx{!U~__Q=@_kjAd2+d=^+Wc94{_){JbGNXwQ-=}PjrTw+V=;@~I8R`af zU-cyR{O&%L)0453o0hwj@s=5lwU42dmXRxqZ0_RQgfw|9wY!LJ?!*d{s6?qomq+>& zZ{pKM*^$J=1gRs&_OWpgs*i6kTl zvblI}WE6}S5GZ(lqxeSf$AJmJl&E!}xl$BbSgv}UF6h0n6tO#{JlShIvR`nSbV;%Q zl-SKsmN6}|VCTBOb*ObzjISajJY)H3Wtwivz39A%VvyRh!1`$Pb}(vl26E5Sl*X6l z=ZhI2@{&d^UHN{T4jsRoQ1lP#@Q17`USUojmCtdEdfGGx1a7@L8$?1HLK$u=JN?@y z!xY0xBj8lE(Xm0Xw-c#bimIvtImWzgS_iCb$)88ga;h9ZjBpMJHBF zy;d)jcInmvi;~?*3?;Etl%dh&mSo+e0Kt*C>Q)XmX5wa}O{N-C>gw%}4?U)4v&x9Is=P!z+RXiQt(2`U5Hm1X1bjLQSuw?(Ci~4@}c7A=>m_}SYex)PX?JGY5j@C3Cj!0W5Mly zTn>+ad%Ku-02p=^9;0LaS<@}vrLq*qHgjfv?(L_8PpWn&K;9E|110glT_#2W%U<&k z=PR5ZI+j??xD;{<;CtWF4xPnCAK=4ne!Z=Or>Zj0|}UT6pXJS}2I zc*c9b`bK91Lmb|hG462aaOnBXS^68YG6I-w4G|`U-0bWg6*>s38WtZB#tI1e6cNcJ z4OaXU>{_C|v$N^u+FJ23=ez+-?Wp=HN3vvyXE2+iqWi*+c4S|=7erY10E)F_X?^JF z0>xQg-wg(akpA@ztDyPz35DMa{>~%g#wFib_pQ4Rp1% z253sl{<}K#Hxb&8?(WV24h~OGPj*ipb|+UG4lW@fAr4M%4sLEXXbCnqFGqJX5SybL z-G4Rm|F$D-+Ejp-$hr0+Z?Q2K>{rWFCtw6T_)03myzlQ}KAjj(y z4lZ_1j{j~OS{3;EEkNBCWM!`>ZR=p==mzaWl#82}7x=FV|Lf8Jbon1u_5Y(PC;xxe z{EsL9t_kFL9l?K$=)ctUuWzCH5=8}a{I~8!QJatkA<*d{x0P1YhJM1m&JFa%2YoaC z`xAOki`uGjtONr?Gpisip$&pP%0g)^o4FmBo5{6go^U=LQO}F#ekV1D%`K-OUG%PI z@Vl}M&j>w=6{99jle9eJ4{YXU#|DE4%XfuW0qtWQHUYCOr8Z@r#{3GnIM}fN#})VYsKOIU!A@xu(FntQ|T<^=cy z&U^8ul68&K*gGB}?wc_JpB)!XgE1_f568zt|H+&>EAisH9Okt?DsOl`o(~kaT`&G^ zTi{=IpQ`O6G$`=9S)N-pMr`2vgW#?54>tRq4#CnngAPULpuz?0&`{`gv2#atTJ3uW zsWt6_3t%Hzk`?hF2>6GZ#2ipH$LM;;4TFc)__-Ad!z2I6-nF6Qdk_0#d7aw%xNffK z?qb)+a%-KR-1djwKWc=Rjyl+YN45D=CsZ&pPUklaaJ1C_>l!D8`oIUN5~Ml>sOI@? z5A^?`5H(!zTk2piwJl3&KeREsXhoub6cL>S+E^&71b)^FgY&Y-T;bK6$*N~v@;e=689(Y zfo}m!)z^!54Cu}mJ0pi_y)r~bNzYdm0fjPAgjbK~%Z&faxS;07>5Y)Ws{f6>{dS}F z=^Bj13gK?VK(B*4kX?&pDVIkgcNQNKD$a0fUqFK!kfgjH4=chDSmG>$8iMVNj;_i8 zxtsC_hq{@K%i0c~qbfOQ5U>U8X1W!%y(jvIN&JF5OaT{0@mUW58KlDtZIJjgPP&9C zdb?H&I^U?>PBAEg3gM&<#2-baJ$pJ05QCl<>utA_bya_tRx9p06(+w|gxZN+Gqflm z;OIi*E8nbMzKgx*s^5+K)r{`nwb}3A+429kwgQ_Zp#B4%I=|_7@mmCK#w?F_=b^DT zQbT2b??#t=MaUA;>DY3dlEP;2E*OlOS0OI*zt=6(J{-Zzaj7W{ISP8L2EXeChU1Qx z=d7f8uidPvKMXlb3v;2!!%1Jz9eL=B4*#hEN2n2xOrCeVJUKO=`kiLz@rs4iHJ3LZ z{Hk5?KJ24;itLO=K59NJ-%qzIPY44?|J*nKr+JVmA-ebUX6T# zd{K7(XTekj1ESYeqMveOcUi@+?`BP&A*uT`SYGnYTi=v$O<+>c83I`|L|*Z7KHwlwd?wZHZ}_1v##>SYDZ|dn#Rzf7AL9#N`M6pI3K0gbSk`)E6_lr zLc6@p#za@LYmXOWp81XFj&0{;(?-OL{HwlhBuj{IS_hnoLl!L)RiJBS!fLK#%k%xA zUyMHVk&NN`|M*LgUJteWyvc~C!T7#pwyNn z`YPG!kZ5T&@P*MC{E(v>suusl+0eEQ0aTj=ot9y zP*a8w9sH1qTGA6m#%eHdY@&yH>&tJIVhPUHt62lQ0FOIM>{cI);F1CZ`>MW9bjJd` z0MF*Btama^2BfOZjRWvoIFO!$-xVvHc<+ZDI__sGmJWT?DIJ}Euo+v#@V#r}+?D_B zzvFRWcrd4-#2^ac4S0SG^lD5XgqlLfRMx5Q?xK5;nUQ{myGtCB>nNqaSkE5UCn*oI zOsFjfymg=Zg&w&s_HsA22r-Nq6Ff~M40w51wVTVL&;}%^9SmIv7AsvX7b`J9ygNvk zvwoFmcDyunJeAc$53b*^Y#BSyt%H?;2_u+@ z{(|BZBq!E?ek*)EZxKe@9@+a52h_)6oRIT;S*%93U*WsWa%ZdN^Pyf=*r1q4?9^-Q zueCJfVR$~neds%5#C>M5o8_6EI#Z~Wdd+8lp?!JzHmh_hHRmF8cgxA| z(15b2Y$ny@elm5ZW%=0A3%V&8tq6EJY!kKRkt~|uri&G%1rsHUWG;KIioBe7cKpWZ z26Wu@;;9W^b44iMV+I@gp7&*|zH0D+^i|!$cMD_w^{FI0(_0P=%ltXe_(!?(I#T=4 zGy7nc1w;*Q^i)>;$xptFL<1C_hV>rf)gIn8UJ5om<};yY{RO^|KMcEbtvh^ajTph> zgp=1#w*z7)cJBU{`BYv;4Lj*});tiK48k-uu_t$|3yy%hD4wb~I}kuKHGS9U_jz9Q zJQA?l>%wdKp*ppV6*mn!*Q%}l0<(sD$|@u>@_?t6 zJ($K7Wv!4Qufwv2YoJo@w1SiWMMjO^$TGM*wRMZW=@>#`)jR7qY>hv19r*h(G3T-1 zI%|aS`S0MYS<2@1MD1h0Ks%RH?SyQ$YQ3z#|EbSv z#=aKq-f(??&0K_WpjFay#NIOAc@^d2waYze{nK^4C%H{#%uzq`Xb#WQKS_r zP`3d?Q>pEjg$Mft)ndrOWE5`E42&Y~=CObSMghd}s;UYMn+rXU9&TB7GJ;DxGkL$6 zl-vRfa=HB;aaBMr!jGT2Uz-Id_b+l@e6KE17pOwIVs5OznEfuRhq#L~6(ypeAsX*} zOi#@!CUJm=mtvgGlWu_BId%$YAsgT#u2PvNe#?2S(*cd`RW7GsvwK-pv|SHDga3nwJ^D_-^FCckXp@pTJT1#d)G1MpSR1i1m3tnSqpai~RD#;#~XeUtTjU z#}SLqn#9CBf@3)&&uQ-d<&?M3sFN~5CQr7AbjgJN$GLJrUGxltXR%DpACf4l7qb#O zC2Jr_BHJMyCN98WkGOS+*h7NQ4f@N69vT;A=zq8E6^y~}987wb*rjwSB>1|!%KnTV zOXa}S#WrWzn2miY^E@T9T7M@y%3rmp02dCrUuBkchJRSCvYg=_WF7mPUGF5 zvQ>(CdDJfxcfQa)(vcz;0bxEb`2b)w#gimUA6;&pNroYblaY*nIWIcJY141Oi?obi zSSJxKy(`e)r*WM^COFci03QfTmnBaIAY?QwAQ`x``z;j=7h6q0Dd;XrhYncLS+Ghq zdIatZvSw>V6XWcH!ail%w5Sy)LZmG|pn71hYi6sDo?**K^xYDoGnqIb(^)fOf}Cig zYh{T&DB(cV{dbJP4!suqW0f3kKAHDc>cwm_P&!EymEu&M0U)e2d=U=`meb*^_JH|o z;Js3GQm72Rk9$U!?V^iruBW8u8dcjan|HJHZcS(o736AO!RpG7SADDK%rsGw3tXp1 z#RA}>b0W|UnUi&!!bW=5ChUE}L4;@1>H3JXJJ1*Wr5P^qxON6>Xa-dIJ5UH1W*m#IvD5VSwZ&b&_r?R$8Gts)t4ao;SfAVZNB`q$zQB z$F^Uaz1Djay6B1PubZmG#Ie6LF_%0p5KC4Bh935mhG{!*_5W4LE9)7VvX1L#zYzMO z12Q5_^js2N2nk055$*Ai^N&(D6`dERiVP+2@KPsdaH2BP9$QyryC%BjqW5vuCOV{! zCdn3^hjNron{sV{l1?%oy9xtHYgsjXH{9nP?suqkq zWuDFu%CK>3S>j8qSGi;s-&gEgy?lYkBv!*}*sJ`Z{(8zguI#D)vuFEO_K_Qo-B$KX zEPb~AP0Q*N>66)&wYD!5V7V4!U0;gB3Emfdt5a|N4!t;00+7QYP3 zcMU$P89rYkOIPbkXzCab3E!g?QPR2T9fdmMul&_53<&ZrlW-4h^n09Qf8wRR++5#< z)If$d_DHOC2vOwwg>{QXo2-W60wfi;FM{f+TyT`Qh@ZO4c@A)FMm31s@$h|$4$i?& zd0MiW_h!y?&!A|Y!ZK#}x5%j->b2_K8^l?e@A@~P=amwkFX|Y#bOUk} z(qn3<^TW88t~{o>;r`M1y62(51W^FrvNh-TsnUS(WXOI2bkKsa5X00tA1^tm=w4Fh zoRQA#t!LeWOLsBe3Di}Ur4-2hmopz7g3NW*M#r*d2BVt`Miq}_e z3J)iASscO@2_2@xJ~I;RU;S0be%6n<8B;5%5b)}Aed0UNINdr1rL9it++Q2s<$j4k z*z2D@N)(7#XTOrJ%+ZJ5S48+Bnu19y<7~>qO%Sv8(H7*g-yw|QPsztY&pX3o6CAPu z;hTj#(;*o)jd)&fHmNj8e@2+-40%_9c~1`frjFwZyJ8UIyzbsI6X@uy+_c|#-~w?e zWm-PK>Yh%uBPSuKzb}F~TR0HNR{n~4bMv}CyLucL6kQ3D2N}+rqr;(FHLL8>5or~Tkka}7Lb)B-bV~yQb7_v=;}9!p?0wWb09I^d^9Q6^sI}g6 z6(&tc%7)mI|H93NJ(I;(_1s@a{(|Ae^2|?C$GzkFvB@7Cq&JGpf(xB zG|GpkT?j^KZv1)$!VIey+NR{drx^&dqHt$I`3?9eIQrm1LtxhbAb&b z(Uc0FjUvz3KB52BUE4__74mN?#D#7KXfR&?(SFE%+`+IGM=_z8LZj17hbPa%PaWsH+_9yG6F(xx7ADKi>IG{xJ<}1yL zHt1$tRAgU44dQ-S??_{-c2|IjnFlWe;Pk6Lh*8^3+RQAj`M{7QGK6gZt_RAINQzK-;MysLuG60c(@^RXhmAL_sXWb(Fov4pwG~``F;_tCE z5*eI76Ay=I5j{tzZVrns@^9jizS9a1Ns8wCCXK?Ki*DyiDhJC3_}unTokai4Xf6{| z0S|nkZq^mZ1Lks6@>?SxlkIn!EZ5F3I!!N3$jNo|jH`-$kx;#~Kn(dqHJoBwT@UCN zasMtc1ca+0GBPt~KluX?q->}6uD()u*V~7V^#@4ssPttUw4L>oTe$KVUbW^>i}&J*F+epzxrxd?_a{-7 z-aoSE!n-56TP93=bMvEI{KI?#X%g)E^jW2v^6w{#*&3F((=^PwJ!U9)uy1!GJi!hE zVpfObZ-3wVf<+m>4bO9~6aHqMY+1Qt7qcFc)7?&n!1F;K6T=?> z{_~@1XM@vs?gJCf`ntkz9+<+#C1RyrDzoG6u~lY@4FQEyfV4k=+~+z~y##;$^t53; z-3Ke7!^?Me_}^5-E_c(qM)hkfqSzQRCf5cwsRopBZj7{c5=kWez_Ply9^Ww--(Jk0 zpDFNYo#CEyszrc$qy5V?l&vk(oz)63kSxHml!+>d3f8&uMUQt^R*OmC%-T`C&58gW zlDi(K7n{RM&;qsckSwx^7w;RPgxJFGw8^D3H?GJA?FhEnMSlRi?GC651-0A$8P&(Fj;oKapMy=ZDNxRE&2XD# zvdi=wW;{7Hm916<0patOYgA(b5~cwGSrr-|!bEWxx=SLe!c*in^~4v<2U zIG?7vYsv%K#g`(Q;wY0hLGY{!ixQFtCkobO`f1uh_&&TSsCnH;4PNG@w-%kFC-drJs@O=v5sBSOVGwW&?`S=|fEqiud z#d=uY>S3Gc>NXCL#ozqlowsl1+{?^$8@MJ2$0LkH<(=WDtPV>G0S=qJ{aOL!#|a#T zV#W)X{E$BItJ5nEZz_j&4|crmPN2`mmdN9ABavOo>ZMAq zNH$1(9Qf#i4GAMb{)XY-A}Zx&p21&VZg{VP@seOOymxR{w$5h6k?+qXB|T?1lvpWM zT-}u=4c0`x!oI_1dbnv7D;>9$YzTiC=IXvWosTma61>6%`0L!#masLfZGQofEl1yH zI1lf4f`3COM=!FcYoZ9*T#c%LRN%^O{|!-t4EQUGyDv8NG?o4QliK4}@@N+bncA3D za`FDi_Xy4C-69$SI$+*QwgZ>v;m%X5p!?C*^QV>O0BidzQLHEG$uNE}A~vvX5A6q5 zisWr8!@j(*tY65ysRDQKC$ADGErEQZA1o>iTl((P^hznpp0+-_Yf+3RrpH*ucXU%jc_T_KE7;G%`!a zaJ!@*+!|2%@q!4eW&!n(OeRw=>~{pGLs_#w8l8hORKDo<0ys-sO_XC)K-gbFVJf|B zz=)r##1ws6QODRk?RRyhPU8-}Y~>XXY;%U;&fr@%In2Xu2Um2_B7_IwlokKw6Z!yW zHRaSOJCZ-UZ3jT9jdV!r1ZVlKessT1q2WW}Xd+{|4L%1beUdQD=Fvd4EM~Xv{IB_b z4FS-u+b;3CiKwfGuhp~Jt5GM1B7bt)ZaquSI9R~RnYq|0#g5g5vf|BwuU63z*rwG; zRVe~0LRtAa-)8s%2FN+Y6BnSVh2oS2!qW2P@xZz=(K7pBxn$BHn&D9k*i}-a9b&QV zt1Z>bZD$)}YG)^L`LszC7g>)`@phxveeYe+9Ol&guVZmv`H1_t%N$inB$}hhn4*OfwPMZ}FRSx`2vS^c@NR$Dn(cpQsHbx%X37m(pEa!-6^jeM868?UPJ zcG3TY%VM#>;3HD74hVOBU+oSGmWSx#c>E;kXAt?l58HZ2H_Y#!X1=)cho5l}f`$yV@U-&CV)ka(0eR>ENb=4_C79M+`e)w*SGe=Ndn-P#l?IJPfP zJ_YUA`|IDAutj|S>aSoFP{U5%nyqghbdO9C*&XSP+_X=EwFJ%F>q%! z3-4Fe%bpU`svG|}Vb#lQQ_Bn%9<{cDEDaTdywe;@t;Lt)=HKa(2S z6iXHZngp@?eAbsOwPzXw{TJ;5)&xSu1(p_j8htv0w@S0pjQG{`2525xr_PQSqdYgF zH(o0?J~=l6Ib#o^o@v52E33nqLc5-$!$!r`_(e(n58%~M75;^{hOU3;;l;WL%ALQS zLE+E0OFR4xB)5yUCTG8N+n9ZiEU3_4f#;$pMy;lo94MP`7AnwcR&e7#C`E~T;!)wl zm(t{YbpVABA8CB=r*a&J6LSPN!s)tept&TV+fAw$5U7`qGQq}n`DIW}6!-Iz%RnWR z!wYrt-6SjXno1PA?ZWDQ1(`t~q1$X!s>d~?si{}=Uab+@JlUw&%VXt!QAWSNcxaf& zkr@JDD9@p>FU*RXSixGji2RSM~chF>Fwsy{8vrE?-qL5eAjq3r*xz?y(Z_$zH#NMoamyEw!h)Yvu1=Jjm*AMVp!m)qoM8CVI7L@eQG5y z?JQ+`f^r*JbIr4LaNHpP{~@hxO&e%-*i%pY!wK1}Nx+jcl(PvrG~5MTHTiDNbv%0{ znWP$h)}M#+i5tSZUXI>V8KJ9>I|A!a{McW7B@l0Z+*sjtSJnfyWdWljcn$}{D#(THVgj>ywASi09zZ~=E-F9 zcC#11Jt->GIIm%gjqO+9zX#gyY{So2T)*{h#3}afXB^q`o~%oTD{!!fKwM-@cLwDv^=9#_eB|XWVj^7`xh) zmi?_)I^h0aQrY=Fl-7)*#`$j1^*pS;JUh35m)Qw-J-TC^9ymaT+swKVccD+I^<%-9 z07f9R8dc*@iqG>j*Bt##NTO$f>rkrU$e@4q`MSY5m~4sq@zCT2)wAiZQMYHu!*aIW ziT7Mf|0bD3tww1vi^<&(7uFM^zT|4L$?DcS0TkWV4FaEXs!JG$(9aSO!1?Os{3{hv z3B`azp)Ahvx}#@{!SLz7q&Y2f^!Qx~#To~Ed!B{2leD_u8#oYftU@zax>=0RBUNQ+ zrijPN{jYuxTu0d}u9le4m`VoxFj?LpY(Rb;uupmMXvb|IN2te~k-(5h|8L+cVTNY% zbf9Yi_FvkhOwFML<%oLS?-yhF8cn^a&EvmYbvN=S7rDA_=TDX!gPMz8(aOQO{h;= zCiSTKEKW^oNjX4itQRN)yN(ssT#wNYzcs(Lsx^&?)9GS7g<%UuXs4D&>*N5N<;Ox z-$D^3kz6~FB;h2{PvONsocohX92k4C`HF*SWGiQ(QS6xdN`CoBbOOX=NGgMh{X_>x zpLAP3+(PGYu>{%j;kD7uTd9Ddfq+Z(ON~h=Ic^AkyQlg};ew#%O6uW0n%`k^kv?b1 zV~TfDH)rhPGaj&)Go2X67HpieEBAi&wqIZr3#)ZZP*r~q0Cwu|yPYl;ohd2KLDD{$UbBYu0mSAEg4s@=NsZYm{oC;B9KXTiO*RdgYBh+8;II zytM^S8aK`Tw~`MVjXPg0@oX}+o%dvN%t-BaPfm>V5KEW{oK!`+>=*Ce35$eqguV6L z`^{srq;RhNx-Q;N>g5;;9c%eq_btsw&kZ5mm`9G+!PB1gGKf}jf3wK_J^VAyVG6zR z0GgZdBtG|TAw;5e1-T)xTm+hHa42df*}nThtNh@i=xAman*4AGT0$-zl0Ui^B(n|~ zaD!%D3!?rh(N=JiStlWm0k+Q30iFG=V3#|C^xBWcm8~U%4GG%io-{L%!|j6| z-%0Mpg>}j`_6NC?v?4zi@N4S#52xI}tI))O@?i}v6AMH?Ry5zPCbm45rdB?<+V9Et zG+2Ife}#`KdkzlA`KBx}cR-`)6PIU(_8C=19XC*ixer`LX|qpM;V&81Ao|PIU8Y4M z8}fc0ZaNsprq3>#^XFgQ0qLxP!MUGe1=XX-C-)-IJdK-auU)I)s&ViYG(1B_E3Vd% z#2R1ee!%V+4=r6)VB?M7iCfO2`%=fQ$SKKKhDDns6$ky1%+{AToV~5|2Bq%Hn!=%u z`&XB(yCP0M2L!@2S$mKhM&~j%3%R=i#seT-#l1}+*)=I3g~8q1jsN~cy`useBU#+! zF+7ediN2a~koS2QEAW0qAFl7%6}@Tl$Uo~hqs)p_WTCfEVoA!Nivw174^}fKqDqkk zFSe>B%P?yrj~7`^0F$|L3E+t$k6#_+jXvAApXOis<@?XxnE|Pw84}4=)ibFbkK4=y zjhVaiuZab>l&?!N3n@duruL*p^GEF+dgA>YFAGp1eIg?L(y*O&-qGYN>!*U-Y~mi3 z?sT+J`lU>9$w57B?Xk8I9<7@#ckvaHuAl6Jsi%6E7DiZu8Njrg0?}0&u7VQ~R``lb zu`RZvqcrzm^F(|*1B8d~!=&4Oz1IeFlzpV02bZZ9+@Bw^lRq}Ds|F|y=BE4~j_2I6 z;dk_ZV+w7>gB({-1d_BDX%tzu6tbx)GRU!~F*Y%(6S%&)Hsd;)s`)7*wkv8$vA^#`9<-LMZoM(@)p%7o_WseAJ*RNmM_$`0-`E6E?pbDq(zMzenID<)ww^7QfKR0Eph_1up~?sSB*U*1 zf~U|&3+K!+eQP?^PLq*t>^9il7$k=`g=)JIxi}eburI_di&4NILJT71a~y!XnEa7m z9U;2iU(-wmoD|mcS?851SRwj*=Gwem)@+7A?%&8Cl5T-!jBcadFLV-eVLdglu)7hk zGu?)p!s0(9f}qR#%};y94>Hp@H-=5Fg*FxTzjWXH3FYc;dQE{laT_ken!S^4>sssK zF&mDCj1}=m-)jtfFeY0^y!#>%!@U_4Dv=wubivmgil`<-Cx7RH?t^;?xYmX{#rIqyPd_ISPgJu;A@0JY((`LtJIV4fG(MW=WmUfT_Pq~iT8%|xM8_l#K zCyZHx4!A=@w@@kB4X&*_+T?WZBn)N&)FpF5T`>e|Uu3u8_ z8T*UI?8#qLia3RkVH(k95O*w}<#v4G0%0Hb`e(<76(ZLHsUBWWDR%a4V<`}q;Q{Uw zhpAof>hdkV#7w$J4Boh7KzKWaw0pV z`x;z>FgKU(AUD4~BqxISEG8_V?}TeK|+4?s}Qb(JJrg!AYl&Z9j}W#@*z@}1hCwb)A#Q7g3=1-zT{3SOYR ztIzL|*+V8vL@ZM%p{$`+!aCsS3RLV}M1v+A{9=L|F>xdA#yIIewVSGJ`+1)#y0JTz zW@y=|5a`=iUbBCdP+P>tC0zQp?w6Mxt?o%X z&W&(YS`K53*3;}gWyaEYYujmf9CpUXyH3>oZWjS+CZx%TYLeWG$Jb5!W|Nkh$cz(7 zfQE0Qtd=5CC--&MyY3kNjYz_)jYykMyh(^-ulYa8WgY5y_`HQ?C<4fO+1sj~&01;` zzzVq)E@BS_;+dp5e8knl=yESk=cc)zC;}lrSrU@Q+)*`umF{S8WXi!ziM2?pE|8K< zs2BSh2!#DLz(eHpN-*=1Ja4}$bD|g%P+{r14FXnQVVR3s4mTEmyLSVuzlUu3WSa#f zIIMN&+)yBDi(NwxSS`gLC2w3Lc}bpt9KG>n%eVx`Jy>F`cnke8OQzB*skrd`V~By- za_;NP!KSpD^HaRY4dp{cViu_;IVpczS~k*1F$RZ$I73)23J3<-)EV(cgN)zgqCV3v z5&vzYgj6rcX>0+f#9f?3#Ub|CLh#2apHVaX=; zJ-X0!c>JyH4vu99j~`mnoe{+udN{kay8?>*}Bz8`ZRRM#_D+!x|0#FFu1nEQ#7C2ZKT}Y@WimTb1z^d;RD8>a_352mkAhW> zmD~3u?vD8gs9z|Gb^F`)gVNl!{wVXgkuMKyVaOOp$c z?$uV^0<5Q~X^mD;^tH=1#soXNeI+*U#ZX{q>tw0GiWZP3Dbn1HsLH6~@if*@g$DTI zkE!A5yrf722H9toyH8XV09kGa7LWSvxmfdn%n&jh+Z9jWA*6&5f7YD(h)3}}$MkpM zz#lKg`$nhUx~y?~>;6nxKe7PSO|eWX(^O-jba`w->$6rLKn6lJuA_elSC%pUxVMgC zz`C2$B8B%Jean>YOPK283ZB?=K%fv(ajbN1Uj>+`Hr@#rZnO3|2w-}7Zi(&Fb9gDl z=rpe|?@~{N6Mj`^kzxFX6pY0k9WG>#u!ZSYD=nWWrXqOLn(f*GU)=uJ*8ZKRb-`RQ zSh|Yy0a5c8TQhH)_4|h9E;#-@=zo7`wMbS2*UH>m^x|(yF@?jo(Kz%3<2p(^-L<*> zKrDU}g1tMT;=GcAJMl8jG}Sio=h#9;XAF2nycz255wr5@t0YAw) zVVuY>^Wx^S2y%CAFCIwLpT?;*n|N+ALVUUQsz2B`s}|d&%qHW{ziv)d_wzIcUPNUcVZH-Mb}v0zVH#`^usvaa zB7L%9nPt~K((e8~_>ds;Wk)g^6=oi20`@;i_B2zcUBdpBB=c2LwqOel4rg=p#djHZ z-cwE5!dc`HWrAc%jPP#9kdk?S>H&X!hf#H>A;LL$yl+#D;z!726&K(f)7ui(61Jbu zn5>A8rV_{aDcX-=iTW#|f^w>B{@1SwB&}ZMywzXolM|cnM8e@D!nx&>XJh|d#F?+6 zG#HAr*V`kC7ez>X{=(uHCn`Jr&F3jX&;sVGc30F_q?j&lqMxOAY0>lZg6obQ|a zAz)1b%g44Q*i8%AV?zBv7kEnLw1N1}wGc}h$*i9aXNRf(Pc_&5)>N}@g&;**FbV+z z2{oYf-b?5;B35eXAVeurrAZmt2x6|<7kJT!?05^tJWCN?(l)*fNc z>sMWOGy4=NY~8B9@Rzf@ok6 z-|sPYX70pdX-qi76ex@4(4`ES0Da>?`#8FQMGYat*?_3`*3J9Mr?bSZgr~>%LR18{ zg+G2CGHa{z#B&#d)+0Tkq(odTytwYA8d;@((|#P;bT&Bl=7^B*^Gn@gFh4pbiqdW; z6n|7ZPE9=s8hV|6j`{lga(K6JreV?Y1MDWw=|t#Z9hSoF%p1&iSiP!D`x3tsH~Vw` zE_g}4cUCQAXuYjS!#ubX>WdHP8@^6tU79D-EnRE5L>CYG&WFkSI(%}3GmO>LM9su9 zt2jgrOa1r(vlh35@PkoHa~g$|9-lRaN?iG7+VS&Yb++RqnwdGrJobcMuydja+fDjQ z`17MOA`ib-xnVk|^}mO3;=ngW1ntV`Y3%)?otSKjT9aeDv=Fy$*xU(*{`Ok5B)K=k zIA%UosSe$4cj#`AVT3tOkRb|`1*+{RL&5%&h2VS98)@pT;@^^}v9XUIeXBf!m zb0HJ_9h_0-_KcB*>DOd}#(T+K{KW;*8Rcw)M{+3-P%%**@^8Y$OUu@N?kh1U<`y{;0d}FjEeN{4e6|E&2tm5%iY$~y;L{?;m zmZiMxUHZnZ?jfdv`_tkyG@{5u$SeuTD^7&L-MEl5(GJm-y0)0HyRoX)p;;2~LoJ*f zQigsX!YCU;vm;a%zC|F=p3X1qx$~Z0+Mr$A* zE4g%0v6tu8SEY5tFh!_aF;%xcXbm+`G(U4GVD?_PId{Hz5nIpECq@5`3bN1!+0Mj; zdl>QW3`vEOefWaysn(uQe(VOj3L# zM*}p6P%-ofxsq|K%xf0d;w{#2ufeoYf&}N_NWC=aZk) zM5GPxcPe|iRy*GJZ|xj$Toc+Rr3KUevPt!U^%!PMi=^+SA{(gERA%%w+o+6egCbB@ zwIpNQbv}SNfHjcQ_?@&lyfts$#HJNBa#Gaz&}V{qBE@Znby070Zm6U8$3?QU)qoA; zrY+t`l(i>A1#>F<)}qUP~Mr?!)q+CT# z(p&85k}W(ej5J#(!})5!z4**;*xr)6%s2z?8U0|97xX+Wj(umS(Y44ka=pAnqIR+H zf!v(K+sib9&eVBprpUX=-t(MPqp4EyTNet)w84RV$nkgUfg6Rtt7fiT45ipk%&U2- zTre0p`y~WD0y!d7H4P<@_I{`p*{?t@%4D50*XWHJ=J;joGH8czFGJ2TMSU5K7aSK% zv+rfjKWPkaj?6_B7jEa>{?Nq>khQzU;XA~RB|bRE;W`yN*3EmvO-n{ENn|E-DeqT% ztfoD(5-toz1wG^&dzt-f&KRceZ9MR8Nn1KkLn>5hGXl2QBC-PGHXuK4?E~h}hBh2k zk0~5#7^cZ%^`O2x?&^K|EiMW-ljJy${mek0ye$#?JT1gch2C5W25$*JzlYH@o6D0R z;CmlIZi;wJ2tG9KB&Hgr*yQslnHO%2cu`qjb%l zrsWz0q^N=emMo_Gk77%=IibBWFmvqNxRH_1lc^D+nFZO<8a^7|7{MkbnS_>4tlZr) z-P_HTe0-sy)U6V+TQR!?LT6qaB7wBKFb)e`;sJkI?&)933D(@)hSem;)SDD4?Ut3sXLIbX+%%x@#c-rJ9AOsO^7Dt`b(9pC7U=RDn^9OzVaF0t0qB$pcn6k z$;g@QQB8O1F9&3Ud;z|BM7B*sfvr~gL%0kfEWb4MM*e#Kp(R?GD(E#<2h&$IQDRC&{SLecf*gBZzb49f$2OCUum2s&J6K-m=oa%Z(XXts?Z(n$`)WzLX z7nIihIP}JyN15DR;iTG@Q93fL8LJh}Bj!`Q~s(WWrlcQ);(&8nbV zOUvoSsh4^*tWJg*gj4w~Kb=6!FD-78S{l)!l$*(W*S)T9R2!vr=bDn?w?PF>=-s4yb@pF_}0ebc@VT-PX(>fHL~P~?_RPpIs0%*z=H6}gZ~_~r&^of zY6>xbpq(abRF#v4C9DkZ<7eY2?Xk0qJ6mt0Bbf@ajVY&RTPMVHhl^BrMoT<{lhbjV1+vfWhX z7Z?lds2BlH_8GXhB7YBGitXxt&}jwD{(jS9S*YVZ$I1YMB1-OMH0?ZtFAMt@NWWOL z3hAA%Uf)jtgd~XPK2NqtamFBLded8JBwt&_+`&>*mmGs)F-L%rDSD3QKwv}>t#L9Y z(Y{%}2#<_AoY@j!)dy!YFRlp&_4@HkD03(>t{Y8Z4=TL}+ExfhGTW zM94PP=S|R-k!n$P`pt((#S2n564`>c{k6WQ7VWheZd2UM%6)`08KKldj)9qbJcVA! zlkIqa;o&*Z`NiRT6p~sZ-28;py>sZ6Vwk_}#loGRYdV5=cy@PkQ-EDq=oht>vc8cT z?LOYX@ZSi%Wv4UCuOHX_~lazi%lyP-C-y3DJl3k<&W<$MOQ=9_7m-cJ1&SM(x(f%I!d zyL}DKiKuR0{*otBuFZQ(JWTzWrFpFv&_DejhcD@WSJP|U%~#)NgE{MVMhfT$XH0JO zzAP?l9C=ptJmzltBXtQ)QP5O%^57w=gWQ=_>yxVsGWs$8es;U*b ztrK`Dw}$O`YB3o^bwCu}KCrqydES1ORPrrl&LbpY{>6K)SG9{a5_u(#bTak19I2;+ zGcUY3NUg$|l41UBaEjCD9DI77;RUb4a?Y96c{Xg;F4+;JPGXf_1#?v|L!&{Us$@u5J0F`RFUa@M_nG6wQ>L z2N+r!mr%{&x%0+(<8(UBMcF>Z&t#xCT`Vx!bO*A1y4RMox_y`u1Xoq3i#{+Q37~4L zx*L~gE2fsUTQa=`nm!wmw38+I-#5RZG zD3p&1Rli7q&)plIrCTlSDR zd4s>qHzvqNx<6J!y*FYX4|+s`9ks1Oo*?QVrPhW@12r00^Nc9@A58WycV&!QX9Fh1 z=T-JNMaCSleKD9vO7)3;qBGG`3x%SdVJZ1H2;a0vBbUq}g(6M-i`&a_9xd~=W}5s~ zQlk|%Y3|k^&Sz2KL6RSpp__xx$_#F|*H+cdnAjd>g!LCD{#?~#q~n=o8hgR(UdCE@ zHIEb=k-uItNf+?K;7tCk;#+f9hWVs;rHphICgm?er!4T+R_6uA1N2VMQ|mpVS73jt z`}i|(+WJ15NKoujvK;L>cF>c9sWO=r)F*D1*7H}&OE13Y|6pNGxgPMzT}%1iTO^lg z!Z>Oy_l$!s#n#vdITJOocd0`X zxMKbLw+?sp?`0MG{s(SH4C8DMC<;PXiAUK7l2{FU#%E>a!5ZchJ{QG$diRpJ&EBg2 zO7tzuk84k$OO_!Fco`?I^`7btPxc^Cjh`%(vDfWOi7WO^1^$0ffkb%aJ_+eAw`)^% zi!@@_gMr=a*n?{b)vSj`$;o}2Ha`>`-toUDuQpFrH~L%RZ7r|wglCF)dvCRLN;a~6 zzHa=BkC_5mJr|r04|1l0`-pI6Wv5XbY%t}~-jU9@Qm596xc%L}c@CHKWfGZz$YE&O zvUG24xgp?5ga{cd5_Qn-RxctGL<+I_wG~A-VC#JmNx?SaXvcpmQSO*KSlbWij-CQ#NbUD>kp zB2Xvz1noLb(~{_Pm@7UgVS3@rEvF>UcK(1UW~p|=tg%$Dr&`seW!G4gJ|iwQr{Zd_ z3ixq-AZd8)^r>607SlI$U_jwg1-0ohDtY0=Mpk_a&CXMrCokBEh6xAQYE}ia=Aa6A zp&9f#hnINc*q1mPR`w>|K5Le+FFs4#p7*_^I>a1ZhTgQp&bAvyVcvPJ&MUYGUMuuT zKGgT3eR7|Nc!v4dGb8z}{+E;1x-E4~njS+m7U77^1E(?F${m9U{f+ZStW9*%s@0I+A}$VSTmB94o^0JqD?9jwGeTuwoOL@G&L^TB3hxLfU3>;vbtw&}{ zONyO4t)x1Hb3Jo^j}Ob;)o`Ujuca-OE9gnD5Q}8`m3ekj1`ed(C2P#M|J>wIjSQc5 zQl5R7Fh9mqdmxvTLvbcHl-=-YZg9`QSQ_DysD1ih^k%oHoS-Pnqy?btQD4Tl1=?W^ z%j>mRdZ}L%R=rfJ6PYya^fj2F&5AKhpuk?KiSC9dRsawAj_9GK25JePdzHU>zXqgc4n>SL;P-M zRnlmC>X=nq!+zbeWY~vP!&B^{T>iAqqW(nnPePwZ@t`KgP3bbZJv{gQ!eBF8MJv14 zyDx>_AH!(1+SF*BXNc8Ab0@>TAIft;B63}2LWfRfxE@lXD|9&=RZ@vgmjIH~P! zrmQ4NkQu=uHWD)C=s!hZi^SB3G9>l(M4GKK_}Y3XfPo+Mrkx@ja~pO$zrl|faF>7| zt9$E9)rP7N*Ot*EXYri+1;btl%uwDC@H~RNkO1Cz#2DAyJ<-X^qPD`|1VK$4TE>#I z<4Wwp(GEj-?fDaq>JIzb=Psa$Xz&DZWn{&JtD_L-#`nTyt8a^U2fB4uMEQN3;BN>N z-a-);{!O$}?F6+K&DS|_wc+qs&a?}npWYp{U~yGp^%noGUXFVIuNLCD;oq_O&7+_C~voE`JD>K!vB(IsB7WR>Amt7KfGL_aed91gTdnAJBNC z(w+fl)yVv}3PP*|BOy&TyK;QF9KqZlN&HlqgY!>I7^q(NPLyV|Gfd+pa;~VydUHFR zgk)eJJfzd=dSlS5@WmGuWa1Dn&|G()3rtl!%BF(8&B2%F`KesgJP=U}MMFI1-=+9i znT}ew=R=h5x)~eM(^K&wXz-C>Ff~f+zrO&!7hsp37k1tZkBt3Pi$>V(h?em5)WubN zbtTiPq{pw_!i>?S4JSr>TI)-y0~IAB$1=z<{(*v5ca2Z~+0!50wh_ST)*V>g{nB(! z?Z}f6>(6d%d0ab_WT;q?A}^3q(DTQ&f9AuEKy+ZKVB?SVX!cha?0wZ|iL&2jMVqkf zo<<)8|4;7!>P3l~e-g%UG$2Mz#~XyX_9_4y+QJh!DQ$lC)2OR!eG?h;$7uf(H&q>I zml_61$DX)0l87#{51P5Rg*yefBzR$LHH7{FseiTYKL<2(t#c*Y++`K=0z7wS`ei>b zscts=DXo+ibWm2SB%S{^#QzQ|MWQEoKUrS6-ohIARwxY*sCe)Yw3_r9;4m{YjbmlW z&~FNzz?dXsE0KzC8|rgT?jl3z@Ct zVUst&iOh!S#(=-(z<8X)J*z=kF)hsI>phlZXC$S$L>rOr3EulNF)_ztUG>YiZZ$0zI{=nPjK>~HVW!;w zSOOr&^s_X&jqi=kmXtdHaUA?u)$Bc&WDso|I8{gJT`tMt1!R0R-b;Bg>;+%%b1din zPxAf;A7Q{Srhy@==-n2eXpXoQC?9eCPzyxSpH|FUMy|RFm zj|JPCk4#E{`Td`S{wRP{Ffd3nUcV`6ok&)}H9#Z!d1zsZSz!#333%H(6vQdq7$}te zD@3OO#ud{v-@Kztjm!!4RRVOs5}Jc0I>c^mtq`Hh2`nWSEv3O zsb3UGc%jyD*XnP9z|Ftwdp>{tF{)MJoUR literal 0 HcmV?d00001 diff --git a/CounterClockWise/Images/quadrilateral.png b/CounterClockWise/Images/quadrilateral.png new file mode 100644 index 0000000000000000000000000000000000000000..139d097788289c7115ae827f2c8a6ca3f3312f85 GIT binary patch literal 22372 zcmagF1yr2PvMvn49Rk5!g1fuBLlWHG9R_#z;O-jS-Ge&>5AF_w>p$#!?z!iDd$0A+ zddK?huI{d?uIhfCnQ$cqNhEk&crY+9Bxxxz6)-SJD$r+3SZL6zPqTg)7#O0gg{Y{K zw5TYtlB1oeg|!J7m{fR@8q7D<5!`Go6=`#SSSh$pIF&+KxIA&xIGQC`Y2v(rR8+B3 zhDi7-9kHH}stBs{WB6fBRD>q++WXM9(u#^mC_EZF6`@7`i%#I1lj(Vi@7v?s&sHZh zu<5cb=_2=12C&DUpEN{_sjLh&c_MF6mB8VMg%AK&502El0s_!NI3900>)N5oN>wdX zt#90Kdg6-2i9m3nZIVfh;m1eR_fKHDeJP{xV8l-%owwtk%04TGED1qF1gVz~EL&>l z52RUYm(@wjYzlS2fU!gmC73|u{zbg45b@#Io#}$B%@89_2Fn!<;R<8ih9iy%0DSX# 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

    rzWBHEevtv*Y_5nt#163>f=?NWwH!(dfq|hN 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 Int{ + let polygon = points.count + var orientation = 0 + + for i in 0.. 0 : CounterClockWise + } +} +``` + +Put this code in a playground and test it like so: + +```swift +var p1 = Point(x: 5, y: 8) +var p2 = Point(x: 9, y: 1) +var p3 = Point(x: 3, y: 6) + +print(ccw(points: [p1,p2,p3])) // -1 means ClockWise +``` + +Here's how it works. When given an `[Photo]`, `ccw(points:)` calculates the direction of the given points according to the Shoelaces formula. + + + +`orientation` is less than 0, the direction is clockwise. + +`orientation` is equal to 0, the direction is parallel. + +`orientation` is greater than 0, the direction is counterclockwise. + + + +## An example + +**In Triangle** + +```swift +var p1 = Point(x: 5, y: 8) +var p2 = Point(x: 9, y: 1) +var p3 = Point(x: 3, y: 6) + +print(ccw(points: [p1,p2,p3])) // -1 means ClockWise +``` + +![triangle](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Triangle_img.jpg) + +![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/triangle.png) + + + +**In Quadrilateral** + +```swift +var p4 = Point(x: 5, y: 8) +var p5 = Point(x: 2, y: 3) +var p6 = Point(x: 6, y: 1) +var p7 = Point(x: 9, y: 3) + +print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise +``` + +![Quadrilateral](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Quadrilateral_img.jpg) + +![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/quadrilateral.png) + + + +**In Pentagon** + +```swift +var p8 = Point(x: 5, y: 11) +var p9 = Point(x: 3, y: 4) +var p10 = Point(x: 5, y: 6) +var p11 = Point(x: 9, y: 5) +var p12 = Point(x: 12, y: 8) + +print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise +``` + +![triangle](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Pentagon_img.png) + +![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/pentagon.png) + + + +You probably won't need to use the CCW in any real-world problems, but it's cool to play around with geometry algorithm. The formula was described by Meister (1724-1788) in 1769 and by Gauss in 1795. It can be verified by dividing the polygon into triangles, and can be considered to be a special case of Green's theorem. + + + +*Written for Swift Algorithm Club by TaeJoong Yoon* \ No newline at end of file diff --git a/README.markdown b/README.markdown index 90b310752..efe89edc0 100644 --- a/README.markdown +++ b/README.markdown @@ -109,6 +109,7 @@ Bad sorting algorithms (don't use these!): - [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication. - [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. - [Strassen's Multiplication Matrix](Strassen%20Matrix%20Multiplication/). Efficient way to handle matrix multiplication. +- [CounterClockWise](/CounterClockWise/). Determining the area of a simple polygon. ### Machine learning From e48117cd2cd5efaec539eb83c44d47089edc5054 Mon Sep 17 00:00:00 2001 From: TaeJoong Yoon Date: Wed, 17 Oct 2018 04:22:34 +0900 Subject: [PATCH 08/65] Update README.md --- CounterClockWise/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CounterClockWise/README.md b/CounterClockWise/README.md index 6b6c1a1da..2d15eba53 100644 --- a/CounterClockWise/README.md +++ b/CounterClockWise/README.md @@ -70,9 +70,9 @@ var p3 = Point(x: 3, y: 6) print(ccw(points: [p1,p2,p3])) // -1 means ClockWise ``` -![triangle](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Triangle_img.jpg) +![triangle](./Images/Triangle_img.jpg) -![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/triangle.png) +![triangleExpression](./Images/triangle.png) @@ -87,9 +87,9 @@ var p7 = Point(x: 9, y: 3) print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise ``` -![Quadrilateral](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Quadrilateral_img.jpg) +![Quadrilateral](./Images/Quadrilateral_img.jpg) -![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/quadrilateral.png) +![triangleExpression](./Images/quadrilateral.png) @@ -105,9 +105,9 @@ var p12 = Point(x: 12, y: 8) print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise ``` -![triangle](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/Pentagon_img.png) +![triangle](./Images/Pentagon_img.png) -![triangleExpression](/Users/taejoongyoon/Developer/Swift/swift-algorithm-club/CounterClockWise/Images/pentagon.png) +![triangleExpression](./Images/pentagon.png) @@ -115,4 +115,4 @@ You probably won't need to use the CCW in any real-world problems, but it's cool -*Written for Swift Algorithm Club by TaeJoong Yoon* \ No newline at end of file +*Written for Swift Algorithm Club by TaeJoong Yoon* From 4c718b4023565795675de2b2755db3226b3cd55e Mon Sep 17 00:00:00 2001 From: vp4 Date: Fri, 19 Oct 2018 18:24:40 +0530 Subject: [PATCH 09/65] Remove semicolon --- Linked List/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index 0998349fc..d6f1fc986 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -490,9 +490,9 @@ Recursive Approach: return head } let temp = reverse(head.next) - head.next.next = head; - head.next = NULL; - return temp; + head.next.next = head + head.next = NULL + return temp } ``` From 7add278a6acf10b19e2f8f035441b4a490d0125c Mon Sep 17 00:00:00 2001 From: laurentaylormarshall Date: Tue, 23 Oct 2018 23:43:25 -0500 Subject: [PATCH 10/65] Renames function to use camel case. --- Slow Sort/SlowSort.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Slow Sort/SlowSort.swift b/Slow Sort/SlowSort.swift index 217733daa..c6e705fc7 100644 --- a/Slow Sort/SlowSort.swift +++ b/Slow Sort/SlowSort.swift @@ -9,12 +9,12 @@ func slowSort(_ i: Int, _ j: Int, _ numberList: inout [Int]) { guard if i < j else { return } let m = (i+j)/2 - slowsort(i, m, &numberList) - slowsort(m+1, j, &numberList) + slowSort(i, m, &numberList) + slowSort(m+1, j, &numberList) if numberList[j] < numberList[m] { let temp = numberList[j] numberList[j] = numberList[m] numberList[m] = temp } - slowsort(i, j-1, &numberList) + slowSort(i, j-1, &numberList) } From 227d6d9899d7f9abcc120fc04adc4a72119ee4ef Mon Sep 17 00:00:00 2001 From: laurentaylormarshall Date: Tue, 23 Oct 2018 23:50:21 -0500 Subject: [PATCH 11/65] Renames function to use camel case. --- Slow Sort/README.markdown | 14 ++++++-------- .../SlowSort.playground/Sources/SlowSort.swift | 13 ++++++------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Slow Sort/README.markdown b/Slow Sort/README.markdown index f8cc743cc..f7742b6a3 100644 --- a/Slow Sort/README.markdown +++ b/Slow Sort/README.markdown @@ -17,19 +17,17 @@ We can decompose the problem of sorting n numbers in ascending order into Here is an implementation of slow sort in Swift: ```swift -public func slowsort(_ i: Int, _ j: Int) { - if i>=j { - return - } +func slowSort(_ i: Int, _ j: Int, _ numberList: inout [Int]) { + guard if i < j else { return } let m = (i+j)/2 - slowsort(i,m) - slowsort(m+1,j) + slowSort(i, m, &numberList) + slowSort(m+1, j, &numberList) if numberList[j] < numberList[m] { let temp = numberList[j] numberList[j] = numberList[m] numberList[m] = temp } - slowsort(i,j-1) + slowSort(i, j-1, &numberList) } ``` @@ -47,4 +45,4 @@ public func slowsort(_ i: Int, _ j: Int) { *Written for Swift Algorithm Club by Lukas Schramm* -(used the Insertion Sort Readme as template) \ No newline at end of file +(used the Insertion Sort Readme as template) diff --git a/Slow Sort/SlowSort.playground/Sources/SlowSort.swift b/Slow Sort/SlowSort.playground/Sources/SlowSort.swift index 32bb38505..cf09dcc5d 100644 --- a/Slow Sort/SlowSort.playground/Sources/SlowSort.swift +++ b/Slow Sort/SlowSort.playground/Sources/SlowSort.swift @@ -1,16 +1,15 @@ import Foundation -public func slowsort(_ i: Int, _ j: Int, _ numberList: inout [Int]) { - if i>=j { - return - } +public func slowSort(_ i: Int, _ j: Int, _ numberList: inout [Int]) { + guard i < j else { return } + let m = (i+j)/2 - slowsort(i, m, &numberList) - slowsort(m+1, j, &numberList) + slowSort(i, m, &numberList) + slowSort(m+1, j, &numberList) if numberList[j] < numberList[m] { let temp = numberList[j] numberList[j] = numberList[m] numberList[m] = temp } - slowsort(i, j-1, &numberList) + slowSort(i, j-1, &numberList) } From d3de867354ef9f639e991259e8722b9b9bb4e202 Mon Sep 17 00:00:00 2001 From: laurentaylormarshall Date: Wed, 24 Oct 2018 18:31:38 -0500 Subject: [PATCH 12/65] Updates build settings to use Swift 4.2. Removes references to checking for Swift version 4.0. Removes unused import. --- Quicksort/Quicksort.playground/Contents.swift | 5 ----- Quicksort/Tests/QuicksortTests.swift | 7 ------- Quicksort/Tests/SortingTestHelpers.swift | 1 - .../Tests/Tests-Quicksort.xcodeproj/project.pbxproj | 10 +++++++--- .../xcshareddata/xcschemes/Tests-Quicksort.xcscheme | 4 +--- 5 files changed, 8 insertions(+), 19 deletions(-) diff --git a/Quicksort/Quicksort.playground/Contents.swift b/Quicksort/Quicksort.playground/Contents.swift index 94d9f8e45..f0427731f 100644 --- a/Quicksort/Quicksort.playground/Contents.swift +++ b/Quicksort/Quicksort.playground/Contents.swift @@ -1,10 +1,5 @@ //: Playground - noun: a place where people can play -// last checked with Xcode 9.0b4 -#if swift(>=4.0) -print("Hello, Swift 4!") -#endif - import Foundation // *** Simple but inefficient version of quicksort *** diff --git a/Quicksort/Tests/QuicksortTests.swift b/Quicksort/Tests/QuicksortTests.swift index 0a8f1a2a8..c8d9a62e6 100644 --- a/Quicksort/Tests/QuicksortTests.swift +++ b/Quicksort/Tests/QuicksortTests.swift @@ -1,13 +1,6 @@ import XCTest class QuicksortTests: XCTestCase { - func testSwift4() { - // last checked with Xcode 9.0b4 - #if swift(>=4.0) - print("Hello, Swift 4!") - #endif - } - func testQuicksort() { checkSortAlgorithm(quicksort) } diff --git a/Quicksort/Tests/SortingTestHelpers.swift b/Quicksort/Tests/SortingTestHelpers.swift index d699ec1e4..0c47cde4e 100644 --- a/Quicksort/Tests/SortingTestHelpers.swift +++ b/Quicksort/Tests/SortingTestHelpers.swift @@ -1,4 +1,3 @@ -import Foundation import XCTest func randomArray(_ size: Int) -> [Int] { diff --git a/Quicksort/Tests/Tests-Quicksort.xcodeproj/project.pbxproj b/Quicksort/Tests/Tests-Quicksort.xcodeproj/project.pbxproj index c1b14e727..923195121 100644 --- a/Quicksort/Tests/Tests-Quicksort.xcodeproj/project.pbxproj +++ b/Quicksort/Tests/Tests-Quicksort.xcodeproj/project.pbxproj @@ -86,7 +86,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { @@ -149,12 +149,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -187,7 +189,7 @@ SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -203,12 +205,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -234,7 +238,7 @@ SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; }; name = Release; }; diff --git a/Quicksort/Tests/Tests-Quicksort.xcodeproj/xcshareddata/xcschemes/Tests-Quicksort.xcscheme b/Quicksort/Tests/Tests-Quicksort.xcodeproj/xcshareddata/xcschemes/Tests-Quicksort.xcscheme index 5b67c6f70..ec81527d1 100644 --- a/Quicksort/Tests/Tests-Quicksort.xcodeproj/xcshareddata/xcschemes/Tests-Quicksort.xcscheme +++ b/Quicksort/Tests/Tests-Quicksort.xcodeproj/xcshareddata/xcschemes/Tests-Quicksort.xcscheme @@ -1,6 +1,6 @@ Date: Thu, 20 Dec 2018 19:36:18 -0500 Subject: [PATCH 13/65] Fixes a typo --- A-Star/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/A-Star/README.md b/A-Star/README.md index f362bb61e..b373d25fc 100644 --- a/A-Star/README.md +++ b/A-Star/README.md @@ -16,7 +16,7 @@ On the first step we expand the root node on the left (blue). We set the cost `g ![Step 1](Images/step1.png) -We put the first not in the closed list (light blue) so that we don't try expanding it again if there were to be loops in the graph. Next we take the node on the open list with the smallest value of `g + h` where `g` is the current cost (0) plus the edge cost (1). Since all nodes in the open list have the same value we choose the top one. +We put the first node in the closed list (light blue) so that we don't try expanding it again if there were to be loops in the graph. Next we take the node on the open list with the smallest value of `g + h` where `g` is the current cost (0) plus the edge cost (1). Since all nodes in the open list have the same value we choose the top one. ![Step 2](Images/step2.png) From eb9424d3f69d18a311c474907c2775f2a07d2852 Mon Sep 17 00:00:00 2001 From: abuzeid ibrahim Date: Thu, 15 Aug 2019 14:21:38 +0200 Subject: [PATCH 14/65] rename variables with convenience names --- Insertion Sort/InsertionSort.swift | 42 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Insertion Sort/InsertionSort.swift b/Insertion Sort/InsertionSort.swift index 2ad607ac8..926dad302 100644 --- a/Insertion Sort/InsertionSort.swift +++ b/Insertion Sort/InsertionSort.swift @@ -2,22 +2,22 @@ /// /// - Parameters: /// - array: the array of elements to be sorted +/// - sortedArray: copy the array to save stability /// - isOrderedBefore: returns true if the elements provided are in the corect order /// - Returns: a sorted array containing the same elements func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { - guard array.count > 1 else { return array } - - var a = array - for x in 1.. 0 && isOrderedBefore(temp, a[y - 1]) { - a[y] = a[y - 1] - y -= 1 + guard array.count > 1 else { return array } + var sortedArray = array + for index in 1.. 0, isOrderedBefore(temp, sortedArray[currentIndex - 1]) { + sortedArray[currentIndex] = sortedArray[currentIndex - 1] + currentIndex -= 1 + } + sortedArray[currentIndex] = temp } - a[y] = temp - } - return a + return sortedArray } /// Performs the Insertion sort algorithm to a given array @@ -27,15 +27,15 @@ func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { func insertionSort(_ array: [T]) -> [T] { guard array.count > 1 else { return array } - var a = array - for x in 1.. 0 && temp < a[y - 1] { - a[y] = a[y - 1] - y -= 1 + var sortedArray = array + for index in 1.. 0, temp < sortedArray[currentIndex - 1] { + sortedArray[currentIndex] = sortedArray[currentIndex - 1] + currentIndex -= 1 } - a[y] = temp + sortedArray[currentIndex] = temp } - return a + return sortedArray } From 92e797ac998b3f7a00cb1c2247c01d927cfa5414 Mon Sep 17 00:00:00 2001 From: abuzeid ibrahim Date: Thu, 15 Aug 2019 14:31:22 +0200 Subject: [PATCH 15/65] rename variables in the playground --- .../InsertionSort.playground/Contents.swift | 36 +++++++++---------- .../contents.xcplayground | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Insertion Sort/InsertionSort.playground/Contents.swift b/Insertion Sort/InsertionSort.playground/Contents.swift index 184fc36e4..e1d3a312e 100644 --- a/Insertion Sort/InsertionSort.playground/Contents.swift +++ b/Insertion Sort/InsertionSort.playground/Contents.swift @@ -9,17 +9,17 @@ func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } - var a = array - for x in 1.. 0 && isOrderedBefore(temp, a[y - 1]) { - a[y] = a[y - 1] - y -= 1 + var sortedArray = array + for index in 1.. 0 && isOrderedBefore(temp, sortedArray[currentIndex - 1]) { + sortedArray[currentIndex] = sortedArray[currentIndex - 1] + currentIndex -= 1 } - a[y] = temp + sortedArray[currentIndex] = temp } - return a + return sortedArray } /// Performs the Insertion sort algorithm to a given array @@ -27,17 +27,17 @@ func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { /// - Parameter array: the array to be sorted, conatining elements that conform to the Comparable protocol /// - Returns: a sorted array containing the same elements func insertionSort(_ array: [T]) -> [T] { - var a = array - for x in 1.. 0 && temp < a[y - 1] { - a[y] = a[y - 1] - y -= 1 + var sortedArray = array + for index in 1.. 0 && temp < sortedArray[currentIndex - 1] { + sortedArray[currentIndex] = sortedArray[currentIndex - 1] + currentIndex -= 1 } - a[y] = temp + sortedArray[currentIndex] = temp } - return a + return sortedArray } let list = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] diff --git a/Insertion Sort/InsertionSort.playground/contents.xcplayground b/Insertion Sort/InsertionSort.playground/contents.xcplayground index 9f9eecc96..06828af92 100644 --- a/Insertion Sort/InsertionSort.playground/contents.xcplayground +++ b/Insertion Sort/InsertionSort.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file From 6dc91c4a7bee34ff2b4fe9f4f2d5d77d3d42e55c Mon Sep 17 00:00:00 2001 From: Abuzeid-Ibrahim Date: Thu, 15 Aug 2019 14:35:33 +0200 Subject: [PATCH 16/65] Update README.markdown --- Insertion Sort/README.markdown | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Insertion Sort/README.markdown b/Insertion Sort/README.markdown index 4bad29aa1..8c2a5c1a0 100644 --- a/Insertion Sort/README.markdown +++ b/Insertion Sort/README.markdown @@ -91,15 +91,15 @@ Here is an implementation of insertion sort in Swift: ```swift func insertionSort(_ array: [Int]) -> [Int] { - var a = array // 1 - for x in 1.. 0 && a[y] < a[y - 1] { // 3 - a.swapAt(y - 1, y) - y -= 1 + var sortedArray = array // 1 + for index in 1.. 0 && sortedArray[currentIndex] < sortedArray[currentIndex - 1] { // 3 + sortedArray.swapAt(currentIndex - 1, currentIndex) + currentIndex -= 1 } } - return a + return sortedArray } @@ -154,17 +154,17 @@ In code that looks like this: ```swift func insertionSort(_ array: [Int]) -> [Int] { - var a = array - for x in 1.. 0 && temp < a[y - 1] { - a[y] = a[y - 1] // 1 - y -= 1 + var sortedArray = array + for index in 1.. 0 && temp < sortedArray[currentIndex - 1] { + sortedArray[currentIndex] = sortedArray[currentIndex - 1] // 1 + currentIndex -= 1 } - a[y] = temp // 2 + sortedArray[currentIndex] = temp // 2 } - return a + return sortedArray } ``` From 70fdd27222f6ed42f958b78d906b4a0b0d4fb66f Mon Sep 17 00:00:00 2001 From: abuzeid ibrahim Date: Tue, 3 Sep 2019 16:14:28 +0200 Subject: [PATCH 17/65] move documentation to func body --- Insertion Sort/InsertionSort.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Insertion Sort/InsertionSort.swift b/Insertion Sort/InsertionSort.swift index 926dad302..e24ede905 100644 --- a/Insertion Sort/InsertionSort.swift +++ b/Insertion Sort/InsertionSort.swift @@ -2,11 +2,11 @@ /// /// - Parameters: /// - array: the array of elements to be sorted -/// - sortedArray: copy the array to save stability /// - isOrderedBefore: returns true if the elements provided are in the corect order /// - Returns: a sorted array containing the same elements func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } + /// - sortedArray: copy the array to save stability var sortedArray = array for index in 1.. Date: Tue, 29 Oct 2019 16:55:50 -0700 Subject: [PATCH 18/65] updaing incorrect big-O performance documentation of heap removal --- Heap/Heap.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Heap/Heap.swift b/Heap/Heap.swift index cf39fb8a5..7560bc7b9 100755 --- a/Heap/Heap.swift +++ b/Heap/Heap.swift @@ -212,7 +212,7 @@ extension Heap where T: Equatable { return nodes.index(where: { $0 == node }) } - /** Removes the first occurrence of a node from the heap. Performance: O(n log n). */ + /** Removes the first occurrence of a node from the heap. Performance: O(n). */ @discardableResult public mutating func remove(node: T) -> T? { if let index = index(of: node) { return remove(at: index) From 7b08311b01bb7f4f2a261286e93e9cf7abe6da1b Mon Sep 17 00:00:00 2001 From: Robert Manson Date: Sun, 3 Nov 2019 17:36:22 -0800 Subject: [PATCH 19/65] Fix infinite recursion in DFS Fixes infinite recursion in the DFS algorithm for topological sort caused by graphs with cycles. For example the following graph would previously have recursed indefinitely `a->b->a`. --- Topological Sort/TopologicalSort1.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index 2ad9b51a0..05f1ab887 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -1,6 +1,7 @@ extension Graph { private func depthFirstSearch(_ source: Node, visited: inout [Node : Bool]) -> [Node] { var result = [Node]() + visited[source] = true if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { @@ -10,7 +11,6 @@ extension Graph { } } - visited[source] = true return [source] + result } From 0904c23f746bbbbfc5525ce32cf5c181c1eafe8e Mon Sep 17 00:00:00 2001 From: freak4pc Date: Sat, 9 Nov 2019 18:58:19 +0200 Subject: [PATCH 20/65] Use swapAt for Lomuto's partitioning --- Quicksort/Quicksort.playground/Contents.swift | 4 ++-- Quicksort/README.markdown | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Quicksort/Quicksort.playground/Contents.swift b/Quicksort/Quicksort.playground/Contents.swift index 94d9f8e45..bbe5d9b7d 100644 --- a/Quicksort/Quicksort.playground/Contents.swift +++ b/Quicksort/Quicksort.playground/Contents.swift @@ -42,12 +42,12 @@ func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int var i = low for j in low..(_ a: inout [T], low: Int, high: Int) -> Int var i = low for j in low.. Date: Wed, 27 Nov 2019 17:22:04 +0800 Subject: [PATCH 21/65] Update Heap.swift Time complexity of remove() is O(n + log n), which simplifies to O(n). --- Heap/Heap.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Heap/Heap.swift b/Heap/Heap.swift index cf39fb8a5..7560bc7b9 100755 --- a/Heap/Heap.swift +++ b/Heap/Heap.swift @@ -212,7 +212,7 @@ extension Heap where T: Equatable { return nodes.index(where: { $0 == node }) } - /** Removes the first occurrence of a node from the heap. Performance: O(n log n). */ + /** Removes the first occurrence of a node from the heap. Performance: O(n). */ @discardableResult public mutating func remove(node: T) -> T? { if let index = index(of: node) { return remove(at: index) From 7762f6a884daa51e4acdb5677c664bec38273f5c Mon Sep 17 00:00:00 2001 From: TL Date: Fri, 29 Nov 2019 18:52:19 +0800 Subject: [PATCH 22/65] fix: add use case --- Skip-List/SkipList.playground/Contents.swift | 13 +++++++++++++ .../SkipList.playground/Sources/SkipList.swift | 2 +- Skip-List/SkipList.swift | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Skip-List/SkipList.playground/Contents.swift b/Skip-List/SkipList.playground/Contents.swift index 1b4847c0e..55b9d3a23 100644 --- a/Skip-List/SkipList.playground/Contents.swift +++ b/Skip-List/SkipList.playground/Contents.swift @@ -5,3 +5,16 @@ print("Hello, Swift 4!") // SkipList is ready for Swift 4. // TODO: Add Test + +let k = SkipList() +k.insert(key: 10, data: "10") +k.insert(key: 12, data: "12") +k.insert(key: 13, data: "13") +k.insert(key: 20, data: "20") +k.insert(key: 24, data: "24") + +if let value = k.get(key: 20) { + print(value) +} else { + print("not found!") +} diff --git a/Skip-List/SkipList.playground/Sources/SkipList.swift b/Skip-List/SkipList.playground/Sources/SkipList.swift index f626da0f8..186286977 100644 --- a/Skip-List/SkipList.playground/Sources/SkipList.swift +++ b/Skip-List/SkipList.playground/Sources/SkipList.swift @@ -212,7 +212,7 @@ extension SkipList { } } - func insert(key: Key, data: Payload) { + public func insert(key: Key, data: Payload) { if head != nil { if let node = findNode(key: key) { // replace, in case of key already exists. diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index fc635d0f2..8a1959f70 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -212,7 +212,7 @@ extension SkipList { } } - func insert(key: Key, data: Payload) { + public func insert(key: Key, data: Payload) { if head != nil { if let node = findNode(key: key) { // replace, in case of key already exists. From b513c0331b79a520cd30569913a624eaae8fa7bb Mon Sep 17 00:00:00 2001 From: Kyle Nicol <54515183+TRGoCPftF@users.noreply.github.com> Date: Tue, 10 Dec 2019 12:30:45 -0500 Subject: [PATCH 23/65] Update simann_example.swift Corrected definition where shuffle() was invoking self.shuffle() instead of self.tour.shuffle(), which would left the example in a infinite loop of shuffle() invocation --- Simulated annealing/simann_example.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Simulated annealing/simann_example.swift b/Simulated annealing/simann_example.swift index 0e07e0024..e7933c89a 100644 --- a/Simulated annealing/simann_example.swift +++ b/Simulated annealing/simann_example.swift @@ -138,7 +138,7 @@ extension Tour { } func shuffle() { - self.shuffle() + self.tour.shuffle() } } From 809cb974dc0b105407500f42e675c55f55e1588b Mon Sep 17 00:00:00 2001 From: "G. Moraleda" Date: Wed, 22 Jan 2020 17:51:05 +0100 Subject: [PATCH 24/65] Typos corrected --- Count Occurrences/README.markdown | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index 297bc4b0f..95f020e90 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -25,10 +25,10 @@ In code this looks as follows: func countOccurrences(of key: T, in array: [T]) -> Int { var leftBoundary: Int { var low = 0 - var high = a.count + var high = array.count while low < high { let midIndex = low + (high - low)/2 - if a[midIndex] < key { + if array[midIndex] < key { low = midIndex + 1 } else { high = midIndex @@ -39,10 +39,10 @@ func countOccurrences(of key: T, in array: [T]) -> Int { var rightBoundary: Int { var low = 0 - var high = a.count + var high = array.count while low < high { let midIndex = low + (high - low)/2 - if a[midIndex] > key { + if array[midIndex] > key { high = midIndex } else { low = midIndex + 1 @@ -62,7 +62,7 @@ To test this algorithm, copy the code to a playground and then do: ```swift let a = [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] -countOccurrencesOfKey(3, inArray: a) // returns 4 +countOccurrences(of: 3, in: a) // returns 4 ``` > **Remember:** If you use your own array, make sure it is sorted first! From 8a7db67f4f0e1706a3a91054f1b7aecc6ac95761 Mon Sep 17 00:00:00 2001 From: "G. Moraleda" Date: Wed, 22 Jan 2020 19:57:53 +0100 Subject: [PATCH 25/65] Update README.markdown --- Count Occurrences/README.markdown | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index 95f020e90..2e48d1020 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -22,13 +22,13 @@ The trick is to use two binary searches, one to find where the `3`s start (the l In code this looks as follows: ```swift -func countOccurrences(of key: T, in array: [T]) -> Int { +func countOccurrences(of key: T, in a: [T]) -> Int { var leftBoundary: Int { var low = 0 - var high = array.count + var high = a.count while low < high { let midIndex = low + (high - low)/2 - if array[midIndex] < key { + if a[midIndex] < key { low = midIndex + 1 } else { high = midIndex @@ -39,10 +39,10 @@ func countOccurrences(of key: T, in array: [T]) -> Int { var rightBoundary: Int { var low = 0 - var high = array.count + var high = a.count while low < high { let midIndex = low + (high - low)/2 - if array[midIndex] > key { + if a[midIndex] > key { high = midIndex } else { low = midIndex + 1 @@ -55,7 +55,9 @@ func countOccurrences(of key: T, in array: [T]) -> Int { } ``` -Notice that the variables `leftBoundary` and `rightBoundary` are very similar to the [binary search](../Binary%20Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. Also, notice that we constrain the type `T` to be Comparable so that the algorithm can be applied to an array of Strings, Ints or other types that conform to the Swift Comparable protocol. +Notice that the variables `leftBoundary` and `rightBoundary` are very similar to the [binary search](../Binary%20Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. Also, notice that we constrain the type `T` to be Comparable so that the algorithm can be applied to an + +y of Strings, Ints or other types that conform to the Swift Comparable protocol. To test this algorithm, copy the code to a playground and then do: From 467503c623c0fa781ea337b68a2ee5251d9a20bc Mon Sep 17 00:00:00 2001 From: "G. Moraleda" Date: Wed, 22 Jan 2020 19:58:38 +0100 Subject: [PATCH 26/65] Update README.markdown --- Count Occurrences/README.markdown | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index 2e48d1020..4deb9990e 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -55,9 +55,7 @@ func countOccurrences(of key: T, in a: [T]) -> Int { } ``` -Notice that the variables `leftBoundary` and `rightBoundary` are very similar to the [binary search](../Binary%20Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. Also, notice that we constrain the type `T` to be Comparable so that the algorithm can be applied to an - -y of Strings, Ints or other types that conform to the Swift Comparable protocol. +Notice that the variables `leftBoundary` and `rightBoundary` are very similar to the [binary search](../Binary%20Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. Also, notice that we constrain the type `T` to be Comparable so that the algorithm can be applied to an array of Strings, Ints or other types that conform to the Swift Comparable protocol. To test this algorithm, copy the code to a playground and then do: From 43181f5b4c8790fa887c4a6bd5ea8e94b0279eb5 Mon Sep 17 00:00:00 2001 From: Satveer Singh Date: Thu, 6 Feb 2020 19:30:24 +1100 Subject: [PATCH 27/65] Fix typo in Heap Sort README lg -> log --- Heap Sort/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Heap Sort/README.markdown b/Heap Sort/README.markdown index a45dad6f9..5bec58626 100644 --- a/Heap Sort/README.markdown +++ b/Heap Sort/README.markdown @@ -42,7 +42,7 @@ As you can see, the largest items are making their way to the back. We repeat th > **Note:** This process is very similar to [selection sort](../Selection%20Sort/), which repeatedly looks for the minimum item in the remainder of the array. Extracting the minimum or maximum value is what heaps are good at. -Performance of heap sort is **O(n lg n)** in best, worst, and average case. Because we modify the array directly, heap sort can be performed in-place. But it is not a stable sort: the relative order of identical elements is not preserved. +Performance of heap sort is **O(n log n)** in best, worst, and average case. Because we modify the array directly, heap sort can be performed in-place. But it is not a stable sort: the relative order of identical elements is not preserved. Here's how you can implement heap sort in Swift: From f664af1f502ec7f6692e8dcb34d5848ce3af4e60 Mon Sep 17 00:00:00 2001 From: "G. Moraleda" Date: Mon, 10 Feb 2020 20:01:47 +0100 Subject: [PATCH 28/65] Renamed array --- Count Occurrences/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index 4deb9990e..8e935ea58 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -22,10 +22,10 @@ The trick is to use two binary searches, one to find where the `3`s start (the l In code this looks as follows: ```swift -func countOccurrences(of key: T, in a: [T]) -> Int { +func countOccurrences(of key: T, in array: [T]) -> Int { var leftBoundary: Int { var low = 0 - var high = a.count + var high = array.count while low < high { let midIndex = low + (high - low)/2 if a[midIndex] < key { @@ -39,7 +39,7 @@ func countOccurrences(of key: T, in a: [T]) -> Int { var rightBoundary: Int { var low = 0 - var high = a.count + var high = array.count while low < high { let midIndex = low + (high - low)/2 if a[midIndex] > key { From 901aaeac47c2275d0e5facbf9c5525882eb4f7ea Mon Sep 17 00:00:00 2001 From: Paul Anguiano Date: Thu, 5 Mar 2020 18:10:39 -0800 Subject: [PATCH 29/65] Modified Trie to add prefix support to boolean contains(), plus unit tests. --- Trie/Trie/Trie/Trie.swift | 9 ++++++--- Trie/Trie/TrieTests/TrieTests.swift | 27 ++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index accc7b61c..3d5031cf3 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -117,9 +117,12 @@ extension Trie { /// Determines whether a word is in the trie. /// - /// - Parameter word: the word to check for + /// - Parameters: + /// - word: the word to check for + /// - matchPrefix: whether the search word should match + /// if it is only a prefix of other nodes in the trie /// - Returns: true if the word is present, false otherwise. - func contains(word: String) -> Bool { + func contains(word: String, matchPrefix: Bool = false) -> Bool { guard !word.isEmpty else { return false } @@ -130,7 +133,7 @@ extension Trie { } currentNode = childNode } - return currentNode.isTerminating + return matchPrefix || currentNode.isTerminating } /// Attempts to walk to the last node of a word. The diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 0c5bc69c6..59da2cd9b 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -167,7 +167,8 @@ class TrieTests: XCTestCase { let trieCopy = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? Trie XCTAssertEqual(trieCopy?.count, trie.count) } - + + /// Tests whether word prefixes are properly found and returned. func testFindWordsWithPrefix() { let trie = Trie() trie.insert(word: "test") @@ -190,4 +191,28 @@ class TrieTests: XCTestCase { let wordsUpperCase = trie.findWordsWithPrefix(prefix: "Te") XCTAssertEqual(wordsUpperCase.sorted(), ["team", "test"]) } + + /// Tests whether word prefixes are properly detected on a boolean contains() check. + func testContainsWordMatchPrefix() { + let trie = Trie() + trie.insert(word: "test") + trie.insert(word: "another") + trie.insert(word: "exam") + let wordsAll = trie.contains(word: "", matchPrefix: true) + XCTAssertEqual(wordsAll, true) + let words = trie.contains(word: "ex", matchPrefix: true) + XCTAssertEqual(words, true) + trie.insert(word: "examination") + let words2 = trie.contains(word: "exam", matchPrefix: true) + XCTAssertEqual(words2, true) + let noWords = trie.contains(word: "tee", matchPrefix: true) + XCTAssertEqual(noWords, false) + let unicodeWord = "😬😎" + trie.insert(word: unicodeWord) + let wordsUnicode = trie.contains(word: "😬", matchPrefix: true) + XCTAssertEqual(wordsUnicode, true) + trie.insert(word: "Team") + let wordsUpperCase = trie.contains(word: "Te", matchPrefix: true) + XCTAssertEqual(wordsUpperCase, true) + } } From 510f3da1a0e445c3c1ec4aec69f1731a86acfbc4 Mon Sep 17 00:00:00 2001 From: Mick Bennett Date: Fri, 27 Mar 2020 00:00:03 -0700 Subject: [PATCH 30/65] updated depricated hashable values to hash into methods --- Graph/Graph/Edge.swift | 10 ++++------ Graph/Graph/Vertex.swift | 5 +++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Graph/Graph/Edge.swift b/Graph/Graph/Edge.swift index ac5ed6a25..b69937895 100644 --- a/Graph/Graph/Edge.swift +++ b/Graph/Graph/Edge.swift @@ -29,12 +29,10 @@ extension Edge: CustomStringConvertible { extension Edge: Hashable { - public var hashValue: Int { - var string = "\(from.description)\(to.description)" - if weight != nil { - string.append("\(weight!)") - } - return string.hashValue + public func hash(into hasher: inout Hasher) { + hasher.combine(from.description) + hasher.combine(to.description) + hasher.combine(weight) } } diff --git a/Graph/Graph/Vertex.swift b/Graph/Graph/Vertex.swift index 758a367bb..47499dcc6 100644 --- a/Graph/Graph/Vertex.swift +++ b/Graph/Graph/Vertex.swift @@ -24,8 +24,9 @@ extension Vertex: CustomStringConvertible { extension Vertex: Hashable { - public var hashValue: Int { - return "\(data)\(index)".hashValue + public func hash(into hasher: inout Hasher) { + hasher.combine(data) + hasher.combine(index) } } From 47356447f47fc353cb95dcdcc9a4d296b1a1b816 Mon Sep 17 00:00:00 2001 From: Mick Bennett Date: Thu, 9 Apr 2020 16:47:58 -0700 Subject: [PATCH 31/65] updated lcs string extension to access string directly --- .../Contents.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift b/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift index c8d413e7f..0e78b7043 100644 --- a/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift +++ b/Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift @@ -1,4 +1,4 @@ -// last checked with Xcode 9.0b4 +// last checked with Xcode 11.4 #if swift(>=4.0) print("Hello, Swift 4!") #endif @@ -7,10 +7,10 @@ extension String { public func longestCommonSubsequence(_ other: String) -> String { func lcsLength(_ other: String) -> [[Int]] { - var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1) + var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.count+1), count: self.count+1) - for (i, selfChar) in self.characters.enumerated() { - for (j, otherChar) in other.characters.enumerated() { + for (i, selfChar) in self.enumerated() { + for (j, otherChar) in other.enumerated() { if otherChar == selfChar { matrix[i+1][j+1] = matrix[i][j] + 1 } else { @@ -22,8 +22,8 @@ extension String { } func backtrack(_ matrix: [[Int]]) -> String { - var i = self.characters.count - var j = other.characters.count + var i = self.count + var j = other.count var charInSequence = self.endIndex var lcs = String() @@ -41,7 +41,7 @@ extension String { lcs.append(self[charInSequence]) } } - return String(lcs.characters.reversed()) + return String(lcs.reversed()) } return backtrack(lcsLength(other)) From 5b0861c2eca8ec37ed3f2667ada5de7e850cd75e Mon Sep 17 00:00:00 2001 From: Azhar Anwar Date: Tue, 28 Apr 2020 15:52:03 +0530 Subject: [PATCH 32/65] fixes: typo and punctuation --- Shuffle/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Shuffle/README.markdown b/Shuffle/README.markdown index 5a2a07a98..d9c35868a 100644 --- a/Shuffle/README.markdown +++ b/Shuffle/README.markdown @@ -37,7 +37,7 @@ This code works just fine but it's not very efficient. Removing an element from ## The Fisher-Yates / Knuth shuffle -Here is a much improved version of the shuffle algorithm: +Here is a much-improved version of the shuffle algorithm: ```swift extension Array { @@ -52,7 +52,7 @@ extension Array { } ``` -Again, this picks objects at random. In the naive version we placed those objects into a new temporary array so we could keep track of which objects were already shuffled and which still remained to be done. In this improved algorithm, however, we'll move the shuffled objects to the end of the original array. +Again, this picks objects at random. In the naive version, we placed those objects into a new temporary array so we could keep track of which objects were already shuffled and which still remained to be done. In this improved algorithm, however, we'll move the shuffled objects to the end of the original array. Let's walk through the example. We have the array: @@ -116,7 +116,7 @@ The `shuffledArray()` function first creates a new array with `n` zeros. Then it For this function, `The condition that checks if j ≠ i may be omitted in languages that have no problems accessing uninitialized array values, and for which assigning is cheaper than comparing.`, you can check it in wiki. And also remove checking logic will optimise performance. -The algoritm is quite clever and I suggest you walk through an example yourself, either on paper or in the playground. (Hint: Again it splits the array into two regions.) +The algorithm is quite clever and I suggest you walk through an example yourself, either on paper or in the playground. (Hint: Again it splits the array into two regions.) ## See also From 409ffd6921441afb56a7ea68c73a0f2c9516c809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sarp=20G=C3=BCney=20Ba=C5=9Faraner?= Date: Thu, 7 May 2020 10:35:45 +0300 Subject: [PATCH 33/65] fix typo Dinstance -> Distance --- HaversineDistance/HaversineDistance.playground/Contents.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HaversineDistance/HaversineDistance.playground/Contents.swift b/HaversineDistance/HaversineDistance.playground/Contents.swift index 3d8d60f54..ed89b4462 100644 --- a/HaversineDistance/HaversineDistance.playground/Contents.swift +++ b/HaversineDistance/HaversineDistance.playground/Contents.swift @@ -1,6 +1,6 @@ import UIKit -func haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double { +func haversineDistance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double { let haversin = { (angle: Double) -> Double in return (1 - cos(angle))/2 @@ -27,4 +27,4 @@ let amsterdam = (52.3702, 4.8952) let newYork = (40.7128, -74.0059) // Google says it's 5857 km so our result is only off by 2km which could be due to all kinds of things, not sure how google calculates the distance or which latitude and longitude google uses to calculate the distance. -haversineDinstance(la1: amsterdam.0, lo1: amsterdam.1, la2: newYork.0, lo2: newYork.1) +haversineDistance(la1: amsterdam.0, lo1: amsterdam.1, la2: newYork.0, lo2: newYork.1) From 7a77f3fa8abbdc0ee68b77b84d56b3e1eaf61087 Mon Sep 17 00:00:00 2001 From: L Rettberg Date: Sat, 9 May 2020 11:57:00 -0500 Subject: [PATCH 34/65] Update Readme for code modification Update to reflect alternative of using .isMultiple(of:) method instead of modulo (%) operator --- Fizz Buzz/README.markdown | 97 ++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 28 deletions(-) diff --git a/Fizz Buzz/README.markdown b/Fizz Buzz/README.markdown index 8c250da27..be516bd46 100644 --- a/Fizz Buzz/README.markdown +++ b/Fizz Buzz/README.markdown @@ -16,46 +16,48 @@ The modulus operator `%` is the key to solving fizz buzz. The modulus operator returns the remainder after an integer division. Here is an example of the modulus operator: -| Division | Division Result | Modulus | Modulus Result | -| ------------- | -------------------------- | --------------- | ---------------:| -| 1 / 3 | 0 with a remainder of 3 | 1 % 3 | 1 | -| 5 / 3 | 1 with a remainder of 2 | 5 % 3 | 2 | -| 16 / 3 | 5 with a remainder of 1 | 16 % 3 | 1 | +| Division | Division Result | Modulus | Modulus Result| +| ----------- | --------------------- | ------------- | :-----------: | +| 1 / 3 | 0 with a remainder of 3 | 1 % 3 | 1 | +| 5 / 3 | 1 with a remainder of 2 | 5 % 3 | 2 | +| 16 / 3 | 5 with a remainder of 1 | 16 % 3 | 1 | A common approach to determine if a number is even or odd is to use the modulus operator: -| Modulus | Result | Swift Code | Swift Code Result | Comment | -| ------------- | ---------------:| ------------------------------- | -----------------:| --------------------------------------------- | -| 6 % 2 | 0 | `let isEven = (number % 2 == 0)` | `true` | If a number is divisible by 2 it is *even* | -| 5 % 2 | 1 | `let isOdd = (number % 2 != 0)` | `true` | If a number is not divisible by 2 it is *odd* | +| Modulus | Result | Swift Code | Swift Code
    Result | Comment | +| -------- | :-----:| -------------------------------- | :----------------:| --------------------------------------------- | +| 6 % 2 | 0 | `let isEven = (number % 2 == 0)` | `true` | If a number is divisible by 2 it is *even* | +| 5 % 2 | 1 | `let isOdd = (number % 2 != 0)` | `true` | If a number is not divisible by 2 it is *odd* | + +Alternatively, Swift's built in function .isMultiple(of:) can be used, i.e. 6.isMultiple(of: 2) will return true, 5.isMultiple(of: 2) will return false ## Solving fizz buzz -Now we can use the modulus operator `%` to solve fizz buzz. +Now we can use the modulus operator `%` or .isMultiple(of:) method to solve fizz buzz. Finding numbers divisible by three: -| Modulus | Modulus Result | Swift Code | Swift Code Result | -| ------- | --------------:| ------------- |------------------:| -| 1 % 3 | 1 | `1 % 3 == 0` | `false` | -| 2 % 3 | 2 | `2 % 3 == 0` | `false` | -| 3 % 3 | 0 | `3 % 3 == 0` | `true` | -| 4 % 3 | 1 | `4 % 3 == 0` | `false` | +| Modulus | Modulus
    Result | Swift Code
    using Modulo | Swift Code
    using .isMultiple(of:) | Swift Code
    Result | +| ------- | :---------------: | -------------------------- | ------------------------------------ | ------------------- | +|1 % 3 | 1 | `1 % 3 == 0` | `1.isMultiple(of: 3)` | `false` | +|2 % 3 | 2 | `2 % 3 == 0` | `2.isMultiple(of: 3)` | `false` | +|3 % 3 | 0 | `3 % 3 == 0` | `3.isMultiple(of: 3)` | `true` | +|4 % 3 | 1 | `4 % 3 == 0` | `4.isMultiple(of: 3)` | `false` | Finding numbers divisible by five: -| Modulus | Modulus Result | Swift Code | Swift Code Result | -| ------- | --------------:| ------------- |------------------:| -| 1 % 5 | 1 | `1 % 5 == 0` | `false` | -| 2 % 5 | 2 | `2 % 5 == 0` | `false` | -| 3 % 5 | 3 | `3 % 5 == 0` | `false` | -| 4 % 5 | 4 | `4 % 5 == 0` | `false` | -| 5 % 5 | 0 | `5 % 5 == 0` | `true` | -| 6 % 5 | 1 | `6 % 5 == 0` | `false` | +| Modulus | Modulus
    Result | Swift Code
    using Modulo | Swift Code
    using .isMultiple(of:) | Swift Code
    Result | +| ------- | :---------------: | -------------------------- | ------------------------------------ | -------------------- | +| 1 % 5 | 1 | `1 % 5 == 0` | `1.isMultiple(of: 5)` | `false` | +| 2 % 5 | 2 | `2 % 5 == 0` | `2.isMultiple(of: 5)` | `false` | +| 3 % 5 | 3 | `3 % 5 == 0` | `3.isMultiple(of: 5)` | `false` | +| 4 % 5 | 4 | `4 % 5 == 0` | `4.isMultiple(of: 5)` | `false` | +| 5 % 5 | 0 | `5 % 5 == 0` | `5.isMultiple(of: 5)` | `true` | +| 6 % 5 | 1 | `6 % 5 == 0` | `6.isMultiple(of: 5)` | `false` | ## The code -Here is a simple implementation in Swift: +Here is a simple implementation in Swift using Modulus approach ```swift func fizzBuzz(_ numberOfTurns: Int) { @@ -79,7 +81,31 @@ func fizzBuzz(_ numberOfTurns: Int) { } ``` -Put this code in a playground and test it like so: +Here is simple implementation in Swift using .isMultiple(of:) and switch statement + +```swift +func fizzBuzz(_ numberOfTurns: Int) { + guard numberOfTurns >= 1 else { + print("Number of turns must be >= 1") + return + } + + for i in 1...numberOfTurns { + switch (i.isMultiple(of: 3), i.isMultiple(of: 5)) { + case (false, false): + print("\(i)") + case (true, false): + print("Fizz") + case (false, true): + print("Buzz") + case (true, true): + print("Fizz Buzz") + } + } +} +``` + +Put either code in a playground and test it like so: ```swift fizzBuzz(15) @@ -87,10 +113,25 @@ fizzBuzz(15) This will output: - 1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, Fizz Buzz +1 +2 +Fizz +4 +Buzz +Fizz +7 +8 +Fizz +Buzz +11 +Fizz +13 +14 +Fizz Buzz ## See also [Fizz buzz on Wikipedia](https://en.wikipedia.org/wiki/Fizz_buzz) -*Written by [Chris Pilcher](https://github.com/chris-pilcher)* +*Originally written by [Chris Pilcher](https://github.com/chris-pilcher)*
    +*Updated by [Lance Rettberg](https://github.com/l-rettberg)* From 99d769d03c0cfee1b92b63aeeb1b203811eaddc8 Mon Sep 17 00:00:00 2001 From: L Rettberg Date: Sat, 9 May 2020 12:02:06 -0500 Subject: [PATCH 35/65] Update FizzBuzz Update to 1) add guard, 2) use .isMultiple(of:), 3) use switch statement --- Fizz Buzz/FizzBuzz.swift | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Fizz Buzz/FizzBuzz.swift b/Fizz Buzz/FizzBuzz.swift index b6bb410e7..704ea7c6b 100644 --- a/Fizz Buzz/FizzBuzz.swift +++ b/Fizz Buzz/FizzBuzz.swift @@ -1,19 +1,21 @@ -func fizzBuzz(_ numberOfTurns: Int) { - for i in 1...numberOfTurns { - var result = "" +// Updated for Xcode Version 11.4.1 (11E503a) - if i % 3 == 0 { - result += "Fizz" +func fizzBuzz2(_ numberOfTurns: Int) { + guard numberOfTurns >= 1 else { + print("Number of turns must be >= 1") + return } - - if i % 5 == 0 { - result += (result.isEmpty ? "" : " ") + "Buzz" - } - - if result.isEmpty { - result += "\(i)" + + for i in 1...numberOfTurns { + switch (i.isMultiple(of: 3), i.isMultiple(of: 5)) { + case (false, false): + print("\(i)") + case (true, false): + print("Fizz") + case (false, true): + print("Buzz") + case (true, true): + print("Fizz Buzz") + } } - - print(result) - } } From 71431b12042a2dc17eb9c170a9fa5c731942462d Mon Sep 17 00:00:00 2001 From: L Rettberg Date: Sat, 9 May 2020 12:09:54 -0500 Subject: [PATCH 36/65] Update --- Fizz Buzz/FizzBuzz.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fizz Buzz/FizzBuzz.swift b/Fizz Buzz/FizzBuzz.swift index 704ea7c6b..2e66b26f4 100644 --- a/Fizz Buzz/FizzBuzz.swift +++ b/Fizz Buzz/FizzBuzz.swift @@ -1,6 +1,6 @@ // Updated for Xcode Version 11.4.1 (11E503a) -func fizzBuzz2(_ numberOfTurns: Int) { +func fizzBuzz(_ numberOfTurns: Int) { guard numberOfTurns >= 1 else { print("Number of turns must be >= 1") return From f94bccc68d017bbc61cb774f7642dd25b25f1d4a Mon Sep 17 00:00:00 2001 From: L Rettberg Date: Sat, 9 May 2020 14:41:39 -0500 Subject: [PATCH 37/65] Updates to 1) add guard, 2) use .isMultiple(of:) and 3) use switch statement --- Fizz Buzz/FizzBuzz.playground/Contents.swift | 34 ++++++++++---------- Fizz Buzz/FizzBuzz.swift | 4 +-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Fizz Buzz/FizzBuzz.playground/Contents.swift b/Fizz Buzz/FizzBuzz.playground/Contents.swift index ae966bbcc..2ab13b362 100644 --- a/Fizz Buzz/FizzBuzz.playground/Contents.swift +++ b/Fizz Buzz/FizzBuzz.playground/Contents.swift @@ -1,23 +1,23 @@ -// last checked with Xcode 10.0 (10A255) +// Last checked with Xcode Version 11.4.1 (11E503a) func fizzBuzz(_ numberOfTurns: Int) { - for i in 1...numberOfTurns { - var result = "" - - if i % 3 == 0 { - result += "Fizz" + guard numberOfTurns >= 1 else { + print("Number of turns must be >= 1") + return } - - if i % 5 == 0 { - result += (result.isEmpty ? "" : " ") + "Buzz" + + for i in 1...numberOfTurns { + switch (i.isMultiple(of: 3), i.isMultiple(of: 5)) { + case (false, false): + print("\(i)") + case (true, false): + print("Fizz") + case (false, true): + print("Buzz") + case (true, true): + print("Fizz Buzz") + } } - - if result.isEmpty { - result += "\(i)" - } - - print(result) - } } -fizzBuzz(100) +fizzBuzz(15) diff --git a/Fizz Buzz/FizzBuzz.swift b/Fizz Buzz/FizzBuzz.swift index 2e66b26f4..bf753e648 100644 --- a/Fizz Buzz/FizzBuzz.swift +++ b/Fizz Buzz/FizzBuzz.swift @@ -1,4 +1,4 @@ -// Updated for Xcode Version 11.4.1 (11E503a) +// Last checked with Xcode Version 11.4.1 (11E503a) func fizzBuzz(_ numberOfTurns: Int) { guard numberOfTurns >= 1 else { @@ -18,4 +18,4 @@ func fizzBuzz(_ numberOfTurns: Int) { print("Fizz Buzz") } } -} +} \ No newline at end of file From 6a9ec9628099601714655ad42237d8948b2cfc05 Mon Sep 17 00:00:00 2001 From: L Rettberg Date: Sat, 9 May 2020 16:45:31 -0500 Subject: [PATCH 38/65] Remove file --- Fizz Buzz/FizzBuzz.playground/contents.xcplayground | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 Fizz Buzz/FizzBuzz.playground/contents.xcplayground diff --git a/Fizz Buzz/FizzBuzz.playground/contents.xcplayground b/Fizz Buzz/FizzBuzz.playground/contents.xcplayground deleted file mode 100644 index 5da2641c9..000000000 --- a/Fizz Buzz/FizzBuzz.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From e3b3126f819ec57b9759cd4b80f639b1d39b440a Mon Sep 17 00:00:00 2001 From: L Rettberg Date: Sat, 9 May 2020 16:47:18 -0500 Subject: [PATCH 39/65] Delete IDEWorkspaceChecks.plist --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003..000000000 --- a/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - From 51b0c2b5a2abed1a90241e64869ccd173b54a1e7 Mon Sep 17 00:00:00 2001 From: L Rettberg Date: Sat, 9 May 2020 16:47:30 -0500 Subject: [PATCH 40/65] Delete contents.xcworkspacedata --- .../playground.xcworkspace/contents.xcworkspacedata | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/contents.xcworkspacedata b/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/Fizz Buzz/FizzBuzz.playground/playground.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - From 4617d9401be60101c12e100f428c0b460de0a210 Mon Sep 17 00:00:00 2001 From: jinthislife <8064873+jinthislife@users.noreply.github.com> Date: Mon, 11 May 2020 15:30:38 +1000 Subject: [PATCH 41/65] Update README.markdown remove duplicate parameter --- Binary Search Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index 0b382f204..57d1f4bff 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -557,7 +557,7 @@ As a result, doing `tree.search(100)` gives nil. You can check whether a tree is a valid binary search tree with the following method: ```swift - public func isBST(minValue minValue: T, maxValue: T) -> Bool { + public func isBST(minValue: T, maxValue: T) -> Bool { if value < minValue || value > maxValue { return false } let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true From bf3f3d5d690fe0a6e3cd7fc549781551477a8c6b Mon Sep 17 00:00:00 2001 From: Jagdeep Matharu Date: Sun, 31 May 2020 19:54:14 -0400 Subject: [PATCH 42/65] Updating Counting sort for stability --- Counting Sort/CountingSort.playground/Contents.swift | 7 ++++++- Counting Sort/CountingSort.swift | 5 ++++- Counting Sort/README.markdown | 7 +++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Counting Sort/CountingSort.playground/Contents.swift b/Counting Sort/CountingSort.playground/Contents.swift index dc375512a..839b16bc8 100644 --- a/Counting Sort/CountingSort.playground/Contents.swift +++ b/Counting Sort/CountingSort.playground/Contents.swift @@ -29,12 +29,17 @@ func countingSort(array: [Int]) throws -> [Int] { // Step 3 // Place the element in the final array as per the number of elements before it + // Loop through the array in reverse to keep the stability of the new array + // (i.e. 7, is at index 3 and 6, thus in sortedArray the position of 7 at index 3 should be before 7 at index 6 var sortedArray = [Int](repeating: 0, count: array.count) - for element in array { + for index in stride(from: array.count - 1, through: 0, by: -1) { + let element = array[index] countArray[element] -= 1 sortedArray[countArray[element]] = element } + return sortedArray } try countingSort(array: [10, 9, 8, 7, 1, 2, 7, 3]) + diff --git a/Counting Sort/CountingSort.swift b/Counting Sort/CountingSort.swift index 725a634a4..68dcf5c0d 100644 --- a/Counting Sort/CountingSort.swift +++ b/Counting Sort/CountingSort.swift @@ -29,8 +29,11 @@ func countingSort(_ array: [Int])-> [Int] { // Step 3 // Place the element in the final array as per the number of elements before it + // Loop through the array in reverse to keep the stability of the new sorted array + // (For Example: 7 is at index 3 and 6, thus in sortedArray the position of 7 at index 3 should be before 7 at index 6 var sortedArray = [Int](repeating: 0, count: array.count) - for element in array { + for index in stride(from: array.count - 1, through: 0, by: -1) { + let element = array[index] countArray[element] -= 1 sortedArray[countArray[element]] = element } diff --git a/Counting Sort/README.markdown b/Counting Sort/README.markdown index 959becc8c..93d6635bd 100644 --- a/Counting Sort/README.markdown +++ b/Counting Sort/README.markdown @@ -50,7 +50,9 @@ The code for step 2 is: ### Step 3: -This is the last step in the algorithm. Each element in the original array is placed at the position defined by the output of step 2. For example, the number 10 would be placed at an index of 7 in the output array. Also, as you place the elements you need to reduce the count by 1 as those many elements are reduced from the array. +This is the last step in the algorithm. Each element in the original array is placed at the position defined by the output of step 2. For example, the number 10 would be placed at an index of 7 in the output array. Also, as you place the elements you need to reduce the count by 1 as those many elements are reduced from the array. +We also have to loop through the array in reverse to keep the stability of the new sorted array. +For Example: 7 is at index 3 and 6, thus in sortedArray the position of 7 at index 3 should be before 7 at index 6. The final output would be: @@ -63,7 +65,8 @@ Here is the code for this final step: ```swift var sortedArray = [Int](repeating: 0, count: array.count) - for element in array { + for index in stride(from: array.count - 1, through: 0, by: -1) { + let element = array[index] countArray[element] -= 1 sortedArray[countArray[element]] = element } From d06b7e3c5e45a65b2f275a7dd81bfc77520788c6 Mon Sep 17 00:00:00 2001 From: Jagdeep Matharu Date: Sun, 31 May 2020 19:54:43 -0400 Subject: [PATCH 43/65] Updating Counting sort tests project to support Swift 5 --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ Counting Sort/Tests/Tests.xcodeproj/project.pbxproj | 5 +++-- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 Counting Sort/CountingSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/Counting Sort/CountingSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Counting Sort/CountingSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Counting Sort/CountingSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj b/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj index 5cbb0d4aa..aaa6c1b6b 100644 --- a/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -97,6 +97,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -226,7 +227,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -238,7 +239,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + From bf38b12ddc30c6e396a50e61e3dc342ced28e538 Mon Sep 17 00:00:00 2001 From: Jagdeep Matharu Date: Sun, 31 May 2020 19:58:21 -0400 Subject: [PATCH 44/65] Minor change in comment --- Counting Sort/CountingSort.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Counting Sort/CountingSort.playground/Contents.swift b/Counting Sort/CountingSort.playground/Contents.swift index 839b16bc8..99178f85d 100644 --- a/Counting Sort/CountingSort.playground/Contents.swift +++ b/Counting Sort/CountingSort.playground/Contents.swift @@ -30,7 +30,7 @@ func countingSort(array: [Int]) throws -> [Int] { // Step 3 // Place the element in the final array as per the number of elements before it // Loop through the array in reverse to keep the stability of the new array - // (i.e. 7, is at index 3 and 6, thus in sortedArray the position of 7 at index 3 should be before 7 at index 6 + // i.e. 7, is at index 3 and 6, thus in sortedArray the position of 7 at index 3 should be before 7 at index 6 var sortedArray = [Int](repeating: 0, count: array.count) for index in stride(from: array.count - 1, through: 0, by: -1) { let element = array[index] From d8d165208465c8c725eda950e8cb2ddb3d7cfdca Mon Sep 17 00:00:00 2001 From: Yossa Bourne Date: Thu, 11 Jun 2020 09:56:40 +0700 Subject: [PATCH 45/65] Fix Swift (language) typos --- Introsort/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Introsort/README.markdown b/Introsort/README.markdown index 376703cf7..3e596ee89 100644 --- a/Introsort/README.markdown +++ b/Introsort/README.markdown @@ -2,7 +2,7 @@ Goal: Sort an array from low to high (or high to low). -IntroSort is the algorithm used by swift to sort a collection. Introsort is an hybrid algorithm invented by David Musser in 1993 with the purpose of giving a generic sorting algorithm for the C++ standard library. The classic implementation of introsort expect a recursive Quicksort with fallback to Heapsort in case the recursion depth level reached a certain max. The maximum depends on the number of elements in the collection and it is usually 2 * log(n). The reason behind this “fallback” is that if Quicksort was not able to get the solution after 2 * log(n) recursions for a branch, probably it hit its worst case and it is degrading to complexity O( n^2 ). To optimise even further this algorithm, the swift implementation introduce an extra step in each recursion where the partition is sorted using InsertionSort if the count of the partition is less than 20. +IntroSort is the algorithm used by Swift to sort a collection. Introsort is an hybrid algorithm invented by David Musser in 1993 with the purpose of giving a generic sorting algorithm for the C++ standard library. The classic implementation of introsort expect a recursive Quicksort with fallback to Heapsort in case the recursion depth level reached a certain max. The maximum depends on the number of elements in the collection and it is usually 2 * log(n). The reason behind this “fallback” is that if Quicksort was not able to get the solution after 2 * log(n) recursions for a branch, probably it hit its worst case and it is degrading to complexity O( n^2 ). To optimise even further this algorithm, the Swift implementation introduce an extra step in each recursion where the partition is sorted using InsertionSort if the count of the partition is less than 20. The number 20 is an empiric number obtained observing the behaviour of InsertionSort with lists of this size. From 9bc6aad9aaa56ce53ea7319f52c25585651e737a Mon Sep 17 00:00:00 2001 From: Roberto Efrain Hernandez Date: Wed, 10 Jun 2020 23:44:40 -0700 Subject: [PATCH 46/65] Updating how String can be casted into an Array. Just wanted to update the syntax from Array(self.characters) to Array(self). Similarly for casting of the ptnr String. --- Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift index 81bc65278..be0cd961d 100644 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -12,8 +12,8 @@ extension String { func indexesOf(ptnr: String) -> [Int]? { - let text = Array(self.characters) - let pattern = Array(ptnr.characters) + let text = Array(self) + let pattern = Array(ptnr) let textLength: Int = text.count let patternLength: Int = pattern.count From abfa66b02d35b6320a5e404241db94d4317386d6 Mon Sep 17 00:00:00 2001 From: msalvacion Date: Thu, 11 Jun 2020 15:32:05 -0700 Subject: [PATCH 47/65] Fix: Typos in Heap README.markdown Added missing word and fixed a typo --- Heap/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index 6c65fe9c8..fee881129 100755 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -82,7 +82,7 @@ array[parent(i)] >= array[i] Verify that this heap property holds for the array from the example heap. -As you can see, these equations allow us to find the parent or child index for any node without the need for pointers. It is complicated than just dereferencing a pointer, but that is the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. +As you can see, these equations allow us to find the parent or child index for any node without the need for pointers. It is more complicated than just dereferencing a pointer, but that is the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. It is important to understand this relationship between array index and position in the tree. Here is a larger heap which has 15 nodes divided over four levels: @@ -164,7 +164,7 @@ All of the above take time **O(log n)** because shifting up or down is expensive - `buildHeap(array)`: Converts an (unsorted) array into a heap by repeatedly calling `insert()`. If you are smart about this, it can be done in **O(n)** time. -- [Heap sort](../Heap%20Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** +- [Heap sort](../Heap%20Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n log n).** The heap also has a `peek()` function that returns the maximum (max-heap) or minimum (min-heap) element, without removing it from the heap. Time: **O(1)**. From f30e53c3cb45af31f8b80c35a8c4ee781d1ee311 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 15 Jun 2020 18:23:10 -0400 Subject: [PATCH 48/65] Fixes a few typos --- Introsort/README.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Introsort/README.markdown b/Introsort/README.markdown index 3e596ee89..280950928 100644 --- a/Introsort/README.markdown +++ b/Introsort/README.markdown @@ -2,7 +2,9 @@ Goal: Sort an array from low to high (or high to low). -IntroSort is the algorithm used by Swift to sort a collection. Introsort is an hybrid algorithm invented by David Musser in 1993 with the purpose of giving a generic sorting algorithm for the C++ standard library. The classic implementation of introsort expect a recursive Quicksort with fallback to Heapsort in case the recursion depth level reached a certain max. The maximum depends on the number of elements in the collection and it is usually 2 * log(n). The reason behind this “fallback” is that if Quicksort was not able to get the solution after 2 * log(n) recursions for a branch, probably it hit its worst case and it is degrading to complexity O( n^2 ). To optimise even further this algorithm, the Swift implementation introduce an extra step in each recursion where the partition is sorted using InsertionSort if the count of the partition is less than 20. +IntroSort is the algorithm used by Swift to sort a collection. Introsort is an hybrid algorithm invented by David Musser in 1993 with the purpose of giving a generic sorting algorithm for the C++ standard library. + +The classic implementation of introsort uses a recursive Quicksort with a fallback to Heapsort in the case where the recursion depth level reached a certain maximum value. The maximum depends on the number of elements in the collection and it is usually 2 * log(n). The reason behind this “fallback” is that if Quicksort was not able to get the solution after 2 * log(n) recursions for a branch, probably it hit its worst case and it is degrading to complexity O( n^2 ). To optimise even further this algorithm, the Swift implementation introduce an extra step in each recursion where the partition is sorted using InsertionSort if the count of the partition is less than 20. The number 20 is an empiric number obtained observing the behaviour of InsertionSort with lists of this size. From f4fb2fc0eb04ab6a7862ae903f258741896f9ec1 Mon Sep 17 00:00:00 2001 From: nghiahoang Date: Thu, 25 Jun 2020 13:17:01 +0700 Subject: [PATCH 49/65] fix: SplayTree.remove is broken --- .../SplayTree.playground/Contents.swift | 33 +---- .../Sources/SplayTree.swift | 122 ++++------------- Splay Tree/SplayTree.swift | 124 ++++-------------- Splay Tree/readme.md | 7 +- 4 files changed, 57 insertions(+), 229 deletions(-) diff --git a/Splay Tree/SplayTree.playground/Contents.swift b/Splay Tree/SplayTree.playground/Contents.swift index a8a0bc5c6..28a201b37 100644 --- a/Splay Tree/SplayTree.playground/Contents.swift +++ b/Splay Tree/SplayTree.playground/Contents.swift @@ -5,29 +5,10 @@ print("Hello, Swift 4!") #endif -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() - - - - +var tree = SplayTree(value: 0) +tree.insert(value: 2) +tree.insert(value: 3) +tree.insert(value: 4) +tree.insert(value: 7) +_ = tree.search(value: 2) +tree.remove(value: 2) diff --git a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift index 9e484129c..f450eaced 100644 --- a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift +++ b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift @@ -289,120 +289,42 @@ extension Node { - Node Resulting from the deletion and the splaying of the removed node */ - public func remove(value: T) -> Node? { - let replacement: Node? + fileprivate func remove(value: T) -> Node? { + guard let target = search(value: value) else { return self } - if let v = self.value, v == value { + if let left = target.left, let right = target.right { + let largestOfLeftChild = left.maximum() + left.parent = nil + right.parent = nil - 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 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 - 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 - 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 - parentToSplay = parent - } - - reconnectParentTo(node: replacement) + SplayOperation.splay(node: largestOfLeftChild) + largestOfLeftChild.right = right - // performs the splay operation - if let parentToSplay = parentToSplay { - SplayOperation.splay(node: parentToSplay) - } + return largestOfLeftChild - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil + } else if let left = target.left { + replace(node: target, with: left) + return left - return parentToSplay + } else if let right = target.right { + replace(node: target, with: right) + return right - } 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 { - if right != nil { - return right?.remove(value: value) - } else { - let node = self - SplayOperation.splay(node: node) - return node - - } + return nil } } - 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() + private func replace(node: Node, with newNode: Node?) { + guard let sourceParent = sourceNode.parent else { return } - // 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 + if sourceNode.isLeftChild { + sourceParent.left = newNode } else { - successor.right = nil + sourceParent.right = newNode } - // And finally, connect the successor node to our parent. - return successor - } - - private func reconnectParentTo(node: Node?) { - if let parent = parent { - if isLeftChild { - parent.left = node - } else { - parent.right = node - } - } - node?.parent = parent + newNode?.parent = sourceParent } } diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index a7b20743d..0f1fa48f0 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -44,7 +44,7 @@ public enum SplayOperation { - Returns - Operation Case zigZag - zigZig - zig */ - public static func operation(forNode node: Node) -> 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) { @@ -289,120 +289,42 @@ extension Node { - Node Resulting from the deletion and the splaying of the removed node */ - public func remove(value: T) -> Node? { - let replacement: Node? + fileprivate func remove(value: T) -> Node? { + guard let target = search(value: value) else { return self } - if let v = self.value, v == value { + if let left = target.left, let right = target.right { + let largestOfLeftChild = left.maximum() + left.parent = nil + right.parent = nil - 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 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 - 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 - 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 - parentToSplay = parent - } + SplayOperation.splay(node: largestOfLeftChild) + largestOfLeftChild.right = right - reconnectParentTo(node: replacement) + return largestOfLeftChild - // performs the splay operation - if let parentToSplay = parentToSplay { - SplayOperation.splay(node: parentToSplay) - } + } else if let left = target.left { + replace(node: target, with: left) + return left - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - - return parentToSplay + } else if let right = target.right { + replace(node: target, with: right) + return right - } 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 { - if right != nil { - return right?.remove(value: value) - } else { - let node = self - SplayOperation.splay(node: node) - return node - - } + return nil } } - 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() + private func replace(node: Node, with newNode: Node?) { + guard let sourceParent = sourceNode.parent else { return } - // 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 + if sourceNode.isLeftChild { + sourceParent.left = newNode } else { - successor.right = nil + sourceParent.right = newNode } - // And finally, connect the successor node to our parent. - return successor - } - - private func reconnectParentTo(node: Node?) { - if let parent = parent { - if isLeftChild { - parent.left = node - } else { - parent.right = node - } - } - node?.parent = parent + newNode?.parent = sourceParent } } diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md index 75c3c0389..8a852c950 100644 --- a/Splay Tree/readme.md +++ b/Splay Tree/readme.md @@ -102,8 +102,11 @@ To insert a value: To delete a value: -- Delete it as in a binary search tree -- Splay the parent of the removed node to the root +- Perform search for the value, after performed search function if the tree contains the value, it'll be the root of the new tree. +- If the tree has only left child, change left child to the root of the tree, remove the old root node +- If the tree has only right child, change right child to the root of the tree, remove the old root node +- Else, the tree has both two children, set parent of two children to nil, so that they're two new trees (left-tree and right-tree). +- Splay the minimum node of right-tree (or minimum node of left-tree), then set left-tree as left child of new root of right-tree (or set right-tree as right child of new root of left-tree), return right-tree ### Search From 73f009209e99eaed53a6c81bf72dae83a5397cb4 Mon Sep 17 00:00:00 2001 From: Ahmed Abdulkareem Rezik Date: Thu, 9 Jul 2020 14:33:03 +0200 Subject: [PATCH 50/65] Fixed Hashable Conformance to hash(into:) --- Graph/Graph/Edge.swift | 14 +++++++------- Graph/Graph/Vertex.swift | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Graph/Graph/Edge.swift b/Graph/Graph/Edge.swift index ac5ed6a25..61cb576d1 100644 --- a/Graph/Graph/Edge.swift +++ b/Graph/Graph/Edge.swift @@ -29,13 +29,13 @@ extension Edge: CustomStringConvertible { extension Edge: Hashable { - public var hashValue: Int { - var string = "\(from.description)\(to.description)" - if weight != nil { - string.append("\(weight!)") - } - return string.hashValue - } + public func hash(into hasher: inout Hasher) { + hasher.combine(from) + hasher.combine(to) + if weight != nil { + hasher.combine(weight) + } + } } public func == (lhs: Edge, rhs: Edge) -> Bool { diff --git a/Graph/Graph/Vertex.swift b/Graph/Graph/Vertex.swift index 758a367bb..cdf39ba62 100644 --- a/Graph/Graph/Vertex.swift +++ b/Graph/Graph/Vertex.swift @@ -24,8 +24,10 @@ extension Vertex: CustomStringConvertible { extension Vertex: Hashable { - public var hashValue: Int { - return "\(data)\(index)".hashValue + public func hasher(into hasher: inout Hasher){ + + hasher.combine(data) + hasher.combine(index) } } From 0513f7d1d0432d844357f5b931bfc5e0d1940870 Mon Sep 17 00:00:00 2001 From: Ahmed Abdulkareem Rezik Date: Thu, 9 Jul 2020 14:37:37 +0200 Subject: [PATCH 51/65] Fixed Conformance to Hashable Protocol in Vertex and Edge structs --- Graph/Graph/Edge.swift | 14 ++++++++------ Graph/Graph/Vertex.swift | 12 +++++++----- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Graph/Graph/Edge.swift b/Graph/Graph/Edge.swift index 61cb576d1..1f29e07dd 100644 --- a/Graph/Graph/Edge.swift +++ b/Graph/Graph/Edge.swift @@ -29,13 +29,15 @@ extension Edge: CustomStringConvertible { extension Edge: Hashable { + public func hash(into hasher: inout Hasher) { - hasher.combine(from) - hasher.combine(to) - if weight != nil { - hasher.combine(weight) - } - } + hasher.combine(from) + hasher.combine(to) + if weight != nil { + hasher.combine(weight) + } + } + } public func == (lhs: Edge, rhs: Edge) -> Bool { diff --git a/Graph/Graph/Vertex.swift b/Graph/Graph/Vertex.swift index cdf39ba62..45b2c3088 100644 --- a/Graph/Graph/Vertex.swift +++ b/Graph/Graph/Vertex.swift @@ -24,11 +24,13 @@ extension Vertex: CustomStringConvertible { extension Vertex: Hashable { - public func hasher(into hasher: inout Hasher){ - - hasher.combine(data) - hasher.combine(index) - } + + + public func hasher(into hasher: inout Hasher){ + + hasher.combine(data) + hasher.combine(index) + } } From 4311cad2e332b9454c1189bddcbbca5f156a3d4c Mon Sep 17 00:00:00 2001 From: Samuel Huang Date: Wed, 22 Jul 2020 13:26:35 -0700 Subject: [PATCH 52/65] Update BTree.swift Fix spelling of swift markers - rename `Travelsals` to `Traversals` --- B-Tree/BTree.playground/Sources/BTree.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/B-Tree/BTree.playground/Sources/BTree.swift b/B-Tree/BTree.playground/Sources/BTree.swift index 2693eb308..2ed0b2593 100644 --- a/B-Tree/BTree.playground/Sources/BTree.swift +++ b/B-Tree/BTree.playground/Sources/BTree.swift @@ -86,7 +86,7 @@ extension BTreeNode { } } -// MARK: BTreeNode extension: Travelsals +// MARK: BTreeNode extension: Traversals extension BTreeNode { @@ -443,7 +443,7 @@ public class BTree { } } -// MARK: BTree extension: Travelsals +// MARK: BTree extension: Traversals extension BTree { /** From 617187bf4c36ab57948592d403e295cf8127d664 Mon Sep 17 00:00:00 2001 From: Richard Ash Date: Sat, 29 Aug 2020 13:37:23 -0700 Subject: [PATCH 53/65] Update style of Graph --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++++++++ Graph/Graph/Edge.swift | 15 +++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 Graph/Graph.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Graph/Graph.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/Graph/Graph.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Graph/Graph.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Graph/Graph.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Graph/Graph.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Graph/Graph.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/Graph/Graph.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Graph/Graph/Edge.swift b/Graph/Graph/Edge.swift index 3c95f9666..9ddd4e23d 100644 --- a/Graph/Graph/Edge.swift +++ b/Graph/Graph/Edge.swift @@ -29,14 +29,13 @@ extension Edge: CustomStringConvertible { extension Edge: Hashable { - public func hash(into hasher: inout Hasher) { - hasher.combine(from) - hasher.combine(to) - if weight != nil { - hasher.combine(weight) - } - } - + public func hash(into hasher: inout Hasher) { + hasher.combine(from) + hasher.combine(to) + if weight != nil { + hasher.combine(weight) + } + } } From d951e67ec24167c9518bcab4e91946ce956978f3 Mon Sep 17 00:00:00 2001 From: Richard Ash Date: Sat, 29 Aug 2020 13:57:25 -0700 Subject: [PATCH 54/65] Update README.markdown --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 3e0174576..093c5b9e7 100644 --- a/README.markdown +++ b/README.markdown @@ -195,6 +195,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Minimum Spanning Tree](Minimum%20Spanning%20Tree/) - [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) - [Dijkstra's shortest path algorithm](Dijkstra%20Algorithm/) +- [A*](A-star/) ## Puzzles From 7bba2b28da53b3764f24c7fa455fe37065948530 Mon Sep 17 00:00:00 2001 From: Richard Ash Date: Sat, 29 Aug 2020 13:58:06 -0700 Subject: [PATCH 55/65] Update README.markdown --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 093c5b9e7..b8b59bbcc 100644 --- a/README.markdown +++ b/README.markdown @@ -195,7 +195,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Minimum Spanning Tree](Minimum%20Spanning%20Tree/) - [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) - [Dijkstra's shortest path algorithm](Dijkstra%20Algorithm/) -- [A*](A-star/) +- [A-star](A-star/) ## Puzzles From cf518c04b31013a4f1b468648967eb7a7a3694b6 Mon Sep 17 00:00:00 2001 From: Richard Ash Date: Sat, 29 Aug 2020 13:58:47 -0700 Subject: [PATCH 56/65] Update README.markdown --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index b8b59bbcc..e87fe0335 100644 --- a/README.markdown +++ b/README.markdown @@ -195,7 +195,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Minimum Spanning Tree](Minimum%20Spanning%20Tree/) - [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) - [Dijkstra's shortest path algorithm](Dijkstra%20Algorithm/) -- [A-star](A-star/) +- [A-Star](A-Star/) ## Puzzles From e515919e305371cbff38319e00d21c90b35188e4 Mon Sep 17 00:00:00 2001 From: Richard Ash Date: Sat, 29 Aug 2020 14:24:59 -0700 Subject: [PATCH 57/65] Update Vertex.swift --- Graph/Graph/Vertex.swift | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Graph/Graph/Vertex.swift b/Graph/Graph/Vertex.swift index f74b38396..48645f0fa 100644 --- a/Graph/Graph/Vertex.swift +++ b/Graph/Graph/Vertex.swift @@ -24,16 +24,10 @@ extension Vertex: CustomStringConvertible { extension Vertex: Hashable { - - - - public func hasher(into hasher: inout Hasher){ - - hasher.combine(data) - hasher.combine(index) - } - - + public func hasher(into hasher: inout Hasher) { + hasher.combine(data) + hasher.combine(index) + } } From 81e2726f03ea14a5f92ddafe2e093cba9bee84c1 Mon Sep 17 00:00:00 2001 From: Richard Ash Date: Sat, 29 Aug 2020 14:35:34 -0700 Subject: [PATCH 58/65] Update Linked List/README.markdown --- Linked List/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index d6f1fc986..c80b11d6f 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -491,7 +491,7 @@ Recursive Approach: } let temp = reverse(head.next) head.next.next = head - head.next = NULL + head.next = nil return temp } ``` From 15229cf1b57bd5bd95e81a19a0fd7de9abe0bb6f Mon Sep 17 00:00:00 2001 From: Richard Ash Date: Sat, 29 Aug 2020 14:38:06 -0700 Subject: [PATCH 59/65] Update Linked List/README.markdown --- Linked List/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index c80b11d6f..fdbc2ee84 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -486,7 +486,7 @@ Iterative Approach: Recursive Approach: ```swift public func reverse(node: head) { - if (!head || !(head.next)) { + if !head || !head.next { return head } let temp = reverse(head.next) From d664df8cb4fea0aad54d2e693f01684cec0590f9 Mon Sep 17 00:00:00 2001 From: Hashem Date: Mon, 29 Mar 2021 15:58:37 +0400 Subject: [PATCH 60/65] Update README.markdown `sort()` is in place sort. in reveres `sorted()` returns a sorted copy of the original array --- Insertion Sort/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Insertion Sort/README.markdown b/Insertion Sort/README.markdown index 8c2a5c1a0..1c41aa91d 100644 --- a/Insertion Sort/README.markdown +++ b/Insertion Sort/README.markdown @@ -114,7 +114,7 @@ insertionSort(list) Here is how the code works. -1. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly. Like Swift's own `sort()`, the `insertionSort()` function will return a sorted *copy* of the original array. +1. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly. Like Swift's own `sorted()`, the `insertionSort()` function will return a sorted *copy* of the original array. 2. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what picks the top-most number from the pile. The variable `x` is the index of where the sorted portion ends and the pile begins (the position of the `|` bar). Remember, at any given moment the beginning of the array -- from index 0 up to `x` -- is always sorted. The rest, from index `x` until the last element, is the unsorted pile. From 90e23a6790f1f0a0e3704314a08be02114bcdf11 Mon Sep 17 00:00:00 2001 From: Coskun Deniz Date: Sat, 21 Aug 2021 19:44:58 +0100 Subject: [PATCH 61/65] declare 'index' as variable --- Insertion Sort/InsertionSort.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Insertion Sort/InsertionSort.swift b/Insertion Sort/InsertionSort.swift index e24ede905..5f0b6c2b4 100644 --- a/Insertion Sort/InsertionSort.swift +++ b/Insertion Sort/InsertionSort.swift @@ -28,14 +28,13 @@ func insertionSort(_ array: [T]) -> [T] { guard array.count > 1 else { return array } var sortedArray = array - for index in 1.. 0, temp < sortedArray[currentIndex - 1] { - sortedArray[currentIndex] = sortedArray[currentIndex - 1] - currentIndex -= 1 + for var index in 1.. 0, temp < sortedArray[index - 1] { + sortedArray[index] = sortedArray[index - 1] + index -= 1 } - sortedArray[currentIndex] = temp + sortedArray[index] = temp } return sortedArray } From 5ad2c68e359c6676df6b3b95315fe8d2b8d70d81 Mon Sep 17 00:00:00 2001 From: Aaron Watkins Date: Fri, 26 Nov 2021 16:35:21 -0500 Subject: [PATCH 62/65] legacy variables names correct legacy variable name `x` to be `index` so reader isnt wasting time scratching their head and can focus more on understanding the insertion sort algorithm. --- Insertion Sort/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Insertion Sort/README.markdown b/Insertion Sort/README.markdown index 1c41aa91d..f37bfeaef 100644 --- a/Insertion Sort/README.markdown +++ b/Insertion Sort/README.markdown @@ -116,9 +116,9 @@ Here is how the code works. 1. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly. Like Swift's own `sorted()`, the `insertionSort()` function will return a sorted *copy* of the original array. -2. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what picks the top-most number from the pile. The variable `x` is the index of where the sorted portion ends and the pile begins (the position of the `|` bar). Remember, at any given moment the beginning of the array -- from index 0 up to `x` -- is always sorted. The rest, from index `x` until the last element, is the unsorted pile. +2. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what picks the top-most number from the pile. The variable `index` is the index of where the sorted portion ends and the pile begins (the position of the `|` bar). Remember, at any given moment the beginning of the array -- from index 0 up to `index` -- is always sorted. The rest, from index `index` until the last element, is the unsorted pile. -3. The inner loop looks at the element at position `x`. This is the number at the top of the pile, and it may be smaller than any of the previous elements. The inner loop steps backwards through the sorted array; every time it finds a previous number that is larger, it swaps them. When the inner loop completes, the beginning of the array is sorted again, and the sorted portion has grown by one element. +3. The inner loop looks at the element at position `index`. This is the number at the top of the pile, and it may be smaller than any of the previous elements. The inner loop steps backwards through the sorted array; every time it finds a previous number that is larger, it swaps them. When the inner loop completes, the beginning of the array is sorted again, and the sorted portion has grown by one element. > **Note:** The outer loop starts at index 1, not 0. Moving the very first element from the pile to the sorted portion doesn't actually change anything, so we might as well skip it. From eb4e151b55ff846c28be5d2357b7ab2f776a9dce Mon Sep 17 00:00:00 2001 From: Aaron Watkins Date: Fri, 26 Nov 2021 16:45:21 -0500 Subject: [PATCH 63/65] correct index to currentIndex --- Insertion Sort/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Insertion Sort/README.markdown b/Insertion Sort/README.markdown index f37bfeaef..f7b933b92 100644 --- a/Insertion Sort/README.markdown +++ b/Insertion Sort/README.markdown @@ -116,9 +116,9 @@ Here is how the code works. 1. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly. Like Swift's own `sorted()`, the `insertionSort()` function will return a sorted *copy* of the original array. -2. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what picks the top-most number from the pile. The variable `index` is the index of where the sorted portion ends and the pile begins (the position of the `|` bar). Remember, at any given moment the beginning of the array -- from index 0 up to `index` -- is always sorted. The rest, from index `index` until the last element, is the unsorted pile. +2. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what picks the top-most number from the pile. The variable `currentIndex` is the index of where the sorted portion ends and the pile begins (the position of the `|` bar). Remember, at any given moment the beginning of the array -- from index 0 up to `currentIndex` -- is always sorted. The rest, from index `currentIndex` until the last element, is the unsorted pile. -3. The inner loop looks at the element at position `index`. This is the number at the top of the pile, and it may be smaller than any of the previous elements. The inner loop steps backwards through the sorted array; every time it finds a previous number that is larger, it swaps them. When the inner loop completes, the beginning of the array is sorted again, and the sorted portion has grown by one element. +3. The inner loop looks at the element at position `currentIndex`. This is the number at the top of the pile, and it may be smaller than any of the previous elements. The inner loop steps backwards through the sorted array; every time it finds a previous number that is larger, it swaps them. When the inner loop completes, the beginning of the array is sorted again, and the sorted portion has grown by one element. > **Note:** The outer loop starts at index 1, not 0. Moving the very first element from the pile to the sorted portion doesn't actually change anything, so we might as well skip it. From 6af57a839d59db84ded9e95315d4a9aeff8a9d64 Mon Sep 17 00:00:00 2001 From: Namratha2604 Date: Thu, 26 Sep 2024 14:25:05 +0530 Subject: [PATCH 64/65] #986-corrected the comment --- Bloom Filter/BloomFilter.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bloom Filter/BloomFilter.playground/Contents.swift b/Bloom Filter/BloomFilter.playground/Contents.swift index 7a3719d57..8ed808a06 100644 --- a/Bloom Filter/BloomFilter.playground/Contents.swift +++ b/Bloom Filter/BloomFilter.playground/Contents.swift @@ -79,4 +79,4 @@ bloom.insert("Bloom Filterz") print(bloom.array) bloom.query("Bloom Filterz") // true -bloom.query("Hello WORLD") // true +bloom.query("Hello WORLD") // false or true: It may return true due to a false positive, but it's not guaranteed. From 5e8c02913c04d86d3b41ebf47210b9f974ad7d26 Mon Sep 17 00:00:00 2001 From: Nitesh J Date: Mon, 7 Oct 2024 14:05:17 +0530 Subject: [PATCH 65/65] issue resolved #997 and #998 Correction of the README.markdown and Selection Sampling code improvement #998 --- Selection Sampling/README.markdown | 2 +- Selection Sampling/SelectionSampling.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Selection Sampling/README.markdown b/Selection Sampling/README.markdown index 741f592f4..5c2ff5e25 100644 --- a/Selection Sampling/README.markdown +++ b/Selection Sampling/README.markdown @@ -12,7 +12,7 @@ func select(from a: [T], count k: Int) -> [T] { for i in 0..(from a: [T], count k: Int) -> [T] { for i in 0..