diff --git a/Algorithm.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Algorithm.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Algorithm.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Package.swift b/Package.swift index 090a41f..d1d7762 100644 --- a/Package.swift +++ b/Package.swift @@ -9,7 +9,8 @@ let package = Package( // Products define the executables and libraries produced by a package, and make them visible to other packages. .library( name: "Algorithm", - targets: ["Algorithm"]), + targets: ["Algorithm"] + ) ], dependencies: [ // Dependencies declare other packages that this package depends on. @@ -21,10 +22,12 @@ let package = Package( .target( name: "Algorithm", dependencies: [], - path: "Sources"), + path: "Sources" + ), .testTarget( name: "AlgorithmTests", dependencies: ["Algorithm"], - path: "Tests"), + path: "Tests" + ) ] ) diff --git a/Sources/Algorithm+Array.swift b/Sources/Algorithm+Array.swift index 5f69e3c..fba1d3e 100644 --- a/Sources/Algorithm+Array.swift +++ b/Sources/Algorithm+Array.swift @@ -24,117 +24,116 @@ */ extension Array where Element: Equatable { - /** - Removes a given Element from an Array if it exists. - - Parameter object: An Element. - - Returns: An optional Element if the removed - element exists. - */ - @discardableResult - mutating func remove(object: Element) -> Element? { - return firstIndex(of: object).map { self.remove(at: $0) } - } - - /** - Removes a list of given Elements from an Array if - they exists. - - Parameter objects: A list of Elements. - */ - mutating func remove(objects: Element...) { - remove(objects: objects) - } - - /** - Removes an Array of given Elements from an Array if - they exists. - - Parameter objects: An Array of Elements. - */ - mutating func remove(objects: [Element]) { - objects.forEach { - self.remove(object: $0) + /** + Removes a given Element from an Array if it exists. + - Parameter object: An Element. + - Returns: An optional Element if the removed + element exists. + */ + @discardableResult + mutating func remove(object: Element) -> Element? { + return firstIndex(of: object).map { self.remove(at: $0) } } - } - - /** - The total count for the given Elements. - - Parameter of elements: A list of Elements. - - Returns: An Int. - */ - public func count(of elements: Element...) -> Int { - return count(of: elements) - } - - /** - The total count for the given Elements. - - Parameter of elements: An Array of Elements. - - Returns: An Int. - */ - public func count(of elements: [Element]) -> Int { - - var c = 0 - for e in elements { - for x in self where e == x { - c += 1 - } + + /** + Removes a list of given Elements from an Array if + they exists. + - Parameter objects: A list of Elements. + */ + mutating func remove(objects: Element...) { + remove(objects: objects) } - return c - } - - /** - The probability of getting the given Elements. - - Parameter of elements: A list of Elements. - - Returns: A Double. - */ - public func probability(of elements: Element...) -> Double { - return probability(of: elements) - } - - /** - The probability of getting the given Elements. - - Parameter of elements: An Array of Elements. - - Returns: A Double. - */ - public func probability(of elements: [Element]) -> Double { - return 0 < count ? Double(count(of: elements)) / Double(count) : 0 - } - - /** - A probability method that uses a block to determine the member state of a condition. - - Parameter of elements: A list of Elements. - - Returns: A Double. - */ - public func probability(execute block: @escaping (Element) -> Bool) -> Double { - guard 0 < count else { - return 0 + + /** + Removes an Array of given Elements from an Array if + they exists. + - Parameter objects: An Array of Elements. + */ + mutating func remove(objects: [Element]) { + objects.forEach { + self.remove(object: $0) + } } - - var c = 0 - for e in self { - if block(e) { - c += 1 - } + + /** + The total count for the given Elements. + - Parameter of elements: A list of Elements. + - Returns: An Int. + */ + public func count(of elements: Element...) -> Int { + return count(of: elements) + } + + /** + The total count for the given Elements. + - Parameter of elements: An Array of Elements. + - Returns: An Int. + */ + public func count(of elements: [Element]) -> Int { + var c = 0 + for e in elements { + for x in self where e == x { + c += 1 + } + } + return c + } + + /** + The probability of getting the given Elements. + - Parameter of elements: A list of Elements. + - Returns: A Double. + */ + public func probability(of elements: Element...) -> Double { + return probability(of: elements) + } + + /** + The probability of getting the given Elements. + - Parameter of elements: An Array of Elements. + - Returns: A Double. + */ + public func probability(of elements: [Element]) -> Double { + return count > 0 ? Double(count(of: elements)) / Double(count) : 0 + } + + /** + A probability method that uses a block to determine the member state of a condition. + - Parameter of elements: A list of Elements. + - Returns: A Double. + */ + public func probability(execute block: @escaping (Element) -> Bool) -> Double { + guard count > 0 else { + return 0 + } + + var c = 0 + for e in self { + if block(e) { + c += 1 + } + } + + return Double(c) / Double(count) + } + + /** + Calculates the expected value of elements based on a given number of trials. + - Parameter trials: Number of trials. + - Parameter elements: A list of Elements. + - Returns: A Double. + */ + public func expectedValue(trials: Int, for elements: Element...) -> Double { + return expectedValue(trials: trials, for: elements) + } + + /** + Calculates the expected value of elements based on a given number of trials. + - Parameter trials: Number of trials. + - Parameter elements: An Array of Elements. + - Returns: A Double. + */ + public func expectedValue(trials: Int, for elements: [Element]) -> Double { + return Double(trials) * probability(of: elements) } - - return Double(c) / Double(count) - } - - /** - Calculates the expected value of elements based on a given number of trials. - - Parameter trials: Number of trials. - - Parameter elements: A list of Elements. - - Returns: A Double. - */ - public func expectedValue(trials: Int, for elements: Element...) -> Double { - return expectedValue(trials: trials, for: elements) - } - - /** - Calculates the expected value of elements based on a given number of trials. - - Parameter trials: Number of trials. - - Parameter elements: An Array of Elements. - - Returns: A Double. - */ - public func expectedValue(trials: Int, for elements: [Element]) -> Double { - return Double(trials) * probability(of: elements) - } } diff --git a/Sources/Algorithm+Set.swift b/Sources/Algorithm+Set.swift index dac8904..b1f6c1d 100644 --- a/Sources/Algorithm+Set.swift +++ b/Sources/Algorithm+Set.swift @@ -24,87 +24,87 @@ */ extension Set: Probable { - /** - The total count for the given Elements. - - Parameter of elements: A list of Elements. - - Returns: An Int. - */ - public func count(of elements: Element...) -> Int { - return count(of: elements) - } - - /** - The total count for the given Elements. - - Parameter of elements: An Array of Elements. - - Returns: An Int. - */ - public func count(of elements: [Element]) -> Int { - var c = 0 - for e in elements { - for x in self { - if e == x { - c += 1 + /** + The total count for the given Elements. + - Parameter of elements: A list of Elements. + - Returns: An Int. + */ + public func count(of elements: Element...) -> Int { + return count(of: elements) + } + + /** + The total count for the given Elements. + - Parameter of elements: An Array of Elements. + - Returns: An Int. + */ + public func count(of elements: [Element]) -> Int { + var c = 0 + for e in elements { + for x in self { + if e == x { + c += 1 + } + } + } + return c + } + + /** + The probability of getting the given Elements. + - Parameter of elements: A list of Elements. + - Returns: A Double. + */ + public func probability(of elements: Element...) -> Double { + return probability(of: elements) + } + + /** + The probability of getting the given Elements. + - Parameter of elements: An Array of Elements. + - Returns: A Double. + */ + public func probability(of elements: [Element]) -> Double { + return count > 0 ? Double(count(of: elements)) / Double(count) : 0 + } + + /** + A probability method that uses a block to determine the member state of a condition. + - Parameter of elements: A list of Elements. + - Returns: A Double. + */ + public func probability(of block: @escaping (Element) -> Bool) -> Double { + guard count > 0 else { + return 0 + } + + var c = 0 + for e in self { + if block(e) { + c += 1 + } } - } + + return Double(c) / Double(count) } - return c - } - - /** - The probability of getting the given Elements. - - Parameter of elements: A list of Elements. - - Returns: A Double. - */ - public func probability(of elements: Element...) -> Double { - return probability(of: elements) - } - - /** - The probability of getting the given Elements. - - Parameter of elements: An Array of Elements. - - Returns: A Double. - */ - public func probability(of elements: [Element]) -> Double { - return 0 < count ? Double(count(of: elements)) / Double(count) : 0 - } - - /** - A probability method that uses a block to determine the member state of a condition. - - Parameter of elements: A list of Elements. - - Returns: A Double. - */ - public func probability(of block: @escaping (Element) -> Bool) -> Double { - guard 0 < count else { - return 0 + + /** + Calculates the expected value of elements based on a given number of trials. + - Parameter trials: Number of trials. + - Parameter elements: A list of Elements. + - Returns: A Double. + */ + public func expectedValue(trials: Int, for elements: Element...) -> Double { + return expectedValue(trials: trials, for: elements) } - - var c = 0 - for e in self { - if block(e) { - c += 1 - } + + /** + Calculates the expected value of elements based on a given number of trials. + - Parameter trials: Number of trials. + - Parameter elements: An Array of Elements. + - Returns: A Double. + */ + public func expectedValue(trials: Int, for elements: [Element]) -> Double { + return Double(trials) * probability(of: elements) } - - return Double(c) / Double(count) - } - - /** - Calculates the expected value of elements based on a given number of trials. - - Parameter trials: Number of trials. - - Parameter elements: A list of Elements. - - Returns: A Double. - */ - public func expectedValue(trials: Int, for elements: Element...) -> Double { - return expectedValue(trials: trials, for: elements) - } - - /** - Calculates the expected value of elements based on a given number of trials. - - Parameter trials: Number of trials. - - Parameter elements: An Array of Elements. - - Returns: A Double. - */ - public func expectedValue(trials: Int, for elements: [Element]) -> Double { - return Double(trials) * probability(of: elements) - } } diff --git a/Sources/Deque.swift b/Sources/Deque.swift index 44ee648..640c46b 100644 --- a/Sources/Deque.swift +++ b/Sources/Deque.swift @@ -24,137 +24,137 @@ */ public struct Deque: CustomStringConvertible, Sequence { - public typealias Iterator = AnyIterator - - /** - :name: list - :description: Underlying element structure. - - returns: DoublyLinkedList - */ - private var list: DoublyLinkedList - - /** - :name: count - :description: Total number of items in the Deque. - - returns: Int - */ - public var count: Int { - return list.count - } - - /** - :name: front - :description: Get the element at the front of the Deque - and do not remove it. - - returns: Element? - */ - public var front: Element? { - return list.front - } - - /** - :name: back - :description: Get the element at the back of the Deque - and do not remove it. - - returns: Element? - */ - public var back: Element? { - return list.back - } - - /** - :name: isEmpty - :description: A boolean of whether the Deque is empty. - - returns: Bool - */ - public var isEmpty: Bool { - return list.isEmpty - } - - /** - :name: description - :description: Conforms to the Printable Protocol. - - returns: String - */ - public var description: String { - return list.description - } - - /** - :name: init - :description: Constructor. - */ - public init() { - list = DoublyLinkedList() - } - - /** - Conforms to the SequenceType Protocol. Returns the next value - in the sequence of nodes. - - Returns: A Deque.Iterator. - */ - public func makeIterator() -> Deque.Iterator { - return list.makeIterator() - } - - /** - :name: insertAtFront - :description: Insert a new element at the front of the Deque. - */ - mutating public func insert(atFront element: Element) { - list.insert(atFront: element) - } - - /** - :name: removeAtFront - :description: Get the element at the front of the Deque - and remove it. - - returns: Element? - */ - mutating public func removeAtFront() -> Element? { - return list.removeAtFront() - } - - /** - :name: insertAtBack - :description: Insert a new element at the back of the Deque. - */ - mutating public func insert(atBack element: Element) { - list.insert(atBack: element) - } - - /** - :name: removeAtBack - :description: Get the element at the back of the Deque - and remove it. - - returns: Element? - */ - mutating public func removeAtBack() -> Element? { - return list.removeAtBack() - } - - /** - :name: removeAll - :description: Remove all elements from the Deque. - */ - mutating public func removeAll() { - list.removeAll() - } + public typealias Iterator = AnyIterator + + /** + :name: list + :description: Underlying element structure. + - returns: DoublyLinkedList + */ + private var list: DoublyLinkedList + + /** + :name: count + :description: Total number of items in the Deque. + - returns: Int + */ + public var count: Int { + return list.count + } + + /** + :name: front + :description: Get the element at the front of the Deque + and do not remove it. + - returns: Element? + */ + public var front: Element? { + return list.front + } + + /** + :name: back + :description: Get the element at the back of the Deque + and do not remove it. + - returns: Element? + */ + public var back: Element? { + return list.back + } + + /** + :name: isEmpty + :description: A boolean of whether the Deque is empty. + - returns: Bool + */ + public var isEmpty: Bool { + return list.isEmpty + } + + /** + :name: description + :description: Conforms to the Printable Protocol. + - returns: String + */ + public var description: String { + return list.description + } + + /** + :name: init + :description: Constructor. + */ + public init() { + list = DoublyLinkedList() + } + + /** + Conforms to the SequenceType Protocol. Returns the next value + in the sequence of nodes. + - Returns: A Deque.Iterator. + */ + public func makeIterator() -> Deque.Iterator { + return list.makeIterator() + } + + /** + :name: insertAtFront + :description: Insert a new element at the front of the Deque. + */ + public mutating func insert(atFront element: Element) { + list.insert(atFront: element) + } + + /** + :name: removeAtFront + :description: Get the element at the front of the Deque + and remove it. + - returns: Element? + */ + public mutating func removeAtFront() -> Element? { + return list.removeAtFront() + } + + /** + :name: insertAtBack + :description: Insert a new element at the back of the Deque. + */ + public mutating func insert(atBack element: Element) { + list.insert(atBack: element) + } + + /** + :name: removeAtBack + :description: Get the element at the back of the Deque + and remove it. + - returns: Element? + */ + public mutating func removeAtBack() -> Element? { + return list.removeAtBack() + } + + /** + :name: removeAll + :description: Remove all elements from the Deque. + */ + public mutating func removeAll() { + list.removeAll() + } } -public func +(lhs: Deque, rhs: Deque) -> Deque { - var d = Deque() - for x in lhs { - d.insert(atBack: x) - } - for x in rhs { - d.insert(atBack: x) - } - return d +public func + (lhs: Deque, rhs: Deque) -> Deque { + var d = Deque() + for x in lhs { + d.insert(atBack: x) + } + for x in rhs { + d.insert(atBack: x) + } + return d } -public func +=(lhs: inout Deque, rhs: Deque) { - for x in rhs { - lhs.insert(atBack: x) - } +public func += (lhs: inout Deque, rhs: Deque) { + for x in rhs { + lhs.insert(atBack: x) + } } diff --git a/Sources/DoublyLinkedList.swift b/Sources/DoublyLinkedList.swift index 6455c04..e63ad42 100644 --- a/Sources/DoublyLinkedList.swift +++ b/Sources/DoublyLinkedList.swift @@ -24,330 +24,330 @@ */ public struct DoublyLinkedList: CustomStringConvertible, Sequence { - public typealias Iterator = AnyIterator - - /** - First node in the list. - - Returns: An optional DoublyLinkedListNode. - */ - private var head: DoublyLinkedListNode? - - /** - Last node in list. - - Returns: An optional DoublyLinkedListNode. - */ - private var tail: DoublyLinkedListNode? - - /** - Current cursor position when iterating. - - Returns: An optional DoublyLinkedListNode. - */ - private var current: DoublyLinkedListNode? - - /** - Number of nodes in DoublyLinkedList. - - Returns: An Int. - */ - public private(set) var count: Int - - /** - Conforms to Printable Protocol. - - Returns: A String. - */ - public var description: String { - var output = "(" - var c = 0 - var x = head - while nil !== x { - output += "\(String(describing: x))" - c += 1 - if c != count { - output += ", " - } - x = x!.next + public typealias Iterator = AnyIterator + + /** + First node in the list. + - Returns: An optional DoublyLinkedListNode. + */ + private var head: DoublyLinkedListNode? + + /** + Last node in list. + - Returns: An optional DoublyLinkedListNode. + */ + private var tail: DoublyLinkedListNode? + + /** + Current cursor position when iterating. + - Returns: An optional DoublyLinkedListNode. + */ + private var current: DoublyLinkedListNode? + + /** + Number of nodes in DoublyLinkedList. + - Returns: An Int. + */ + public private(set) var count: Int + + /** + Conforms to Printable Protocol. + - Returns: A String. + */ + public var description: String { + var output = "(" + var c = 0 + var x = head + while nil !== x { + output += "\(String(describing: x))" + c += 1 + if c != count { + output += ", " + } + x = x!.next + } + output += ")" + return output } - output += ")" - return output - } - - /** - Retrieves the data at first node of the DoublyLinkedList. - - Returns: An optional Element. - */ - public var front: Element? { - return head?.element - } - - /** - Retrieves the element at the back node of teh DoublyLinkedList. - - Returns: An optional Element. - */ - public var back: Element? { - return tail?.element - } - - /** - Retrieves the element at the current iterator position - in the DoublyLinkedList. - - Returns: An optional Element. - */ - public var cursor: Element? { - return current?.element - } - - /** - A boolean of whether the DoublyLinkedList is empty. - - Returns: A boolean indicating if the DoubleLinkedList is - empty or not, true if yes, false otherwise. - */ - public var isEmpty: Bool { - return 0 == count - } - - /** - A boolean of whether the cursor has reached the back of the - DoublyLinkedList. - - Returns: A boolean indicating if the cursor is pointing at - the back Element, true if yes, false otherwise. - */ - public var isCursorAtBack: Bool { - return nil == cursor - } - - /** - A boolean of whether the cursor has reached the front of the - DoublyLinkedList. - - Returns: A boolean indicating if the cursor is pointing at - the front Element, true if yes, false otherwise. - */ - public var isCursorAtFront: Bool { - return nil == cursor - } - - /// An initializer. - public init() { - count = 0 - reset() - } - - /** - Retrieves the element at the poistion after the - current cursor poistion. Also moves the cursor - to that node. - - Returns: An optional Element. - */ - @discardableResult - mutating public func next() -> Element? { - current = current?.next - return current?.element - } - - /** - Retrieves the element at the poistion before the - current cursor poistion. Also moves the cursor - to that node. - - Returns: An optional Element. - */ - @discardableResult - mutating public func previous() -> Element? { - current = current?.previous - return current?.element - } - - /** - Conforms to the SequenceType Protocol. Returns the next value - in the sequence of nodes. - - Returns: A DoublyLinkedList.Iterator. - */ - public func makeIterator() -> DoublyLinkedList.Iterator { - var it = head - return AnyIterator { - defer { - it = it?.next - } - return it?.element + + /** + Retrieves the data at first node of the DoublyLinkedList. + - Returns: An optional Element. + */ + public var front: Element? { + return head?.element } - } - - /// Removes all nodes from the DoublyLinkedList. - mutating public func removeAll() { - while !isEmpty { - _ = removeAtFront() + + /** + Retrieves the element at the back node of teh DoublyLinkedList. + - Returns: An optional Element. + */ + public var back: Element? { + return tail?.element } - } - - /** - Inserts a new Element at the front of the DoublyLinkedList. - - Parameter atFront: An Element. - */ - mutating public func insert(atFront element: Element) { - var z: DoublyLinkedListNode - if 0 == count { - z = DoublyLinkedListNode(next: nil, previous: nil, element: element) - tail = z - } else { - z = DoublyLinkedListNode(next: head, previous: nil, element: element) - head!.previous = z + + /** + Retrieves the element at the current iterator position + in the DoublyLinkedList. + - Returns: An optional Element. + */ + public var cursor: Element? { + return current?.element } - head = z - count += 1 - if 1 == count { - current = head - } else if head === current { - current = head!.next + + /** + A boolean of whether the DoublyLinkedList is empty. + - Returns: A boolean indicating if the DoubleLinkedList is + empty or not, true if yes, false otherwise. + */ + public var isEmpty: Bool { + return count == 0 } - } - - /** - Removes the element at the front position. - - Returns: An optional Element. - */ - @discardableResult - mutating public func removeAtFront() -> Element? { - if 0 == count { - return nil + + /** + A boolean of whether the cursor has reached the back of the + DoublyLinkedList. + - Returns: A boolean indicating if the cursor is pointing at + the back Element, true if yes, false otherwise. + */ + public var isCursorAtBack: Bool { + return cursor == nil } - let element: Element? = head!.element - count -= 1 - if 0 == count { - reset() - } else { - head = head!.next + + /** + A boolean of whether the cursor has reached the front of the + DoublyLinkedList. + - Returns: A boolean indicating if the cursor is pointing at + the front Element, true if yes, false otherwise. + */ + public var isCursorAtFront: Bool { + return cursor == nil } - return element - } - - /** - Inserts a new Element at the back of the DoublyLinkedList. - - Parameter atBack: An Element. - */ - mutating public func insert(atBack element: Element) { - var z: DoublyLinkedListNode - if 0 == count { - z = DoublyLinkedListNode(next: nil, previous: nil, element: element) - head = z - } else { - z = DoublyLinkedListNode(next: nil, previous: tail, element: element) - tail!.next = z + + /// An initializer. + public init() { + count = 0 + reset() } - tail = z - count += 1 - if 1 == count { - current = tail - } else if tail === current { - current = tail!.previous + + /** + Retrieves the element at the poistion after the + current cursor poistion. Also moves the cursor + to that node. + - Returns: An optional Element. + */ + @discardableResult + public mutating func next() -> Element? { + current = current?.next + return current?.element } - } - - /** - Removes the element at the back position. - - Returns: An optional Element. - */ - @discardableResult - mutating public func removeAtBack() -> Element? { - if 0 == count { - return nil + + /** + Retrieves the element at the poistion before the + current cursor poistion. Also moves the cursor + to that node. + - Returns: An optional Element. + */ + @discardableResult + public mutating func previous() -> Element? { + current = current?.previous + return current?.element } - let element = tail?.element - count -= 1 - if 0 == count { - reset() - } else { - tail = tail?.previous + + /** + Conforms to the SequenceType Protocol. Returns the next value + in the sequence of nodes. + - Returns: A DoublyLinkedList.Iterator. + */ + public func makeIterator() -> DoublyLinkedList.Iterator { + var it = head + return AnyIterator { + defer { + it = it?.next + } + return it?.element + } } - return element - } - - /// Move the cursor to the front of the DoublyLinkedList. - mutating public func cursorToFront() { - current = head - } - - /// Move the cursor to the back of the DoublyLinkedList. - mutating public func cursorToBack() { - current = tail - } - - /** - Inserts a new Element before the cursor position. - - Parameter beforeCursor element: An Element. - */ - mutating public func insert(beforeCursor element: Element) { - if nil == current || head === current { - insert(atFront: element) - } else { - let z = DoublyLinkedListNode(next: current, previous: current!.previous, element: element) - current!.previous?.next = z - current!.previous = z - count += 1 + + /// Removes all nodes from the DoublyLinkedList. + public mutating func removeAll() { + while !isEmpty { + _ = removeAtFront() + } } - } - - /** - Inserts a new Element after the cursor position. - - Parameter afterCursor element: An Element. - */ - mutating public func insert(afterCursor element: Element) { - if nil == current || tail === current { - insert(atBack: element) - } else { - let z = DoublyLinkedListNode(next: current!.next, previous: current, element: element) - current!.next?.previous = z - current!.next = z - count += 1 + + /** + Inserts a new Element at the front of the DoublyLinkedList. + - Parameter atFront: An Element. + */ + public mutating func insert(atFront element: Element) { + var z: DoublyLinkedListNode + if count == 0 { + z = DoublyLinkedListNode(next: nil, previous: nil, element: element) + tail = z + } else { + z = DoublyLinkedListNode(next: head, previous: nil, element: element) + head!.previous = z + } + head = z + count += 1 + if count == 1 { + current = head + } else if head === current { + current = head!.next + } } - } - - /** - Removes the element at the cursor position. - - Returns: An optional Element. - */ - @discardableResult - mutating public func removeAtCursor() -> Element? { - if 1 >= count { - return removeAtFront() - } else { - let element = current?.element - current?.previous?.next = current?.next - current?.next?.previous = current?.previous - if tail === current { - current = tail?.previous - tail = current - } else if head === current { - current = head?.next - head = current - } else { - current = current?.next - } - count -= 1 - return element + + /** + Removes the element at the front position. + - Returns: An optional Element. + */ + @discardableResult + public mutating func removeAtFront() -> Element? { + if count == 0 { + return nil + } + let element: Element? = head!.element + count -= 1 + if count == 0 { + reset() + } else { + head = head!.next + } + return element + } + + /** + Inserts a new Element at the back of the DoublyLinkedList. + - Parameter atBack: An Element. + */ + public mutating func insert(atBack element: Element) { + var z: DoublyLinkedListNode + if count == 0 { + z = DoublyLinkedListNode(next: nil, previous: nil, element: element) + head = z + } else { + z = DoublyLinkedListNode(next: nil, previous: tail, element: element) + tail!.next = z + } + tail = z + count += 1 + if count == 1 { + current = tail + } else if tail === current { + current = tail!.previous + } + } + + /** + Removes the element at the back position. + - Returns: An optional Element. + */ + @discardableResult + public mutating func removeAtBack() -> Element? { + if count == 0 { + return nil + } + let element = tail?.element + count -= 1 + if count == 0 { + reset() + } else { + tail = tail?.previous + } + return element + } + + /// Move the cursor to the front of the DoublyLinkedList. + public mutating func cursorToFront() { + current = head + } + + /// Move the cursor to the back of the DoublyLinkedList. + public mutating func cursorToBack() { + current = tail + } + + /** + Inserts a new Element before the cursor position. + - Parameter beforeCursor element: An Element. + */ + public mutating func insert(beforeCursor element: Element) { + if current == nil || head === current { + insert(atFront: element) + } else { + let z = DoublyLinkedListNode(next: current, previous: current!.previous, element: element) + current!.previous?.next = z + current!.previous = z + count += 1 + } + } + + /** + Inserts a new Element after the cursor position. + - Parameter afterCursor element: An Element. + */ + public mutating func insert(afterCursor element: Element) { + if current == nil || tail === current { + insert(atBack: element) + } else { + let z = DoublyLinkedListNode(next: current!.next, previous: current, element: element) + current!.next?.previous = z + current!.next = z + count += 1 + } + } + + /** + Removes the element at the cursor position. + - Returns: An optional Element. + */ + @discardableResult + public mutating func removeAtCursor() -> Element? { + if count <= 1 { + return removeAtFront() + } else { + let element = current?.element + current?.previous?.next = current?.next + current?.next?.previous = current?.previous + if tail === current { + current = tail?.previous + tail = current + } else if head === current { + current = head?.next + head = current + } else { + current = current?.next + } + count -= 1 + return element + } + } + + /** + Removes all elements and resets the head, tail, and cursor + to the sentinel value. + */ + private mutating func reset() { + head = nil + tail = nil + current = nil } - } - - /** - Removes all elements and resets the head, tail, and cursor - to the sentinel value. - */ - mutating private func reset() { - head = nil - tail = nil - current = nil - } } -public func +(lhs: DoublyLinkedList, rhs: DoublyLinkedList) -> DoublyLinkedList { - var l = DoublyLinkedList() - for x in lhs { - l.insert(atBack: x) - } - for x in rhs { - l.insert(atBack: x) - } - return l +public func + (lhs: DoublyLinkedList, rhs: DoublyLinkedList) -> DoublyLinkedList { + var l = DoublyLinkedList() + for x in lhs { + l.insert(atBack: x) + } + for x in rhs { + l.insert(atBack: x) + } + return l } -public func +=(lhs: inout DoublyLinkedList, rhs: DoublyLinkedList) { - for x in rhs { - lhs.insert(atBack: x) - } +public func += (lhs: inout DoublyLinkedList, rhs: DoublyLinkedList) { + for x in rhs { + lhs.insert(atBack: x) + } } diff --git a/Sources/DoublyLinkedListNode.swift b/Sources/DoublyLinkedListNode.swift index 130f9bb..d7f5303 100644 --- a/Sources/DoublyLinkedListNode.swift +++ b/Sources/DoublyLinkedListNode.swift @@ -24,43 +24,43 @@ */ internal class DoublyLinkedListNode: CustomStringConvertible { - /** - :name: next - :description: Points to the successor element in the DoublyLinkedList. - - returns: DoublyLinkedListNode? - */ - internal var next: DoublyLinkedListNode? - - /** - :name: previous - :description: points to the predacessor element in the DoublyLinkedList. - - returns: DoublyLinkedListNode? - */ - internal var previous: DoublyLinkedListNode? - - /** - :name: data - :description: Satellite data. - - returns: Element? - */ - internal var element: Element? - - /** - :name: description - :description: Conforms to the Printable Protocol. - - returns: String - */ - internal var description: String { - return "\(String(describing: element))" - } - - /** - :name: init - :description: Constructor. - */ - internal init(next: DoublyLinkedListNode?, previous: DoublyLinkedListNode?, element: Element?) { - self.next = next - self.previous = previous - self.element = element - } + /** + :name: next + :description: Points to the successor element in the DoublyLinkedList. + - returns: DoublyLinkedListNode? + */ + internal var next: DoublyLinkedListNode? + + /** + :name: previous + :description: points to the predacessor element in the DoublyLinkedList. + - returns: DoublyLinkedListNode? + */ + internal var previous: DoublyLinkedListNode? + + /** + :name: data + :description: Satellite data. + - returns: Element? + */ + internal var element: Element? + + /** + :name: description + :description: Conforms to the Printable Protocol. + - returns: String + */ + internal var description: String { + return "\(String(describing: element))" + } + + /** + :name: init + :description: Constructor. + */ + internal init(next: DoublyLinkedListNode?, previous: DoublyLinkedListNode?, element: Element?) { + self.next = next + self.previous = previous + self.element = element + } } diff --git a/Sources/Probable.swift b/Sources/Probable.swift index 2617ba3..a7e1f5d 100644 --- a/Sources/Probable.swift +++ b/Sources/Probable.swift @@ -24,49 +24,49 @@ */ internal protocol Probable { - associatedtype ProbableElement: Equatable - - /** - The instance count of elements. - - Parameter of elements: A list of ProbableElements - - Returns: An Int. - */ - func count(of elements: ProbableElement...) -> Int - - /** - The instance count of elements. - - Parameter of elements: An Array of ProbableElements. - - Returns: An Int. - */ - func count(of elements: [ProbableElement]) -> Int - - /** - The probability of given elements. - - Parameter of elements: A list of ProbableElements. - - Returns: A Double. - */ - func probability(of elements: ProbableElement...) -> Double - - /** - The probability of given elements. - - Parameter of elements: An Array of ProbableElements. - - Returns: A Double. - */ - func probability(of elements: [ProbableElement]) -> Double - - /** - The expected value of given elements based on a number of trials. - - Parameter trials: An Int. - - Parameter for elements: A list of ProbableElements. - - Returns: A Double. - */ - func expectedValue(trials: Int, for elements: ProbableElement...) -> Double - - /** - The expected value of given elements based on a number of trials. - - Parameter trials: An Int. - - Parameter for elements: An Array of ProbableElements. - - Returns: A Double. - */ - func expectedValue(trials: Int, for elements: [ProbableElement]) -> Double + associatedtype ProbableElement: Equatable + + /** + The instance count of elements. + - Parameter of elements: A list of ProbableElements + - Returns: An Int. + */ + func count(of elements: ProbableElement...) -> Int + + /** + The instance count of elements. + - Parameter of elements: An Array of ProbableElements. + - Returns: An Int. + */ + func count(of elements: [ProbableElement]) -> Int + + /** + The probability of given elements. + - Parameter of elements: A list of ProbableElements. + - Returns: A Double. + */ + func probability(of elements: ProbableElement...) -> Double + + /** + The probability of given elements. + - Parameter of elements: An Array of ProbableElements. + - Returns: A Double. + */ + func probability(of elements: [ProbableElement]) -> Double + + /** + The expected value of given elements based on a number of trials. + - Parameter trials: An Int. + - Parameter for elements: A list of ProbableElements. + - Returns: A Double. + */ + func expectedValue(trials: Int, for elements: ProbableElement...) -> Double + + /** + The expected value of given elements based on a number of trials. + - Parameter trials: An Int. + - Parameter for elements: An Array of ProbableElements. + - Returns: A Double. + */ + func expectedValue(trials: Int, for elements: [ProbableElement]) -> Double } diff --git a/Sources/Queue.swift b/Sources/Queue.swift index 9f030f2..877e7e2 100644 --- a/Sources/Queue.swift +++ b/Sources/Queue.swift @@ -24,110 +24,110 @@ */ public struct Queue: CustomStringConvertible, Sequence { - public typealias Iterator = AnyIterator - - /** - :name: list - :description: Underlying data structure. - - returns: DoublyLinkedList - */ - private var list: DoublyLinkedList - - /** - :name: count - :description: Total number of items in the Queue. - - returns: Int - */ - public var count: Int { - return list.count - } - - /** - :name: peek - :description: Get the element at the front of - the Queue, and do not remove it. - - returns: Element? - */ - public var peek: Element? { - return list.front - } - - /** - :name: isEmpty - :description: A boolean of whether the Queue is empty. - - returns: Bool - */ - public var isEmpty: Bool { - return list.isEmpty - } - - /** - :name: description - :description: Conforms to the Printable Protocol. - - returns: String - */ - public var description: String { - return list.description - } - - /** - :name: init - :description: Constructor. - */ - public init() { - list = DoublyLinkedList() - } - - // - // :name: generate - // :description: Conforms to the SequenceType Protocol. Returns - // the next value in the sequence of nodes. - // :returns: Queue.Generator - // - public func makeIterator() -> Iterator { - return list.makeIterator() - } - - /** - :name: enqueue - :description: Insert a new element at the back of the Queue. - */ - mutating public func enqueue(_ element: Element) { - list.insert(atBack: element) - } - - /** - :name: dequeue - :description: Get and remove the element at the front - of the Queue. - - returns: Element? - */ - mutating public func dequeue() -> Element? { - return list.removeAtFront() - } - - /** - :name: removeAll - :description: Remove all elements from the Queue. - */ - mutating public func removeAll() { - list.removeAll() - } - - public static func +(lhs: Queue, rhs: Queue) -> Queue { - var q = Queue() - for x in lhs { - q.enqueue(x) + public typealias Iterator = AnyIterator + + /** + :name: list + :description: Underlying data structure. + - returns: DoublyLinkedList + */ + private var list: DoublyLinkedList + + /** + :name: count + :description: Total number of items in the Queue. + - returns: Int + */ + public var count: Int { + return list.count + } + + /** + :name: peek + :description: Get the element at the front of + the Queue, and do not remove it. + - returns: Element? + */ + public var peek: Element? { + return list.front + } + + /** + :name: isEmpty + :description: A boolean of whether the Queue is empty. + - returns: Bool + */ + public var isEmpty: Bool { + return list.isEmpty + } + + /** + :name: description + :description: Conforms to the Printable Protocol. + - returns: String + */ + public var description: String { + return list.description + } + + /** + :name: init + :description: Constructor. + */ + public init() { + list = DoublyLinkedList() } - for x in rhs { - q.enqueue(x) + + // + // :name: generate + // :description: Conforms to the SequenceType Protocol. Returns + // the next value in the sequence of nodes. + // :returns: Queue.Generator + // + public func makeIterator() -> Iterator { + return list.makeIterator() + } + + /** + :name: enqueue + :description: Insert a new element at the back of the Queue. + */ + public mutating func enqueue(_ element: Element) { + list.insert(atBack: element) + } + + /** + :name: dequeue + :description: Get and remove the element at the front + of the Queue. + - returns: Element? + */ + public mutating func dequeue() -> Element? { + return list.removeAtFront() } - return q - } - - public static func +=(lhs: inout Queue, rhs: Queue) { - for x in rhs { - lhs.enqueue(x) + + /** + :name: removeAll + :description: Remove all elements from the Queue. + */ + public mutating func removeAll() { + list.removeAll() + } + + public static func + (lhs: Queue, rhs: Queue) -> Queue { + var q = Queue() + for x in lhs { + q.enqueue(x) + } + for x in rhs { + q.enqueue(x) + } + return q + } + + public static func += (lhs: inout Queue, rhs: Queue) { + for x in rhs { + lhs.enqueue(x) + } } - } } diff --git a/Sources/RedBlackNode.swift b/Sources/RedBlackNode.swift index f4e6746..1004fc1 100644 --- a/Sources/RedBlackNode.swift +++ b/Sources/RedBlackNode.swift @@ -24,96 +24,94 @@ */ internal class RedBlackNode: Comparable, Equatable, CustomStringConvertible { - /** - :name: parent - :description: A reference to the parent node of a given node. - - returns: RedBlackNode! - */ - internal var parent: RedBlackNode! - - /** - :name: left - :description: A reference to the left child node of a given node. - - returns: RedBlackNode! - */ - internal var left: RedBlackNode! - - /** - :name: right - :description: A reference to the right child node of a given node. - - returns: RedBlackNode! - */ - internal var right: RedBlackNode! - - /** - :name: isRed - :description: A boolean indicating whether te node is marked isRed or black. - - returns: Bool - */ - internal var isRed: Bool - - /** - :name: order - :description: Used to track the order statistic of a node, which maintains - key order in the tree. - - returns: Int - */ - internal var order: Int - - /** - :name: key - :description: A reference to the key value of the node, which is what organizes - a node in a given tree. - - returns: Key! - */ - internal var key: Key! - - /** - :name: value - :description: Satellite data stoisRed in the node. - - returns: Value? - */ - internal var value: Value? - - /** - :name: description - :description: Conforms to the Printable Protocol. - - returns: String - */ - internal var description: String { - return "(\(String(describing: key)), \(String(describing: value)))" - } - - /** - :name: init - :description: Constructor used for sentinel nodes. - */ - internal init() { - isRed = false - order = 0 - } - - /** - :name: init - :description: Constructor used for nodes that store data. - */ - internal init(parent: RedBlackNode, sentinel: RedBlackNode, key: Key, value: Value?) { - self.key = key - self.value = value - self.parent = parent - left = sentinel - right = sentinel - isRed = true - order = 1 - } - - static func ==(lhs: RedBlackNode, rhs: RedBlackNode) -> Bool { - return lhs.key == rhs.key - } - - static func <(lhs: RedBlackNode, rhs: RedBlackNode) -> Bool { - return lhs.key < rhs.key - } -} + /** + :name: parent + :description: A reference to the parent node of a given node. + - returns: RedBlackNode! + */ + internal var parent: RedBlackNode! + + /** + :name: left + :description: A reference to the left child node of a given node. + - returns: RedBlackNode! + */ + internal var left: RedBlackNode! + + /** + :name: right + :description: A reference to the right child node of a given node. + - returns: RedBlackNode! + */ + internal var right: RedBlackNode! + + /** + :name: isRed + :description: A boolean indicating whether te node is marked isRed or black. + - returns: Bool + */ + internal var isRed: Bool + + /** + :name: order + :description: Used to track the order statistic of a node, which maintains + key order in the tree. + - returns: Int + */ + internal var order: Int + + /** + :name: key + :description: A reference to the key value of the node, which is what organizes + a node in a given tree. + - returns: Key! + */ + internal var key: Key! + /** + :name: value + :description: Satellite data stoisRed in the node. + - returns: Value? + */ + internal var value: Value? + /** + :name: description + :description: Conforms to the Printable Protocol. + - returns: String + */ + internal var description: String { + return "(\(String(describing: key)), \(String(describing: value)))" + } + + /** + :name: init + :description: Constructor used for sentinel nodes. + */ + internal init() { + isRed = false + order = 0 + } + + /** + :name: init + :description: Constructor used for nodes that store data. + */ + internal init(parent: RedBlackNode, sentinel: RedBlackNode, key: Key, value: Value?) { + self.key = key + self.value = value + self.parent = parent + left = sentinel + right = sentinel + isRed = true + order = 1 + } + + static func == (lhs: RedBlackNode, rhs: RedBlackNode) -> Bool { + return lhs.key == rhs.key + } + + static func < (lhs: RedBlackNode, rhs: RedBlackNode) -> Bool { + return lhs.key < rhs.key + } +} diff --git a/Sources/RedBlackTree.swift b/Sources/RedBlackTree.swift index 61401d7..96339f6 100644 --- a/Sources/RedBlackTree.swift +++ b/Sources/RedBlackTree.swift @@ -24,876 +24,874 @@ */ public struct RedBlackTree: Probable, Collection, BidirectionalCollection, CustomStringConvertible { - public typealias Element = (key: Key, value: Value?) - public typealias ProbableElement = Key - - /// Returns the position immediately after the given index. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - /// - Returns: The index value immediately after `i`. - public func index(after i: Int) -> Int { - return i + 1 - } - - public func index(before i: Int) -> Int { - return i - 1 - } - - public typealias Iterator = AnyIterator - - /** - Total number of elements within the RedBlackTree - */ - public internal(set) var count = 0 - - /** - :name: sentinel - :description: A node used to mark the end of a path in the tree. - - returns: RedBlackNode - */ - internal private(set) var sentinel: RedBlackNode - - /** - :name: root - :description: The root of the tree data structure. - - returns: RedBlackNode - */ - internal private(set) var root: RedBlackNode - - /** - :name: isUniquelyKeyed - :description: A boolean used to indicate whether to allow the - tree to store non-unique key values or only unique - key values. - - returns: Bool - */ - public private(set) var isUniquelyKeyed: Bool - - /** - :name: description - :description: Conforms to the Printable Protocol. Outputs the - data in the Tree in a readable format. - - returns: String - */ - public var description: String { - return "[" + map { "\($0)" }.joined(separator: ", ") + "]" - } - - /** - :name: startIndex - :description: Conforms to the Collection Protocol. - - returns: Int - */ - public var startIndex: Int { - return 0 - } - - /** - :name: endIndex - :description: Conforms to the Collection Protocol. - - returns: Int - */ - public var endIndex: Int { - return count - } - - /** - :name: first - :description: Get the first node value in the tree, this is - the first node based on the order of keys where - k1 <= k2 <= K3 ... <= Kn - - returns: Element? - */ - public var first: Element? { - guard 0 < count else { - return nil - } - - return self[0] - } - - /** - :name: last - :description: Get the last node value in the tree, this is - the last node based on the order of keys where - k1 <= k2 <= K3 ... <= Kn - - returns: Element? - */ - public var last: Element? { - guard 0 < count else { - return nil - } - - return self[count - 1] - } - - /// Retrieves an Array of the key values in order. - public var keys: [Key] { - return map { $0.key } - } - - /// Retrieves an Array of the values that are sorted based. - public var values: [Value] { - return compactMap { $0.value } - } - - /** - :name: init - :description: Constructor where the tree is guaranteed to store - non-unique keys. - */ - public init() { - isUniquelyKeyed = false - sentinel = RedBlackNode() - root = sentinel - } - - /** - :name: init - :description: Constructor where the tree is optionally allowed - to store uniqe or non-unique keys. - - parameter uniqueKeys: Bool Set the keys to be unique. - */ - public init(uniqueKeys: Bool) { - isUniquelyKeyed = uniqueKeys - sentinel = RedBlackNode() - root = sentinel - } - - public func _customIndexOfEquatableElement(_ element: Key) -> Int?? { - return nil - } - - // - // :name: generate - // :description: Conforms to the SequenceType Protocol. Returns - // the next value in the sequence of nodes using - // index values [0...n-1]. - // :returns: RedBlackTree.Generator - // - public func makeIterator() -> RedBlackTree.Iterator { - var i = indices.makeIterator() - return AnyIterator { i.next().map { self[$0] } } - } - - /** - Conforms to Probable protocol. - */ - public func count(of keys: Key...) -> Int { - return count(of: keys) - } - - /** - Conforms to Probable protocol. - */ - public func count(of keys: [Key]) -> Int { - var c = 0 - - for k in keys { - internalCount(k, node: root, count: &c) - } - - return c - } - - /** - The probability of elements. - */ - public func probability(of keys: Key...) -> Double { - return probability(of: keys) - } - - /** - The probability of elements. - */ - public func probability(of keys: [Key]) -> Double { - return 0 == count ? 0 : Double(count(of: keys)) / Double(count) - } - - /** - The probability of elements. - */ - public func probability(execute block: (Key, Value?) -> Bool) -> Double { - if 0 == count { - return 0 - } - - var c = 0 - - for (k, v) in self { - if block(k, v) { - c += 1 - } - } - - return Double(c) / Double(count) - } - - /** - The expected value of elements. - */ - public func expectedValue(trials: Int, for keys: Key...) -> Double { - return expectedValue(trials: trials, for: keys) - } - - /** - The expected value of elements. - */ - public func expectedValue(trials: Int, for keys: [Key]) -> Double { - return Double(trials) * probability(of: keys) - } - - /** - :name: insert - :description: Insert a key / value pair. - - returns: Bool - */ - @discardableResult - mutating public func insert(value: Value?, for key: Key) -> Bool { - return sentinel !== internalInsert(key, value: value) - } - - /** - :name: insert - :description: Inserts a list of (Key, Value?) pairs. - - parameter nodes: (Key, Value?)... Elements to insert. - */ - mutating public func insert(_ nodes: (Key, Value?)...) { - insert(nodes) - } - - /** - :name: insert - :description: Inserts an array of (Key, Value?) pairs. - - parameter nodes: [(Key, Value?)] Elements to insert. - */ - mutating public func insert(_ nodes: [(Key, Value?)]) { - for (k, v) in nodes { - insert(value: v, for: k) - } - } - - /** - :name: removeValueForKeys - :description: Removes a node from the tree based on the key value given. - If the tree allows non-unique keys, then all keys matching - the given key value will be removed. - - returns: RedBlackTree? - */ - mutating public func removeValue(for keys: Key...) { - return removeValue(for: keys) - } - - /** - :name: removeValueForKeys - :description: Removes a key / value pairs from the tree based on the key given. - If the tree allows non-unique keys, then all keys matching - the given key will be removed. - - returns: RedBlackTree? - */ - mutating public func removeValue(for keys: [Key]) { - for x in keys { - var z = internalRemoveValueForKey(x) - - while sentinel !== z { - z = internalRemoveValueForKey(x) - } - } - } - - /** - :name: removeValueForKey - :description: Removes a single instance of a value for a key. This is - important when using non-unique keys. - - returns: Value? - */ - @discardableResult - mutating public func removeInstanceValueForKey(_ key: Key) -> Value? { - return internalRemoveValueForKey(key).value - } - - /** - :name: removeAll - :description: Remove all nodes from the tree. - */ - mutating public func removeAll() { - while sentinel !== root { - internalRemoveValueForKey(root.key) - } - } - - /** - :name: updateValue - :description: Updates a node for the given key value. - If the tree allows non-unique keys, then all keys matching - the given key value will be updated. - */ - mutating public func update(value: Value?, for key: Key) { - internalUpdateValue(value, for: key, node: root) - } - - /** - :name: findValueForKey - :description: Finds the first instance in a non-unique tree and only instance - in isUniquelyKeyed tree of a given keyed node. - - returns: Value? - */ - public func findValue(for key: Key) -> Value? { - return internalFindNodeForKey(key).value - } - - /** - :name: findLowerValue - :description: Finds instance with key that is lower or equal input key - - returns: Value? - */ - public func findLowerValue(for key: Key) -> Value? { - return internalFindLowerForKey(key).value - } - - /** - :name: findCeilingValue - :description: Finds instance with key that is larger or equal input key - - returns: Value? - */ - public func findCeilingValue(for key: Key) -> Value? { - return internalFindCeilingForKey(key).value - } - - /** - Returns the Key value at a given position. - - Parameter position: An Int. - - Returns: A Key. - */ - public subscript(position: Int) -> Key { - return self[position].key - } - - /** - :name: operator [0...count - 1] - :description: Allows array like access of the index. - Items are kept in order, so when iterating - through the items, they are returned in their - ordeisRed form. - - returns: (key: Key, value: Value?) - */ - public subscript(index: Int) -> (key: Key, value: Value?) { - get { - let x = internalSelect(root, order: index + 1) - return (x.key, x.value) - } - set(element) { - internalUpdateValue(element.value, for: element.key, node: root) - } - } - - /** - :name: operator ["key1"..."keyN"] - :description: Property key mapping. If the key type is a - String, this feature allows access like a - Dictionary. - - returns: Value? - */ - public subscript(key: Key) -> Value? { - get { - return internalFindNodeForKey(key).value - } - set(value) { - if sentinel === internalFindNodeForKey(key) { - _ = internalInsert(key, value: value) - } else { - update(value: value, for: key) - } - } - } - - /** - :name: internalFindLowerForKey - :description: Finds a node with a key that is equal or less that given. - - returns: RedBlackNode - */ - private func internalFindLowerForKey(_ key: Key) -> RedBlackNode { - var z = root - var max = sentinel - - while z !== sentinel { - if key > z.key { - max = z - } - if key == z.key { + public typealias Element = (key: Key, value: Value?) + public typealias ProbableElement = Key + + /// Returns the position immediately after the given index. + /// + /// - Parameter i: A valid index of the collection. `i` must be less than + /// `endIndex`. + /// - Returns: The index value immediately after `i`. + public func index(after i: Int) -> Int { + return i + 1 + } + + public func index(before i: Int) -> Int { + return i - 1 + } + + public typealias Iterator = AnyIterator + + /** + Total number of elements within the RedBlackTree + */ + public internal(set) var count = 0 + + /** + :name: sentinel + :description: A node used to mark the end of a path in the tree. + - returns: RedBlackNode + */ + internal private(set) var sentinel: RedBlackNode + + /** + :name: root + :description: The root of the tree data structure. + - returns: RedBlackNode + */ + internal private(set) var root: RedBlackNode + + /** + :name: isUniquelyKeyed + :description: A boolean used to indicate whether to allow the + tree to store non-unique key values or only unique + key values. + - returns: Bool + */ + public private(set) var isUniquelyKeyed: Bool + + /** + :name: description + :description: Conforms to the Printable Protocol. Outputs the + data in the Tree in a readable format. + - returns: String + */ + public var description: String { + return "[" + map { "\($0)" }.joined(separator: ", ") + "]" + } + + /** + :name: startIndex + :description: Conforms to the Collection Protocol. + - returns: Int + */ + public var startIndex: Int { + return 0 + } + + /** + :name: endIndex + :description: Conforms to the Collection Protocol. + - returns: Int + */ + public var endIndex: Int { + return count + } + + /** + :name: first + :description: Get the first node value in the tree, this is + the first node based on the order of keys where + k1 <= k2 <= K3 ... <= Kn + - returns: Element? + */ + public var first: Element? { + guard count > 0 else { + return nil + } + + return self[0] + } + + /** + :name: last + :description: Get the last node value in the tree, this is + the last node based on the order of keys where + k1 <= k2 <= K3 ... <= Kn + - returns: Element? + */ + public var last: Element? { + guard count > 0 else { + return nil + } + + return self[count - 1] + } + + /// Retrieves an Array of the key values in order. + public var keys: [Key] { + return map { $0.key } + } + + /// Retrieves an Array of the values that are sorted based. + public var values: [Value] { + return compactMap { $0.value } + } + + /** + :name: init + :description: Constructor where the tree is guaranteed to store + non-unique keys. + */ + public init() { + isUniquelyKeyed = false + sentinel = RedBlackNode() + root = sentinel + } + + /** + :name: init + :description: Constructor where the tree is optionally allowed + to store uniqe or non-unique keys. + - parameter uniqueKeys: Bool Set the keys to be unique. + */ + public init(uniqueKeys: Bool) { + isUniquelyKeyed = uniqueKeys + sentinel = RedBlackNode() + root = sentinel + } + + public func _customIndexOfEquatableElement(_: Key) -> Int?? { + return nil + } + + // + // :name: generate + // :description: Conforms to the SequenceType Protocol. Returns + // the next value in the sequence of nodes using + // index values [0...n-1]. + // :returns: RedBlackTree.Generator + // + public func makeIterator() -> RedBlackTree.Iterator { + var i = indices.makeIterator() + return AnyIterator { i.next().map { self[$0] } } + } + + /** + Conforms to Probable protocol. + */ + public func count(of keys: Key...) -> Int { + return count(of: keys) + } + + /** + Conforms to Probable protocol. + */ + public func count(of keys: [Key]) -> Int { + var c = 0 + + for k in keys { + internalCount(k, node: root, count: &c) + } + + return c + } + + /** + The probability of elements. + */ + public func probability(of keys: Key...) -> Double { + return probability(of: keys) + } + + /** + The probability of elements. + */ + public func probability(of keys: [Key]) -> Double { + return count == 0 ? 0 : Double(count(of: keys)) / Double(count) + } + + /** + The probability of elements. + */ + public func probability(execute block: (Key, Value?) -> Bool) -> Double { + if count == 0 { + return 0 + } + + var c = 0 + + for (k, v) in self { + if block(k, v) { + c += 1 + } + } + + return Double(c) / Double(count) + } + + /** + The expected value of elements. + */ + public func expectedValue(trials: Int, for keys: Key...) -> Double { + return expectedValue(trials: trials, for: keys) + } + + /** + The expected value of elements. + */ + public func expectedValue(trials: Int, for keys: [Key]) -> Double { + return Double(trials) * probability(of: keys) + } + + /** + :name: insert + :description: Insert a key / value pair. + - returns: Bool + */ + @discardableResult + public mutating func insert(value: Value?, for key: Key) -> Bool { + return sentinel !== internalInsert(key, value: value) + } + + /** + :name: insert + :description: Inserts a list of (Key, Value?) pairs. + - parameter nodes: (Key, Value?)... Elements to insert. + */ + public mutating func insert(_ nodes: (Key, Value?)...) { + insert(nodes) + } + + /** + :name: insert + :description: Inserts an array of (Key, Value?) pairs. + - parameter nodes: [(Key, Value?)] Elements to insert. + */ + public mutating func insert(_ nodes: [(Key, Value?)]) { + for (k, v) in nodes { + insert(value: v, for: k) + } + } + + /** + :name: removeValueForKeys + :description: Removes a node from the tree based on the key value given. + If the tree allows non-unique keys, then all keys matching + the given key value will be removed. + - returns: RedBlackTree? + */ + public mutating func removeValue(for keys: Key...) { + return removeValue(for: keys) + } + + /** + :name: removeValueForKeys + :description: Removes a key / value pairs from the tree based on the key given. + If the tree allows non-unique keys, then all keys matching + the given key will be removed. + - returns: RedBlackTree? + */ + public mutating func removeValue(for keys: [Key]) { + for x in keys { + var z = internalRemoveValueForKey(x) + + while sentinel !== z { + z = internalRemoveValueForKey(x) + } + } + } + + /** + :name: removeValueForKey + :description: Removes a single instance of a value for a key. This is + important when using non-unique keys. + - returns: Value? + */ + @discardableResult + public mutating func removeInstanceValueForKey(_ key: Key) -> Value? { + return internalRemoveValueForKey(key).value + } + + /** + :name: removeAll + :description: Remove all nodes from the tree. + */ + public mutating func removeAll() { + while sentinel !== root { + internalRemoveValueForKey(root.key) + } + } + + /** + :name: updateValue + :description: Updates a node for the given key value. + If the tree allows non-unique keys, then all keys matching + the given key value will be updated. + */ + public mutating func update(value: Value?, for key: Key) { + internalUpdateValue(value, for: key, node: root) + } + + /** + :name: findValueForKey + :description: Finds the first instance in a non-unique tree and only instance + in isUniquelyKeyed tree of a given keyed node. + - returns: Value? + */ + public func findValue(for key: Key) -> Value? { + return internalFindNodeForKey(key).value + } + + /** + :name: findLowerValue + :description: Finds instance with key that is lower or equal input key + - returns: Value? + */ + public func findLowerValue(for key: Key) -> Value? { + return internalFindLowerForKey(key).value + } + + /** + :name: findCeilingValue + :description: Finds instance with key that is larger or equal input key + - returns: Value? + */ + public func findCeilingValue(for key: Key) -> Value? { + return internalFindCeilingForKey(key).value + } + + /** + Returns the Key value at a given position. + - Parameter position: An Int. + - Returns: A Key. + */ + public subscript(position: Int) -> Key { + return self[position].key + } + + /** + :name: operator [0...count - 1] + :description: Allows array like access of the index. + Items are kept in order, so when iterating + through the items, they are returned in their + ordeisRed form. + - returns: (key: Key, value: Value?) + */ + public subscript(index: Int) -> (key: Key, value: Value?) { + get { + let x = internalSelect(root, order: index + 1) + return (x.key, x.value) + } + set(element) { + internalUpdateValue(element.value, for: element.key, node: root) + } + } + + /** + :name: operator ["key1"..."keyN"] + :description: Property key mapping. If the key type is a + String, this feature allows access like a + Dictionary. + - returns: Value? + */ + public subscript(key: Key) -> Value? { + get { + return internalFindNodeForKey(key).value + } + set(value) { + if sentinel === internalFindNodeForKey(key) { + _ = internalInsert(key, value: value) + } else { + update(value: value, for: key) + } + } + } + + /** + :name: internalFindLowerForKey + :description: Finds a node with a key that is equal or less that given. + - returns: RedBlackNode + */ + private func internalFindLowerForKey(_ key: Key) -> RedBlackNode { + var z = root + var max = sentinel + + while z !== sentinel { + if key > z.key { + max = z + } + if key == z.key { + return z + } + z = key < z.key as Key ? z.left : z.right + } + return max + } + + /** + :name: internalFindCeilingForKey + :description: Finds a node with a key that is equal or larger that given. + - returns: RedBlackNode + */ + private func internalFindCeilingForKey(_ key: Key) -> RedBlackNode { + var z = root + var min = sentinel + + while z !== sentinel { + if key < z.key { + min = z + } + if key == z.key { + return z + } + z = key < z.key as Key ? z.left : z.right + } + return min + } + + /** + :name: indexOf + :description: Returns the Index of a given member, or nil if the member is not present in the set. + - returns: Int + */ + public func index(of key: Key) -> Int { + let x = internalFindNodeForKey(key) + return sentinel === x ? -1 : internalOrder(x) - 1 + } + + /** + :name: internalInsert + :description: Insert a new node with the given key and value. + - returns: RedBlackNode + */ + private mutating func internalInsert(_ key: Key, value: Value?) -> RedBlackNode { + if isUniquelyKeyed, sentinel !== internalFindNodeForKey(key) { + return sentinel + } + + var y = sentinel + var x = root + + while x !== sentinel { + y = x + y.order += 1 + x = key < x.key as Key ? x.left : x.right + } + + let z = RedBlackNode(parent: y, sentinel: sentinel, key: key, value: value) + + if y === sentinel { + root = z + } else if key < y.key as Key { + y.left = z + } else { + y.right = z + } + + insertCleanUp(z) + count += 1 return z - } - z = key < z.key as Key ? z.left : z.right - } - return max - } - - /** - :name: internalFindCeilingForKey - :description: Finds a node with a key that is equal or larger that given. - - returns: RedBlackNode - */ - private func internalFindCeilingForKey(_ key: Key) -> RedBlackNode { - var z = root - var min = sentinel - - while z !== sentinel { - if key < z.key { - min = z - } - if key == z.key { + } + + /** + :name: insertCleanUp + :description: The clean up procedure needed to maintain the RedBlackTree balance. + - returns: RedBlackNode + */ + private mutating func insertCleanUp(_ node: RedBlackNode) { + var z = node + while z.parent.isRed { + if z.parent === z.parent.parent.left { + let y = z.parent.parent.right! + // violation 1, parent child relationship re to isRed + if y.isRed { + z.parent.isRed = false + y.isRed = false + z.parent.parent.isRed = true + z = z.parent.parent + } else { + // case 2, parent is isRed, uncle is black + if z === z.parent.right { + z = z.parent + leftRotate(z) + } + // case 3, balance colours + z.parent.isRed = false + z.parent.parent.isRed = true + rightRotate(z.parent.parent) + } + } else { + // symetric + let y = z.parent.parent.left! + // violation 1, parent child relationship re to isRed + if y.isRed { + z.parent.isRed = false + y.isRed = false + z.parent.parent.isRed = true + z = z.parent.parent + } else { + // case 2, parent is isRed, uncle is black + if z === z.parent.left { + z = z.parent + rightRotate(z) + } + // case 3, balance colours + z.parent.isRed = false + z.parent.parent.isRed = true + leftRotate(z.parent.parent) + } + } + } + root.isRed = false + } + + /** + :name: internalRemoveValueForKey + :description: Removes a node with the given key value and returns that + node. If the value does not exist, the sentinel is returned. + - returns: RedBlackNode + */ + @discardableResult + private mutating func internalRemoveValueForKey(_ key: Key) -> RedBlackNode { + let z = internalFindNodeForKey(key) + if z === sentinel { + return sentinel + } + + if z !== root { + var t = z.parent! + while t !== root { + t.order -= 1 + t = t.parent + } + root.order -= 1 + } + + var x: RedBlackNode! + var y = z + var isRed = y.isRed + + if z.left === sentinel { + x = z.right + transplant(z, v: z.right) + } else if z.right === sentinel { + x = z.left + transplant(z, v: z.left) + } else { + y = minimum(z.right) + isRed = y.isRed + x = y.right + if y.parent === z { + x.parent = y + } else { + transplant(y, v: y.right) + y.right = z.right + y.right.parent = y + var t = x.parent! + while t !== y { + t.order -= 1 + t = t.parent + } + y.order = y.left.order + 1 + } + transplant(z, v: y) + y.left = z.left + y.left.parent = y + y.isRed = z.isRed + y.order = y.left.order + y.right.order + 1 + } + if !isRed { + removeCleanUp(x) + } + count -= 1 return z - } - z = key < z.key as Key ? z.left : z.right - } - return min - } - - /** - :name: indexOf - :description: Returns the Index of a given member, or nil if the member is not present in the set. - - returns: Int - */ - public func index(of key: Key) -> Int { - let x = internalFindNodeForKey(key) - return sentinel === x ? -1 : internalOrder(x) - 1 - } - - /** - :name: internalInsert - :description: Insert a new node with the given key and value. - - returns: RedBlackNode - */ - mutating private func internalInsert(_ key: Key, value: Value?) -> RedBlackNode { - if isUniquelyKeyed && sentinel !== internalFindNodeForKey(key) { - return sentinel; - } - - var y = sentinel - var x = root - - while x !== sentinel { - y = x - y.order += 1 - x = key < x.key as Key ? x.left : x.right - } - - let z = RedBlackNode(parent: y, sentinel: sentinel, key: key, value: value) - - if y === sentinel { - root = z - } else if key < y.key as Key { - y.left = z - } else { - y.right = z - } - - insertCleanUp(z) - count += 1 - return z - } - - /** - :name: insertCleanUp - :description: The clean up procedure needed to maintain the RedBlackTree balance. - - returns: RedBlackNode - */ - mutating private func insertCleanUp(_ node: RedBlackNode) { - var z = node - while z.parent.isRed { - if z.parent === z.parent.parent.left { - let y = z.parent.parent.right! - // violation 1, parent child relationship re to isRed - if y.isRed { - z.parent.isRed = false - y.isRed = false - z.parent.parent.isRed = true - z = z.parent.parent + } + + /** + :name: removeCleanUp + :description: After a successful removal of a node, the RedBlackTree + is rebalanced by this method. + */ + private mutating func removeCleanUp(_ node: RedBlackNode) { + var x = node + while x !== root, !x.isRed { + if x === x.parent.left { + var y = x.parent.right! + if y.isRed { + y.isRed = false + x.parent.isRed = true + leftRotate(x.parent) + y = x.parent.right + } + if !y.left.isRed, !y.right.isRed { + y.isRed = true + x = x.parent + } else { + if !y.right.isRed { + y.left.isRed = false + y.isRed = true + rightRotate(y) + y = x.parent.right + } + y.isRed = x.parent.isRed + x.parent.isRed = false + y.right.isRed = false + leftRotate(x.parent) + x = root + } + } else { // symetric left and right + var y = x.parent.left! + if y.isRed { + y.isRed = false + x.parent.isRed = true + rightRotate(x.parent) + y = x.parent.left + } + if !y.right.isRed, !y.left.isRed { + y.isRed = true + x = x.parent + } else { + if !y.left.isRed { + y.right.isRed = false + y.isRed = true + leftRotate(y) + y = x.parent.left + } + y.isRed = x.parent.isRed + x.parent.isRed = false + y.left.isRed = false + rightRotate(x.parent) + x = root + } + } + } + x.isRed = false + } + + /** + :name: minimum + :description: Finds the minimum keyed node. + - returns: RedBlackNode + */ + private func minimum(_ node: RedBlackNode) -> RedBlackNode { + var x = node + var y = sentinel + while x !== sentinel { + y = x + x = x.left + } + return y + } + + /** + :name: transplant + :description: Swaps two subTrees in the tree. + */ + private mutating func transplant(_ u: RedBlackNode, v: RedBlackNode) { + if u.parent === sentinel { + root = v + } else if u === u.parent.left { + u.parent.left = v } else { - // case 2, parent is isRed, uncle is black - if z === z.parent.right { - z = z.parent - leftRotate(z) - } - // case 3, balance colours - z.parent.isRed = false - z.parent.parent.isRed = true - rightRotate(z.parent.parent) - } - } else { - // symetric - let y = z.parent.parent.left! - // violation 1, parent child relationship re to isRed - if y.isRed { - z.parent.isRed = false - y.isRed = false - z.parent.parent.isRed = true - z = z.parent.parent + u.parent.right = v + } + v.parent = u.parent + } + + /** + :name: leftRotate + :description: Rotates the nodes to satisfy the RedBlackTree + balance property. + */ + private mutating func leftRotate(_ x: RedBlackNode) { + let y = x.right! + + x.right = y.left + if sentinel !== y.left { + y.left.parent = x + } + + y.parent = x.parent + + if sentinel === x.parent { + root = y + } else if x === x.parent.left { + x.parent.left = y } else { - // case 2, parent is isRed, uncle is black - if z === z.parent.left { - z = z.parent - rightRotate(z) - } - // case 3, balance colours - z.parent.isRed = false - z.parent.parent.isRed = true - leftRotate(z.parent.parent) - } - } - } - root.isRed = false - } - - /** - :name: internalRemoveValueForKey - :description: Removes a node with the given key value and returns that - node. If the value does not exist, the sentinel is returned. - - returns: RedBlackNode - */ - @discardableResult - mutating private func internalRemoveValueForKey(_ key: Key) -> RedBlackNode { - let z = internalFindNodeForKey(key) - if z === sentinel { - return sentinel - } - - if z !== root { - var t = z.parent! - while t !== root { - t.order -= 1 - t = t.parent - } - root.order -= 1 - } - - var x: RedBlackNode! - var y = z - var isRed = y.isRed - - if z.left === sentinel { - x = z.right - transplant(z, v: z.right) - } else if z.right === sentinel { - x = z.left - transplant(z, v: z.left) - } else { - y = minimum(z.right) - isRed = y.isRed - x = y.right - if y.parent === z { + x.parent.right = y + } + + y.left = x x.parent = y - } else { - transplant(y, v: y.right) - y.right = z.right - y.right.parent = y - var t = x.parent! - while t !== y { - t.order -= 1 - t = t.parent - } - y.order = y.left.order + 1 - } - transplant(z, v: y) - y.left = z.left - y.left.parent = y - y.isRed = z.isRed - y.order = y.left.order + y.right.order + 1 - } - if !isRed { - removeCleanUp(x) - } - count -= 1 - return z - } - - /** - :name: removeCleanUp - :description: After a successful removal of a node, the RedBlackTree - is rebalanced by this method. - */ - mutating private func removeCleanUp(_ node: RedBlackNode) { - var x = node - while x !== root && !x.isRed { - if x === x.parent.left { - var y = x.parent.right! - if y.isRed { - y.isRed = false - x.parent.isRed = true - leftRotate(x.parent) - y = x.parent.right - } - if !y.left.isRed && !y.right.isRed { - y.isRed = true - x = x.parent - } else { - if !y.right.isRed { - y.left.isRed = false - y.isRed = true - rightRotate(y) - y = x.parent.right - } - y.isRed = x.parent.isRed - x.parent.isRed = false - y.right.isRed = false - leftRotate(x.parent) - x = root - } - } else { // symetric left and right - var y = x.parent.left! - if y.isRed { - y.isRed = false - x.parent.isRed = true - rightRotate(x.parent) - y = x.parent.left - } - if !y.right.isRed && !y.left.isRed { - y.isRed = true - x = x.parent + y.order = x.order + x.order = x.left.order + x.right.order + 1 + } + + /** + :name: rightRotate + :description: Rotates the nodes to satisfy the RedBlackTree + balance property. + */ + private mutating func rightRotate(_ y: RedBlackNode) { + let x = y.left! + + y.left = x.right + if sentinel !== x.right { + x.right.parent = y + } + + x.parent = y.parent + + if sentinel === y.parent { + root = x + } else if y === y.parent.right { + y.parent.right = x } else { - if !y.left.isRed { - y.right.isRed = false - y.isRed = true - leftRotate(y) - y = x.parent.left - } - y.isRed = x.parent.isRed - x.parent.isRed = false - y.left.isRed = false - rightRotate(x.parent) - x = root - } - } - } - x.isRed = false - } - - /** - :name: minimum - :description: Finds the minimum keyed node. - - returns: RedBlackNode - */ - private func minimum(_ node: RedBlackNode) -> RedBlackNode { - var x = node - var y = sentinel - while x !== sentinel { - y = x - x = x.left - } - return y - } - - /** - :name: transplant - :description: Swaps two subTrees in the tree. - */ - mutating private func transplant(_ u: RedBlackNode, v: RedBlackNode) { - if u.parent === sentinel { - root = v - } else if u === u.parent.left { - u.parent.left = v - } else { - u.parent.right = v - } - v.parent = u.parent - } - - /** - :name: leftRotate - :description: Rotates the nodes to satisfy the RedBlackTree - balance property. - */ - mutating private func leftRotate(_ x: RedBlackNode) { - let y = x.right! - - x.right = y.left - if sentinel !== y.left { - y.left.parent = x - } - - y.parent = x.parent - - if sentinel === x.parent { - root = y - } else if x === x.parent.left { - x.parent.left = y - } else { - x.parent.right = y - } - - y.left = x - x.parent = y - y.order = x.order - x.order = x.left.order + x.right.order + 1 - } - - /** - :name: rightRotate - :description: Rotates the nodes to satisfy the RedBlackTree - balance property. - */ - mutating private func rightRotate(_ y: RedBlackNode) { - let x = y.left! - - y.left = x.right - if sentinel !== x.right { - x.right.parent = y - } - - x.parent = y.parent - - if sentinel === y.parent { - root = x - } else if y === y.parent.right { - y.parent.right = x - } else { - y.parent.left = x - } - - x.right = y - y.parent = x - x.order = y.order - y.order = y.left.order + y.right.order + 1 - } - - /** - :name: internalFindNodeForKey - :description: Finds a node with a given key value. - - returns: RedBlackNode - */ - private func internalFindNodeForKey(_ key: Key) -> RedBlackNode { - var z = root - while z !== sentinel { - if key == z.key { - return z - } - z = key < z.key as Key ? z.left : z.right - } - return sentinel - } - - /** - :name: internalSelect - :description: Internally searches for a node by the order statistic value. - - returns: RedBlackNode - */ - private func internalSelect(_ x: RedBlackNode, order: Int) -> RedBlackNode { - validateOrder(order) - - let r = x.left.order + 1 - - if order == r { - return x - } else if order < r { - return internalSelect(x.left, order: order) - } - - return internalSelect(x.right, order: order - r) - } - - /** - :name: internalCount - :description: Traverses the Tree while counting number of times a key appears. - */ - private func internalCount(_ key: Key, node: RedBlackNode, count: inout Int) { - if sentinel !== node { - if key == node.key { - count += 1 - } - - internalCount(key, node: node.left, count: &count) - internalCount(key, node: node.right, count: &count) - } - } - - /** - :name: internalUpdateValue - :description: Traverses the Tree and updates all the values that match the key. - */ - private func internalUpdateValue(_ value: Value?, for key: Key, node: RedBlackNode) { - if node !== sentinel { - if key == node.key { - node.value = value - } - - internalUpdateValue(value, for: key, node: node.left) - internalUpdateValue(value, for: key, node: node.right) - } - } - - /** - :name: internalOrder - :description: Traverses the Tree for the internal order statistic of a key. - - returns: Int - */ - private func internalOrder(_ node: RedBlackNode) -> Int { - var x = node - var r: Int = x.left.order + 1 - - while root !== x { - if x.parent.right === x { - r += x.parent.left.order + 1 - } - x = x.parent - } - - return r - } - - /** - :name: validateOrder - :description: Validates the order statistic being within range of 1...n. - */ - private func validateOrder(_ order: Int) { - assert(order > startIndex || order <= endIndex, "[Algorithm Error: Order out of bounds.]") - } - - public static func ==(lhs: RedBlackTree, rhs: RedBlackTree) -> Bool { - return lhs.count == rhs.count && lhs.elementsEqual(rhs, by: { a, b -> Bool in - return a.key == b.key - }) - } - - public static func !=(lhs: RedBlackTree, rhs: RedBlackTree) -> Bool { - return !(lhs == rhs) - } - - public static func +(lhs: RedBlackTree, rhs: RedBlackTree) -> RedBlackTree { - var t = RedBlackTree() - - for (k, v) in lhs { - t.insert(value: v, for: k) - } - - for (k, v) in rhs { - t.insert(value: v, for: k) - } - - return t - } - - public static func +=(lhs: inout RedBlackTree, rhs: RedBlackTree) { - for (k, v) in rhs { - lhs.insert(value: v, for: k) - } - } - - public static func -(lhs: RedBlackTree, rhs: RedBlackTree) -> RedBlackTree { - var t = rhs - - for (k, _) in rhs { - t.removeValue(for: k) - } - - return t - } - - public static func -=(lhs: inout RedBlackTree, rhs: RedBlackTree) { - for (k, _) in rhs { - lhs.removeValue(for: k) - } - } -} + y.parent.left = x + } + + x.right = y + y.parent = x + x.order = y.order + y.order = y.left.order + y.right.order + 1 + } + + /** + :name: internalFindNodeForKey + :description: Finds a node with a given key value. + - returns: RedBlackNode + */ + private func internalFindNodeForKey(_ key: Key) -> RedBlackNode { + var z = root + while z !== sentinel { + if key == z.key { + return z + } + z = key < z.key as Key ? z.left : z.right + } + return sentinel + } + + /** + :name: internalSelect + :description: Internally searches for a node by the order statistic value. + - returns: RedBlackNode + */ + private func internalSelect(_ x: RedBlackNode, order: Int) -> RedBlackNode { + validateOrder(order) + + let r = x.left.order + 1 + + if order == r { + return x + } else if order < r { + return internalSelect(x.left, order: order) + } + + return internalSelect(x.right, order: order - r) + } + + /** + :name: internalCount + :description: Traverses the Tree while counting number of times a key appears. + */ + private func internalCount(_ key: Key, node: RedBlackNode, count: inout Int) { + if sentinel !== node { + if key == node.key { + count += 1 + } + + internalCount(key, node: node.left, count: &count) + internalCount(key, node: node.right, count: &count) + } + } + + /** + :name: internalUpdateValue + :description: Traverses the Tree and updates all the values that match the key. + */ + private func internalUpdateValue(_ value: Value?, for key: Key, node: RedBlackNode) { + if node !== sentinel { + if key == node.key { + node.value = value + } + + internalUpdateValue(value, for: key, node: node.left) + internalUpdateValue(value, for: key, node: node.right) + } + } + + /** + :name: internalOrder + :description: Traverses the Tree for the internal order statistic of a key. + - returns: Int + */ + private func internalOrder(_ node: RedBlackNode) -> Int { + var x = node + var r: Int = x.left.order + 1 + + while root !== x { + if x.parent.right === x { + r += x.parent.left.order + 1 + } + x = x.parent + } + return r + } + + /** + :name: validateOrder + :description: Validates the order statistic being within range of 1...n. + */ + private func validateOrder(_ order: Int) { + assert(order > startIndex || order <= endIndex, "[Algorithm Error: Order out of bounds.]") + } + + public static func == (lhs: RedBlackTree, rhs: RedBlackTree) -> Bool { + return lhs.count == rhs.count && lhs.elementsEqual(rhs, by: { a, b -> Bool in + a.key == b.key + }) + } + + public static func != (lhs: RedBlackTree, rhs: RedBlackTree) -> Bool { + return !(lhs == rhs) + } + public static func + (lhs: RedBlackTree, rhs: RedBlackTree) -> RedBlackTree { + var t = RedBlackTree() + + for (k, v) in lhs { + t.insert(value: v, for: k) + } + + for (k, v) in rhs { + t.insert(value: v, for: k) + } + + return t + } + + public static func += (lhs: inout RedBlackTree, rhs: RedBlackTree) { + for (k, v) in rhs { + lhs.insert(value: v, for: k) + } + } + + public static func - (_: RedBlackTree, rhs: RedBlackTree) -> RedBlackTree { + var t = rhs + + for (k, _) in rhs { + t.removeValue(for: k) + } + + return t + } + + public static func -= (lhs: inout RedBlackTree, rhs: RedBlackTree) { + for (k, _) in rhs { + lhs.removeValue(for: k) + } + } +} diff --git a/Sources/SortedDictionary.swift b/Sources/SortedDictionary.swift index a7e86f3..05c318f 100644 --- a/Sources/SortedDictionary.swift +++ b/Sources/SortedDictionary.swift @@ -24,363 +24,362 @@ */ public struct SortedDictionary: Probable, Collection, BidirectionalCollection, Equatable, CustomStringConvertible { - public typealias Element = RedBlackTree.Element - public typealias ProbableElement = RedBlackTree.ProbableElement - - /// Returns the position immediately after the given index. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - /// - Returns: The index value immediately after `i`. - public func index(after i: Int) -> Int { - return i + 1 - } - - public func index(before i: Int) -> Int { - return i - 1 - } - - public typealias Iterator = AnyIterator - - /// Total number of elements within the RedBlackTree - public internal(set) var count = 0 - - /// Internal storage of (key, value) pairs. - internal var tree: RedBlackTree - - /// Get the data as a Dictionary. - public var asDictionary: [Key: Value?] { - var d = [Key: Value?]() - for (k, v) in self { - d[k] = v - } - return d - } - - /// Conforms to the Printable Protocol. Outputs the - public var description: String { - return tree.description - } - - /// Conforms to the Collection Protocol. - public var startIndex: Int { - return 0 - } - - /// Conforms to the Collection Protocol. - public var endIndex: Int { - return count - } - - /// Retrieves an Array of the key values in order. - public var keys: [Key] { - return tree.keys - } - - /// Retrieves an Array of the values that are sorted based - public var values: [Value] { - return tree.values - } - - /// Initializer. - public init() { - tree = RedBlackTree(uniqueKeys: true) - } - - /** - Initializes with a given list of elements. - - Parameter elements: A list of (key, value) pairs. - */ - public init(elements: (Key, Value?)...) { - self.init(elements: elements) - } - - /** - Initializes with a given Array of elements. - - Parameter elements: An Array of (key, value) pairs. - */ - public init(elements: [(Key, Value?)]) { - self.init() - insert(elements) - } - - fileprivate init(tree : RedBlackTree) { - self.init() - self.tree = tree - } - - public func _customIndexOfEquatableElement(_ element: Key) -> Int?? { - return nil - } - - public func makeIterator() -> Iterator { - var i = indices.makeIterator() - return AnyIterator { i.next().map { self[$0] } } - } - - /** - Retrieves the total count of instances for the given - keys. - - Parameter of keys: A list of Key types. - - Returns: An Int. - */ - public func count(of keys: Key...) -> Int { - return count(of: keys) - } - - /** - Retrieves the total count of instances for the given - keys. - - Parameter of keys: An Array of Key types. - - Returns: An Int. - */ - public func count(of keys: [Key]) -> Int { - return tree.count(of: keys) - } - - /** - Calculates the probability of the given keys. - - Parameter of keys: A list of Key types. - - Returns: A Double. - */ - public func probability(of keys: Key...) -> Double { - return probability(of: keys) - } - - /** - Calculates the probability of the given keys. - - Parameter of keys: An Array of Key types. - - Returns: A Double. - */ - public func probability(of keys: [Key]) -> Double { - return tree.probability(of: keys) - } - - /** - Calculates the probability using a block. - - Parameter execute block: A block function to execute. - - Returns: A Double. - */ - public func probability(execute block: (Key, Value?) -> Bool) -> Double { - return tree.probability(execute: block) - } - - /** - The expected value of given keys based on a number of trials. - - Parameter trials: An Int. - - Parameter for keys: A list of Elements. - - Returns: A Double. - */ - public func expectedValue(trials: Int, for keys: Key...) -> Double { - return expectedValue(trials: trials, for: keys) - } - - /** - The expected value of given keys based on a number of trials. - - Parameter trials: An Int. - - Parameter for keys: A list of Elements. - - Returns: A Double. - */ - public func expectedValue(trials: Int, for keys: [Key]) -> Double { - return tree.expectedValue(trials: trials, for: keys) - } - - /** - Property key mapping. If the key type is a String, this feature - allows access like a Dictionary. - - Parameter key: A Key type. - - Returns: An optional Value type. - */ - public subscript(key: Key) -> Value? { - get { - return tree[key] - } - set(value) { - tree[key] = value - count = tree.count - } - } - - public subscript(position: Int) -> Key { - return self[position].key - } - - /** - Allows Array like access of the index. Items are kept in order, - so when iterating through the items, they are returned in their - ordered form. - - Parameter index: An Int. - - Returns: A (key: Key, value: Value?) - */ - public subscript(index: Int) -> (key: Key, value: Value?) { - get { - return tree[index] - } - set(value) { - tree[index] = value - count = tree.count - } - } - - /** - Returns the Index of a given member, or -1 if the member is not - present. - - Parameter of key: A Key type. - - Returns: An Int. - */ - public func index(of key: Key) -> Int { - return tree.index(of: key) - } - - /** - Insert a key / value pair. - - Parameter value: An optional Value type. - - Parameter for key: A Key type. - - Returns: A boolean of the result, true if inserted, false - otherwise. - */ - @discardableResult - mutating public func insert(value: Value?, for key: Key) -> Bool { - let result = tree.insert(value: value, for: key) - count = tree.count - return result - } - - /** - Inserts a list of key / value pairs. - - Parameter elements: A list of (Key, Value?) tuples. - */ - mutating public func insert(_ elements: (Key, Value?)...) { - insert(elements) - } - - /** - Inserts an Array of key / value pairs. - - Parameter elements: An Array of (Key, Value?) tuples. - */ - mutating public func insert(_ elements: [(Key, Value?)]) { - tree.insert(elements) - count = tree.count - } - - /** - Removes key / value pairs based on the keys given. - - Parameter for keys: A list of Key types. - */ - mutating public func removeValue(for keys: Key...) { - removeValue(for: keys) - } - - /** - Removes key / value pairs based on the keys given. - - Parameter for keys: An Array of Key types. - */ - mutating public func removeValue(for keys: [Key]) { - tree.removeValue(for: keys) - count = tree.count - } - - /// Removes all key / value pairs. - mutating public func removeAll() { - tree.removeAll() - count = tree.count - } - - /** - Updates a vlue for the given key. - - Parameter value: An optional Value type. - - Parameter for key: A Key type. - */ - mutating public func update(value: Value?, for key: Key) { - tree.update(value: value, for: key) - } - - /** - Finds the value for a given key. - - Parameter for key: A Key type. - - Returns: An optional Value type. - */ - public func findValue(for key: Key) -> Value? { - return tree.findValue(for: key) - } - - /** - Finds the value for a key which is less or equal given. - - Parameter for key: A Key type. - - Returns: An optional Value type. - */ - public func findLowerEntry(for key: Key) -> Value? { - return tree.findLowerValue(for: key) - } - - /** - Finds the value for a key which is larger or equal given. - - Parameter for key: A Key type. - - Returns: An optional Value type. - */ - public func findCeilingEntry(for key: Key) -> Value? { - return tree.findCeilingValue(for: key) - } - - /** - Searches for given keys in the SortedDictionary. - - Parameter for keys: A list of Key types. - - Returns: A SortedDictionary. - */ - public func search(for keys: Key...) -> SortedDictionary { - return search(for: keys) - } - - /** - Searches for given keys in the SortedDictionary. - - Parameter for keys: An Array of Key types. - - Returns: A SortedDictionary. - */ - public func search(for keys: [Key]) -> SortedDictionary { - var d = SortedDictionary() - for key in keys { - traverse(for: key, node: tree.root, dictionary: &d) - } - return d - } - - /** - Traverses the SortedDictionary, looking for a key matches. - - Parameter for key: A Key type. - - Parameter node: A RedBlackNode. - - Parameter dictionary: A SortedDictionary to map the results too. - */ - internal func traverse(for key: Key, node: RedBlackNode, dictionary: inout SortedDictionary) { - guard tree.sentinel !== node else { - return - } - - if key == node.key { - dictionary.insert(value: node.value, for: key) - } - - traverse(for: key, node: node.left, dictionary: &dictionary) - traverse(for: key, node: node.right, dictionary: &dictionary) - } - - static public func ==(lhs: SortedDictionary, rhs: SortedDictionary) -> Bool { - return lhs.tree == rhs.tree - } - - static public func +(lhs: SortedDictionary, rhs: SortedDictionary) -> SortedDictionary { - return SortedDictionary(tree : lhs.tree + rhs.tree) - } - - static public func +=(lhs: inout SortedDictionary, rhs: SortedDictionary) { - lhs.tree += rhs.tree - } - - static public func -(lhs: SortedDictionary, rhs: SortedDictionary) -> SortedDictionary { - return SortedDictionary(tree : lhs.tree - rhs.tree) - } - - static public func -=(lhs: inout SortedDictionary, rhs: SortedDictionary) { - lhs.tree -= rhs.tree - } -} + public typealias Element = RedBlackTree.Element + public typealias ProbableElement = RedBlackTree.ProbableElement + + /// Returns the position immediately after the given index. + /// + /// - Parameter i: A valid index of the collection. `i` must be less than + /// `endIndex`. + /// - Returns: The index value immediately after `i`. + public func index(after i: Int) -> Int { + return i + 1 + } + + public func index(before i: Int) -> Int { + return i - 1 + } + + public typealias Iterator = AnyIterator + + /// Total number of elements within the RedBlackTree + public internal(set) var count = 0 + + /// Internal storage of (key, value) pairs. + internal var tree: RedBlackTree + + /// Get the data as a Dictionary. + public var asDictionary: [Key: Value?] { + var d = [Key: Value?]() + for (k, v) in self { + d[k] = v + } + return d + } + + /// Conforms to the Printable Protocol. Outputs the + public var description: String { + return tree.description + } + + /// Conforms to the Collection Protocol. + public var startIndex: Int { + return 0 + } + + /// Conforms to the Collection Protocol. + public var endIndex: Int { + return count + } + + /// Retrieves an Array of the key values in order. + public var keys: [Key] { + return tree.keys + } + + /// Retrieves an Array of the values that are sorted based + public var values: [Value] { + return tree.values + } + + /// Initializer. + public init() { + tree = RedBlackTree(uniqueKeys: true) + } + + /** + Initializes with a given list of elements. + - Parameter elements: A list of (key, value) pairs. + */ + public init(elements: (Key, Value?)...) { + self.init(elements: elements) + } + + /** + Initializes with a given Array of elements. + - Parameter elements: An Array of (key, value) pairs. + */ + public init(elements: [(Key, Value?)]) { + self.init() + insert(elements) + } + + fileprivate init(tree: RedBlackTree) { + self.init() + self.tree = tree + } + + public func _customIndexOfEquatableElement(_: Key) -> Int?? { + return nil + } + + public func makeIterator() -> Iterator { + var i = indices.makeIterator() + return AnyIterator { i.next().map { self[$0] } } + } + + /** + Retrieves the total count of instances for the given + keys. + - Parameter of keys: A list of Key types. + - Returns: An Int. + */ + public func count(of keys: Key...) -> Int { + return count(of: keys) + } + + /** + Retrieves the total count of instances for the given + keys. + - Parameter of keys: An Array of Key types. + - Returns: An Int. + */ + public func count(of keys: [Key]) -> Int { + return tree.count(of: keys) + } + + /** + Calculates the probability of the given keys. + - Parameter of keys: A list of Key types. + - Returns: A Double. + */ + public func probability(of keys: Key...) -> Double { + return probability(of: keys) + } + + /** + Calculates the probability of the given keys. + - Parameter of keys: An Array of Key types. + - Returns: A Double. + */ + public func probability(of keys: [Key]) -> Double { + return tree.probability(of: keys) + } + + /** + Calculates the probability using a block. + - Parameter execute block: A block function to execute. + - Returns: A Double. + */ + public func probability(execute block: (Key, Value?) -> Bool) -> Double { + return tree.probability(execute: block) + } + + /** + The expected value of given keys based on a number of trials. + - Parameter trials: An Int. + - Parameter for keys: A list of Elements. + - Returns: A Double. + */ + public func expectedValue(trials: Int, for keys: Key...) -> Double { + return expectedValue(trials: trials, for: keys) + } + + /** + The expected value of given keys based on a number of trials. + - Parameter trials: An Int. + - Parameter for keys: A list of Elements. + - Returns: A Double. + */ + public func expectedValue(trials: Int, for keys: [Key]) -> Double { + return tree.expectedValue(trials: trials, for: keys) + } + /** + Property key mapping. If the key type is a String, this feature + allows access like a Dictionary. + - Parameter key: A Key type. + - Returns: An optional Value type. + */ + public subscript(key: Key) -> Value? { + get { + return tree[key] + } + set(value) { + tree[key] = value + count = tree.count + } + } + + public subscript(position: Int) -> Key { + return self[position].key + } + + /** + Allows Array like access of the index. Items are kept in order, + so when iterating through the items, they are returned in their + ordered form. + - Parameter index: An Int. + - Returns: A (key: Key, value: Value?) + */ + public subscript(index: Int) -> (key: Key, value: Value?) { + get { + return tree[index] + } + set(value) { + tree[index] = value + count = tree.count + } + } + + /** + Returns the Index of a given member, or -1 if the member is not + present. + - Parameter of key: A Key type. + - Returns: An Int. + */ + public func index(of key: Key) -> Int { + return tree.index(of: key) + } + + /** + Insert a key / value pair. + - Parameter value: An optional Value type. + - Parameter for key: A Key type. + - Returns: A boolean of the result, true if inserted, false + otherwise. + */ + @discardableResult + public mutating func insert(value: Value?, for key: Key) -> Bool { + let result = tree.insert(value: value, for: key) + count = tree.count + return result + } + + /** + Inserts a list of key / value pairs. + - Parameter elements: A list of (Key, Value?) tuples. + */ + public mutating func insert(_ elements: (Key, Value?)...) { + insert(elements) + } + + /** + Inserts an Array of key / value pairs. + - Parameter elements: An Array of (Key, Value?) tuples. + */ + public mutating func insert(_ elements: [(Key, Value?)]) { + tree.insert(elements) + count = tree.count + } + + /** + Removes key / value pairs based on the keys given. + - Parameter for keys: A list of Key types. + */ + public mutating func removeValue(for keys: Key...) { + removeValue(for: keys) + } + + /** + Removes key / value pairs based on the keys given. + - Parameter for keys: An Array of Key types. + */ + public mutating func removeValue(for keys: [Key]) { + tree.removeValue(for: keys) + count = tree.count + } + + /// Removes all key / value pairs. + public mutating func removeAll() { + tree.removeAll() + count = tree.count + } + + /** + Updates a vlue for the given key. + - Parameter value: An optional Value type. + - Parameter for key: A Key type. + */ + public mutating func update(value: Value?, for key: Key) { + tree.update(value: value, for: key) + } + + /** + Finds the value for a given key. + - Parameter for key: A Key type. + - Returns: An optional Value type. + */ + public func findValue(for key: Key) -> Value? { + return tree.findValue(for: key) + } + + /** + Finds the value for a key which is less or equal given. + - Parameter for key: A Key type. + - Returns: An optional Value type. + */ + public func findLowerEntry(for key: Key) -> Value? { + return tree.findLowerValue(for: key) + } + + /** + Finds the value for a key which is larger or equal given. + - Parameter for key: A Key type. + - Returns: An optional Value type. + */ + public func findCeilingEntry(for key: Key) -> Value? { + return tree.findCeilingValue(for: key) + } + + /** + Searches for given keys in the SortedDictionary. + - Parameter for keys: A list of Key types. + - Returns: A SortedDictionary. + */ + public func search(for keys: Key...) -> SortedDictionary { + return search(for: keys) + } + + /** + Searches for given keys in the SortedDictionary. + - Parameter for keys: An Array of Key types. + - Returns: A SortedDictionary. + */ + public func search(for keys: [Key]) -> SortedDictionary { + var d = SortedDictionary() + for key in keys { + traverse(for: key, node: tree.root, dictionary: &d) + } + return d + } + + /** + Traverses the SortedDictionary, looking for a key matches. + - Parameter for key: A Key type. + - Parameter node: A RedBlackNode. + - Parameter dictionary: A SortedDictionary to map the results too. + */ + internal func traverse(for key: Key, node: RedBlackNode, dictionary: inout SortedDictionary) { + guard tree.sentinel !== node else { + return + } + + if key == node.key { + dictionary.insert(value: node.value, for: key) + } + + traverse(for: key, node: node.left, dictionary: &dictionary) + traverse(for: key, node: node.right, dictionary: &dictionary) + } + + public static func == (lhs: SortedDictionary, rhs: SortedDictionary) -> Bool { + return lhs.tree == rhs.tree + } + + public static func + (lhs: SortedDictionary, rhs: SortedDictionary) -> SortedDictionary { + return SortedDictionary(tree: lhs.tree + rhs.tree) + } + + public static func += (lhs: inout SortedDictionary, rhs: SortedDictionary) { + lhs.tree += rhs.tree + } + + public static func - (lhs: SortedDictionary, rhs: SortedDictionary) -> SortedDictionary { + return SortedDictionary(tree: lhs.tree - rhs.tree) + } + + public static func -= (lhs: inout SortedDictionary, rhs: SortedDictionary) { + lhs.tree -= rhs.tree + } +} diff --git a/Sources/SortedMultiDictionary.swift b/Sources/SortedMultiDictionary.swift index b2ccc4c..9f3ff47 100644 --- a/Sources/SortedMultiDictionary.swift +++ b/Sources/SortedMultiDictionary.swift @@ -24,379 +24,379 @@ */ public struct SortedMultiDictionary: Probable, Collection, Equatable, CustomStringConvertible where Key: Hashable { - public typealias Element = RedBlackTree.Element - - /// Returns the position immediately after the given index. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - /// - Returns: The index value immediately after `i`. - public func index(after i: Int) -> Int { - return i < endIndex ? i + 1 : 0 - } - - public typealias Iterator = AnyIterator<(key: Key, value: Value?)> - - /// Total number of elements within the RedBlackTree - public internal(set) var count = 0 - - /// Internal storage of (key, value) pairs. - internal var tree: RedBlackTree - - /// Get the data as a Dictionary. - public var asDictionary: [Key: Value?] { - var d = [Key: Value?]() - - for (k, v) in self { - d[k] = v - } - - return d - } - - /// Conforms to the Printable Protocol. Outputs the - public var description: String { - return tree.description - } - - /// Get the first (key, value) pair. - public var first: (key: Key, value: Value?)? { - return tree.first - } - - /// Get the last (key, value) pair. - public var last: (key: Key, value: Value?)? { - return tree.last - } - - /// A boolean of whether the SortedMultiDictionary is empty. - public var isEmpty: Bool { - return 0 == count - } - - /// Conforms to the Collection Protocol. - public var startIndex: Int { - return 0 - } - - /// Conforms to the Collection Protocol. - public var endIndex: Int { - return count - } - - /// Retrieves an Array of the key values in order. - public var keys: [Key] { - return tree.keys - } - - /// Retrieves an Array of the values that are sorted based - public var values: [Value] { - return tree.values - } - - /// Initializer. - public init() { - tree = RedBlackTree(uniqueKeys: false) - } - - /** - Initializes with a given list of elements. - - Parameter elements: A list of (key, value) pairs. - */ - public init(elements: (Key, Value?)...) { - self.init(elements: elements) - } - - /** - Initializes with a given Array of elements. - - Parameter elements: An Array of (key, value) pairs. - */ - public init(elements: [(Key, Value?)]) { - self.init() - insert(elements) - } - - public func _customIndexOfEquatableElement(_ element: Key) -> Int?? { - return nil - } - - public func makeIterator() -> SortedMultiDictionary.Iterator { - var i = indices.makeIterator() - return AnyIterator { i.next().map { self[$0] } } - } - - /** - Retrieves the total count of instances for the given - keys. - - Parameter of keys: A list of Key types. - - Returns: An Int. - */ - public func count(of keys: Key...) -> Int { - return count(of: keys) - } - - /** - Retrieves the total count of instances for the given - keys. - - Parameter of keys: An Array of Key types. - - Returns: An Int. - */ - public func count(of keys: [Key]) -> Int { - return tree.count(of: keys) - } - - /** - Calculates the probability of the given keys. - - Parameter of keys: A list of Key types. - - Returns: A Double. - */ - public func probability(of keys: Key...) -> Double { - return probability(of: keys) - } - - /** - Calculates the probability of the given keys. - - Parameter of keys: An Array of Key types. - - Returns: A Double. - */ - public func probability(of keys: [Key]) -> Double { - return tree.probability(of: keys) - } - - /** - Calculates the probability using a block. - - Parameter execute block: A block function to execute. - - Returns: A Double. - */ - public func probability(execute block: (Key, Value?) -> Bool) -> Double { - return tree.probability(execute: block) - } - - /** - The expected value of given keys based on a number of trials. - - Parameter trials: An Int. - - Parameter for keys: A list of Elements. - - Returns: A Double. - */ - public func expectedValue(trials: Int, for keys: Key...) -> Double { - return expectedValue(trials: trials, for: keys) - } - - /** - The expected value of given keys based on a number of trials. - - Parameter trials: An Int. - - Parameter for keys: A list of Elements. - - Returns: A Double. - */ - public func expectedValue(trials: Int, for keys: [Key]) -> Double { - return tree.expectedValue(trials: trials, for: keys) - } - - /** - Property key mapping. If the key type is a String, this feature - allows access like a Dictionary. - - Parameter key: A Key type. - - Returns: An optional Value type. - */ - public subscript(key: Key) -> Value? { - get { - return tree[key] - } - set(value) { - tree[key] = value - count = tree.count - } - } - - /** - Returns the Key value at a given position. - - Parameter position: An Int. - - Returns: A Key. - */ - public subscript(position: Int) -> Key { - return tree[position] - } - - /** - Allows Array like access of the index. Items are kept in order, - so when iterating through the items, they are returned in their - ordered form. - - Parameter index: An Int. - - Returns: A (key: Key, value: Value?) - */ - public subscript(index: Int) -> (key: Key, value: Value?) { - get { - return tree[index] - } - set(value) { - tree[index] = value - count = tree.count - } - } - - /** - Returns the Index of a given member, or -1 if the member is not - present. - - Parameter of key: A Key type. - - Returns: An Int. - */ - public func index(of key: Key) -> Int { - return tree.index(of: key) - } - - /** - Insert a key / value pair. - - Parameter value: An optional Value type. - - Parameter for key: A Key type. - - Returns: A boolean of the result, true if inserted, false - otherwise. - */ - @discardableResult - mutating public func insert(value: Value?, for key: Key) -> Bool { - let result = tree.insert(value: value, for: key) - count = tree.count - return result - } - - /** - Inserts a list of key / value pairs. - - Parameter elements: A list of (Key, Value?) tuples. - */ - mutating public func insert(_ elements: (Key, Value?)...) { - insert(elements) - } - - /** - Inserts an Array of key / value pairs. - - Parameter elements: An Array of (Key, Value?) tuples. - */ - mutating public func insert(_ elements: [(Key, Value?)]) { - tree.insert(elements) - count = tree.count - } - - /** - Removes key / value pairs based on the keys given. - - Parameter for keys: A list of Key types. - */ - mutating public func removeValue(for keys: Key...) { - removeValue(for: keys) - } - - /** - Removes key / value pairs based on the keys given. - - Parameter for keys: An Array of Key types. - */ - mutating public func removeValue(for keys: [Key]) { - tree.removeValue(for: keys) - count = tree.count - } - - /// Removes all key / value pairs. - mutating public func removeAll() { - tree.removeAll() - count = tree.count - } - - /** - Updates a vlue for the given key. - - Parameter value: An optional Value type. - - Parameter for key: A Key type. - */ - mutating public func update(value: Value?, for key: Key) { - tree.update(value: value, for: key) - } - - /** - Finds the value for a given key. - - Parameter for key: A Key type. - - Returns: An optional Value type. - */ - public func findValue(for key: Key) -> Value? { - return tree.findValue(for: key) - } - - /** - Searches for given keys in the SortedMultiDictionary. - - Parameter for keys: A list of Key types. - - Returns: A SortedMultiDictionary. - */ - public func search(for keys: Key...) -> SortedMultiDictionary { - return search(for: keys) - } - - /** - Searches for given keys in the SortedMultiDictionary. - - Parameter for keys: An Array of Key types. - - Returns: A SortedMultiDictionary. - */ - public func search(for keys: [Key]) -> SortedMultiDictionary { - var d = SortedMultiDictionary() - for key in keys { - traverse(for: key, node: tree.root, dictionary: &d) - } - return d - } - - /** - Traverses the SortedMultiDictionary, looking for a key matches. - - Parameter for key: A Key type. - - Parameter node: A RedBlackNode. - - Parameter dictionary: A SortedMultiDictionary to map the results too. - */ - internal func traverse(for key: Key, node: RedBlackNode, dictionary: inout SortedMultiDictionary) { - guard tree.sentinel !== node else { - return - } - - if key == node.key { - dictionary.insert(value: node.value, for: key) - } - - traverse(for: key, node: node.left, dictionary: &dictionary) - traverse(for: key, node: node.right, dictionary: &dictionary) - } + public typealias Element = RedBlackTree.Element + + /// Returns the position immediately after the given index. + /// + /// - Parameter i: A valid index of the collection. `i` must be less than + /// `endIndex`. + /// - Returns: The index value immediately after `i`. + public func index(after i: Int) -> Int { + return i < endIndex ? i + 1 : 0 + } + + public typealias Iterator = AnyIterator<(key: Key, value: Value?)> + + /// Total number of elements within the RedBlackTree + public internal(set) var count = 0 + + /// Internal storage of (key, value) pairs. + internal var tree: RedBlackTree + + /// Get the data as a Dictionary. + public var asDictionary: [Key: Value?] { + var d = [Key: Value?]() + + for (k, v) in self { + d[k] = v + } + + return d + } + + /// Conforms to the Printable Protocol. Outputs the + public var description: String { + return tree.description + } + + /// Get the first (key, value) pair. + public var first: (key: Key, value: Value?)? { + return tree.first + } + + /// Get the last (key, value) pair. + public var last: (key: Key, value: Value?)? { + return tree.last + } + + /// A boolean of whether the SortedMultiDictionary is empty. + public var isEmpty: Bool { + return count == 0 + } + + /// Conforms to the Collection Protocol. + public var startIndex: Int { + return 0 + } + + /// Conforms to the Collection Protocol. + public var endIndex: Int { + return count + } + + /// Retrieves an Array of the key values in order. + public var keys: [Key] { + return tree.keys + } + + /// Retrieves an Array of the values that are sorted based + public var values: [Value] { + return tree.values + } + + /// Initializer. + public init() { + tree = RedBlackTree(uniqueKeys: false) + } + + /** + Initializes with a given list of elements. + - Parameter elements: A list of (key, value) pairs. + */ + public init(elements: (Key, Value?)...) { + self.init(elements: elements) + } + + /** + Initializes with a given Array of elements. + - Parameter elements: An Array of (key, value) pairs. + */ + public init(elements: [(Key, Value?)]) { + self.init() + insert(elements) + } + + public func _customIndexOfEquatableElement(_: Key) -> Int?? { + return nil + } + + public func makeIterator() -> SortedMultiDictionary.Iterator { + var i = indices.makeIterator() + return AnyIterator { i.next().map { self[$0] } } + } + + /** + Retrieves the total count of instances for the given + keys. + - Parameter of keys: A list of Key types. + - Returns: An Int. + */ + public func count(of keys: Key...) -> Int { + return count(of: keys) + } + + /** + Retrieves the total count of instances for the given + keys. + - Parameter of keys: An Array of Key types. + - Returns: An Int. + */ + public func count(of keys: [Key]) -> Int { + return tree.count(of: keys) + } + + /** + Calculates the probability of the given keys. + - Parameter of keys: A list of Key types. + - Returns: A Double. + */ + public func probability(of keys: Key...) -> Double { + return probability(of: keys) + } + + /** + Calculates the probability of the given keys. + - Parameter of keys: An Array of Key types. + - Returns: A Double. + */ + public func probability(of keys: [Key]) -> Double { + return tree.probability(of: keys) + } + + /** + Calculates the probability using a block. + - Parameter execute block: A block function to execute. + - Returns: A Double. + */ + public func probability(execute block: (Key, Value?) -> Bool) -> Double { + return tree.probability(execute: block) + } + + /** + The expected value of given keys based on a number of trials. + - Parameter trials: An Int. + - Parameter for keys: A list of Elements. + - Returns: A Double. + */ + public func expectedValue(trials: Int, for keys: Key...) -> Double { + return expectedValue(trials: trials, for: keys) + } + + /** + The expected value of given keys based on a number of trials. + - Parameter trials: An Int. + - Parameter for keys: A list of Elements. + - Returns: A Double. + */ + public func expectedValue(trials: Int, for keys: [Key]) -> Double { + return tree.expectedValue(trials: trials, for: keys) + } + + /** + Property key mapping. If the key type is a String, this feature + allows access like a Dictionary. + - Parameter key: A Key type. + - Returns: An optional Value type. + */ + public subscript(key: Key) -> Value? { + get { + return tree[key] + } + set(value) { + tree[key] = value + count = tree.count + } + } + + /** + Returns the Key value at a given position. + - Parameter position: An Int. + - Returns: A Key. + */ + public subscript(position: Int) -> Key { + return tree[position] + } + + /** + Allows Array like access of the index. Items are kept in order, + so when iterating through the items, they are returned in their + ordered form. + - Parameter index: An Int. + - Returns: A (key: Key, value: Value?) + */ + public subscript(index: Int) -> (key: Key, value: Value?) { + get { + return tree[index] + } + set(value) { + tree[index] = value + count = tree.count + } + } + + /** + Returns the Index of a given member, or -1 if the member is not + present. + - Parameter of key: A Key type. + - Returns: An Int. + */ + public func index(of key: Key) -> Int { + return tree.index(of: key) + } + + /** + Insert a key / value pair. + - Parameter value: An optional Value type. + - Parameter for key: A Key type. + - Returns: A boolean of the result, true if inserted, false + otherwise. + */ + @discardableResult + public mutating func insert(value: Value?, for key: Key) -> Bool { + let result = tree.insert(value: value, for: key) + count = tree.count + return result + } + + /** + Inserts a list of key / value pairs. + - Parameter elements: A list of (Key, Value?) tuples. + */ + public mutating func insert(_ elements: (Key, Value?)...) { + insert(elements) + } + + /** + Inserts an Array of key / value pairs. + - Parameter elements: An Array of (Key, Value?) tuples. + */ + public mutating func insert(_ elements: [(Key, Value?)]) { + tree.insert(elements) + count = tree.count + } + + /** + Removes key / value pairs based on the keys given. + - Parameter for keys: A list of Key types. + */ + public mutating func removeValue(for keys: Key...) { + removeValue(for: keys) + } + + /** + Removes key / value pairs based on the keys given. + - Parameter for keys: An Array of Key types. + */ + public mutating func removeValue(for keys: [Key]) { + tree.removeValue(for: keys) + count = tree.count + } + + /// Removes all key / value pairs. + public mutating func removeAll() { + tree.removeAll() + count = tree.count + } + + /** + Updates a vlue for the given key. + - Parameter value: An optional Value type. + - Parameter for key: A Key type. + */ + public mutating func update(value: Value?, for key: Key) { + tree.update(value: value, for: key) + } + + /** + Finds the value for a given key. + - Parameter for key: A Key type. + - Returns: An optional Value type. + */ + public func findValue(for key: Key) -> Value? { + return tree.findValue(for: key) + } + + /** + Searches for given keys in the SortedMultiDictionary. + - Parameter for keys: A list of Key types. + - Returns: A SortedMultiDictionary. + */ + public func search(for keys: Key...) -> SortedMultiDictionary { + return search(for: keys) + } + + /** + Searches for given keys in the SortedMultiDictionary. + - Parameter for keys: An Array of Key types. + - Returns: A SortedMultiDictionary. + */ + public func search(for keys: [Key]) -> SortedMultiDictionary { + var d = SortedMultiDictionary() + for key in keys { + traverse(for: key, node: tree.root, dictionary: &d) + } + return d + } + + /** + Traverses the SortedMultiDictionary, looking for a key matches. + - Parameter for key: A Key type. + - Parameter node: A RedBlackNode. + - Parameter dictionary: A SortedMultiDictionary to map the results too. + */ + internal func traverse(for key: Key, node: RedBlackNode, dictionary: inout SortedMultiDictionary) { + guard tree.sentinel !== node else { + return + } + + if key == node.key { + dictionary.insert(value: node.value, for: key) + } + + traverse(for: key, node: node.left, dictionary: &dictionary) + traverse(for: key, node: node.right, dictionary: &dictionary) + } } -public func ==(lhs: SortedMultiDictionary, rhs: SortedMultiDictionary) -> Bool { - if lhs.count != rhs.count { - return false - } - for i in 0..(lhs: SortedMultiDictionary, rhs: SortedMultiDictionary) -> Bool { + if lhs.count != rhs.count { + return false + } + for i in 0 ..< lhs.count { + if lhs[i].key != rhs[i].key { + return false + } } - } - return true + return true } -public func !=(lhs: SortedMultiDictionary, rhs: SortedMultiDictionary) -> Bool { - return !(lhs == rhs) +public func != (lhs: SortedMultiDictionary, rhs: SortedMultiDictionary) -> Bool { + return !(lhs == rhs) } -public func +(lhs: SortedMultiDictionary, rhs: SortedMultiDictionary) -> SortedMultiDictionary { - var t = SortedMultiDictionary() - for (k, v) in lhs { - t.insert(value: v, for: k) - } - for (k, v) in rhs { - t.insert(value: v, for: k) - } - return t +public func + (lhs: SortedMultiDictionary, rhs: SortedMultiDictionary) -> SortedMultiDictionary { + var t = SortedMultiDictionary() + for (k, v) in lhs { + t.insert(value: v, for: k) + } + for (k, v) in rhs { + t.insert(value: v, for: k) + } + return t } -public func +=(lhs: inout SortedMultiDictionary, rhs: SortedMultiDictionary) { - for (k, v) in rhs { - lhs.insert(value: v, for: k) - } +public func += (lhs: inout SortedMultiDictionary, rhs: SortedMultiDictionary) { + for (k, v) in rhs { + lhs.insert(value: v, for: k) + } } -public func -(lhs: SortedMultiDictionary, rhs: SortedMultiDictionary) -> SortedMultiDictionary { - var t = lhs - t.removeValue(for: rhs.keys) - return t +public func - (lhs: SortedMultiDictionary, rhs: SortedMultiDictionary) -> SortedMultiDictionary { + var t = lhs + t.removeValue(for: rhs.keys) + return t } -public func -=(lhs: inout SortedMultiDictionary, rhs: SortedMultiDictionary) { - lhs.removeValue(for: rhs.keys) +public func -= (lhs: inout SortedMultiDictionary, rhs: SortedMultiDictionary) { + lhs.removeValue(for: rhs.keys) } diff --git a/Sources/SortedMultiSet.swift b/Sources/SortedMultiSet.swift index a2d9b7e..ab6aa03 100644 --- a/Sources/SortedMultiSet.swift +++ b/Sources/SortedMultiSet.swift @@ -24,640 +24,639 @@ */ public struct SortedMultiSet: Probable, Collection, Equatable, CustomStringConvertible where T: Hashable { - public typealias Element = T - - /// Returns the position immediately after the given index. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - /// - Returns: The index value immediately after `i`. - public func index(after i: Int) -> Int { - return i < endIndex ? i + 1 : 0 - } - - public typealias Iterator = AnyIterator - - /** - Total number of elements within the RedBlackTree - */ - public internal(set) var count = 0 - - /** - :name: tree - :description: Internal storage of elements. - - returns: RedBlackTree - */ - internal var tree: RedBlackTree - - /** - :name: asArray - */ - public var asArray: [Element] { - var a = [Element]() - for x in self { - a.append(x) - } - return a - } - - /** - :name: description - :description: Conforms to the Printable Protocol. Outputs the - data in the SortedMultiSet in a readable format. - - returns: String - */ - public var description: String { - return "[" + map { "\($0)" }.joined(separator: ", ") + "]" - } - - /** - :name: first - :description: Get the first node value in the tree, this is - the first node based on the order of keys where - k1 <= k2 <= K3 ... <= Kn - - returns: Element? - */ - public var first: Element? { - return tree.first?.value - } - - /** - :name: last - :description: Get the last node value in the tree, this is - the last node based on the order of keys where - k1 <= k2 <= K3 ... <= Kn - - returns: Element? - */ - public var last: Element? { - return tree.last?.value - } - - /** - :name: isEmpty - :description: A boolean of whether the RedBlackTree is empty. - - returns: Bool - */ - public var isEmpty: Bool { - return 0 == count - } - - /** - :name: startIndex - :description: Conforms to the Collection Protocol. - - returns: Int - */ - public var startIndex: Int { - return 0 - } - - /** - :name: endIndex - :description: Conforms to the Collection Protocol. - - returns: Int - */ - public var endIndex: Int { - return count - } - - /** - :name: init - :description: Constructor - */ - public init() { - tree = RedBlackTree(uniqueKeys: false) - } - - /** - :name: init - :description: Constructor - */ - public init(elements: Element...) { - self.init(elements: elements) - } - - /** - :name: init - :description: Constructor - */ - public init(elements: [Element]) { - self.init() - insert(elements) - } - - // - // :name: generate - // :description: Conforms to the SequenceType Protocol. Returns - // the next value in the sequence of nodes using - // index values [0...n-1]. - // :returns: SortedMultiSet.Generator - // - public func makeIterator() -> SortedMultiSet.Iterator { - var i = indices.makeIterator() - return AnyIterator { i.next().map { self[$0] } } - } - - /** - Conforms to Probable protocol. - */ - public func count(of elements: T...) -> Int { - return count(of: elements) - } - - /** - Conforms to Probable protocol. - */ - public func count(of elements: [T]) -> Int { - return tree.count(of: elements) - } - - /** - The probability of elements. - */ - public func probability(of elements: T...) -> Double { - return probability(of: elements) - } - - /** - The probability of elements. - */ - public func probability(of elements: [T]) -> Double { - return tree.probability(of: elements) - } - - /** - The probability of elements. - */ - public func probability(execute block: (Element) -> Bool) -> Double { - return tree.probability { (k, _) -> Bool in - return block(k) - } - } - - /** - The expected value of elements. - */ - public func expectedValue(trials: Int, for elements: T...) -> Double { - return expectedValue(trials: trials, for: elements) - } - - /** - The expected value of elements. - */ - public func expectedValue(trials: Int, for elements: [T]) -> Double { - return tree.expectedValue(trials: trials, for: elements) - } - - /** - :name: operator [0...count - 1] - :description: Allows array like access of the index. - Items are kept in order, so when iterating - through the items, they are returned in their - ordered form. - - returns: Element - */ - public subscript(index: Int) -> Element { - return tree[index].key - } - - - /** - :name: indexOf - :description: Returns the Index of a given member, or -1 if the member is not present in the set. - - returns: Int - */ - public func index(of element: Element) -> Int { - return tree.index(of: element) - } - - /** - :name: contains - :description: A boolean check if values exists - in the set. - - returns: Bool - */ - public func contains(_ elements: Element...) -> Bool { - return contains(elements) - } - - /** - :name: contains - :description: A boolean check if an array of values exist - in the set. - - returns: Bool - */ - public func contains(_ elements: [Element]) -> Bool { - if 0 == elements.count { - return false - } - for x in elements { - if nil == tree.findValue(for: x) { - return false - } + public typealias Element = T + + /// Returns the position immediately after the given index. + /// + /// - Parameter i: A valid index of the collection. `i` must be less than + /// `endIndex`. + /// - Returns: The index value immediately after `i`. + public func index(after i: Int) -> Int { + return i < endIndex ? i + 1 : 0 } - return true - } - - /** - :name: insert - :description: Inserts new elements into the SortedMultiSet. - */ - mutating public func insert(_ elements: Element...) { - insert(elements) - } - - /** - :name: insert - :description: Inserts new elements into the SortedSet. - */ - mutating public func insert(_ elements: [Element]) { - for x in elements { - tree.insert(value: x, for: x) - } - count = tree.count - } - - /** - :name: remove - :description: Removes elements from the SortedSet. - */ - mutating public func remove(_ elements: Element...) { - remove(elements) - } - - /** - :name: remove - :description: Removes elements from the SortedSet. - */ - mutating public func remove(_ elements: [Element]) { - tree.removeValue(for: elements) - count = tree.count - } - - /** - :name: removeAll - :description: Remove all nodes from the tree. - */ - mutating public func removeAll() { - tree.removeAll() - count = tree.count - } - - /** - :name: intersect - :description: Return a new set with elements common to this set and a finite sequence of Sets. - - returns: SortedMultiSet - */ - public func intersection(_ other: SortedMultiSet) -> SortedMultiSet { - var s = SortedMultiSet() - var i = 0 - var j = 0 - let k: Int = count - let l: Int = other.count - while k > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - i += 1 - } else if y < x { - j += 1 - } else { - s.insert(x) - i += 1 - j += 1 - } - } - return s - } - - /** - :name: formIntersection - :description: Insert elements of a finite sequence of Sets. - */ - mutating public func formIntersection(_ other: SortedMultiSet) { - let l = other.count - if 0 == l { - removeAll() - } else { - var i = 0 - var j = 0 - while count > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - _ = tree.removeInstanceValueForKey(x) - count = tree.count - } else if y < x { - j += 1 - } else { - i += 1 - j += 1 + + public typealias Iterator = AnyIterator + + /** + Total number of elements within the RedBlackTree + */ + public internal(set) var count = 0 + + /** + :name: tree + :description: Internal storage of elements. + - returns: RedBlackTree + */ + internal var tree: RedBlackTree + + /** + :name: asArray + */ + public var asArray: [Element] { + var a = [Element]() + for x in self { + a.append(x) + } + return a + } + + /** + :name: description + :description: Conforms to the Printable Protocol. Outputs the + data in the SortedMultiSet in a readable format. + - returns: String + */ + public var description: String { + return "[" + map { "\($0)" }.joined(separator: ", ") + "]" + } + + /** + :name: first + :description: Get the first node value in the tree, this is + the first node based on the order of keys where + k1 <= k2 <= K3 ... <= Kn + - returns: Element? + */ + public var first: Element? { + return tree.first?.value + } + + /** + :name: last + :description: Get the last node value in the tree, this is + the last node based on the order of keys where + k1 <= k2 <= K3 ... <= Kn + - returns: Element? + */ + public var last: Element? { + return tree.last?.value + } + + /** + :name: isEmpty + :description: A boolean of whether the RedBlackTree is empty. + - returns: Bool + */ + public var isEmpty: Bool { + return count == 0 + } + + /** + :name: startIndex + :description: Conforms to the Collection Protocol. + - returns: Int + */ + public var startIndex: Int { + return 0 + } + + /** + :name: endIndex + :description: Conforms to the Collection Protocol. + - returns: Int + */ + public var endIndex: Int { + return count + } + + /** + :name: init + :description: Constructor + */ + public init() { + tree = RedBlackTree(uniqueKeys: false) + } + + /** + :name: init + :description: Constructor + */ + public init(elements: Element...) { + self.init(elements: elements) + } + + /** + :name: init + :description: Constructor + */ + public init(elements: [Element]) { + self.init() + insert(elements) + } + + // + // :name: generate + // :description: Conforms to the SequenceType Protocol. Returns + // the next value in the sequence of nodes using + // index values [0...n-1]. + // :returns: SortedMultiSet.Generator + // + public func makeIterator() -> SortedMultiSet.Iterator { + var i = indices.makeIterator() + return AnyIterator { i.next().map { self[$0] } } + } + + /** + Conforms to Probable protocol. + */ + public func count(of elements: T...) -> Int { + return count(of: elements) + } + + /** + Conforms to Probable protocol. + */ + public func count(of elements: [T]) -> Int { + return tree.count(of: elements) + } + + /** + The probability of elements. + */ + public func probability(of elements: T...) -> Double { + return probability(of: elements) + } + + /** + The probability of elements. + */ + public func probability(of elements: [T]) -> Double { + return tree.probability(of: elements) + } + + /** + The probability of elements. + */ + public func probability(execute block: (Element) -> Bool) -> Double { + return tree.probability { (k, _) -> Bool in + block(k) + } + } + + /** + The expected value of elements. + */ + public func expectedValue(trials: Int, for elements: T...) -> Double { + return expectedValue(trials: trials, for: elements) + } + + /** + The expected value of elements. + */ + public func expectedValue(trials: Int, for elements: [T]) -> Double { + return tree.expectedValue(trials: trials, for: elements) + } + + /** + :name: operator [0...count - 1] + :description: Allows array like access of the index. + Items are kept in order, so when iterating + through the items, they are returned in their + ordered form. + - returns: Element + */ + public subscript(index: Int) -> Element { + return tree[index].key + } + + /** + :name: indexOf + :description: Returns the Index of a given member, or -1 if the member is not present in the set. + - returns: Int + */ + public func index(of element: Element) -> Int { + return tree.index(of: element) + } + + /** + :name: contains + :description: A boolean check if values exists + in the set. + - returns: Bool + */ + public func contains(_ elements: Element...) -> Bool { + return contains(elements) + } + + /** + :name: contains + :description: A boolean check if an array of values exist + in the set. + - returns: Bool + */ + public func contains(_ elements: [Element]) -> Bool { + if elements.count == 0 { + return false + } + for x in elements { + if tree.findValue(for: x) == nil { + return false + } + } + return true + } + + /** + :name: insert + :description: Inserts new elements into the SortedMultiSet. + */ + public mutating func insert(_ elements: Element...) { + insert(elements) + } + + /** + :name: insert + :description: Inserts new elements into the SortedSet. + */ + public mutating func insert(_ elements: [Element]) { + for x in elements { + tree.insert(value: x, for: x) } - } - } - } - - /** - :name: union - :description: Return a new Set with items in both this set and a finite sequence of Sets. - - returns: SortedMultiSet - */ - public func union(_ other: SortedMultiSet) -> SortedMultiSet { - var s = SortedMultiSet() - var i = 0 - var j = 0 - let k: Int = count - let l: Int = other.count - while k > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - s.insert(x) - i += 1 - } else if y < x { - s.insert(y) - j += 1 - } else { - s.insert(x) - i += 1 - j += 1 - } - } - while k > i { - s.insert(self[i]) - i += 1 - } - while l > j { - s.insert(other[j]) - j += 1 - } - return s - } - - /** - :name: unionInPlace - :description: Return a new Set with items in both this set and a finite sequence of Sets. - */ - mutating public func formUnion(_ other: SortedMultiSet) { - var i = 0 - var j = 0 - let l: Int = other.count - while count > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - i += 1 - } else if y < x { - insert(y) - j += 1 - } else { - i += 1 - j += 1 - } - } - while l > j { - insert(other[j]) - j += 1 - } - } - - /** - :name: subtract - :description: Return a new set with elements in this set that do not occur in a finite sequence of Sets. - - returns: SortedMultiSet - */ - public func subtracting(_ other: SortedMultiSet) -> SortedMultiSet { - var s = SortedMultiSet() - var i = 0 - var j = 0 - let k: Int = count - let l: Int = other.count - while k > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - s.insert(x) - i += 1 - } else if y < x { - j += 1 - } else { - i += 1 - j += 1 - } - } - while k > i { - s.insert(self[i]) - i += 1 - } - return s - } - - /** - :name: subtract - :description: Remove all elements in the set that occur in a finite sequence of Sets. - */ - mutating public func subtract(_ other: SortedMultiSet) { - var i = 0 - var j = 0 - let l: Int = other.count - while count > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - i += 1 - } else if y < x { - j += 1 - } else { - _ = tree.removeInstanceValueForKey(x) count = tree.count - j += 1 - } - } - } - - /** - :name: exclusiveOr - :description: Return a new set with elements that are either in the set or a finite sequence but do not occur in both. - - returns: SortedMultiSet - */ - public func symmetricDifference(_ other: SortedMultiSet) -> SortedMultiSet { - var s = SortedMultiSet() - var i = 0 - var j = 0 - let k: Int = count - let l: Int = other.count - while k > i && l > j { - let x: Element = self[i] - let y: Element = other[j] - if x < y { - s.insert(x) - i += 1 - } else if y < x { - s.insert(y) - j += 1 - } else { - i += count(of: x) - j += other.count(of: y) - } - } - while k > i { - s.insert(self[i]) - i += 1 - } - while l > j { - s.insert(other[j]) - j += 1 - } - return s - } - - /** - :name: exclusiveOrInPlace - :description: For each element of a finite sequence, remove it from the set if it is a - common element, otherwise add it to the set. Repeated elements of the sequence will be - ignored. - */ - mutating public func formSymmetricDifference(_ other: SortedMultiSet) { - var i = 0 - var j = 0 - let l: Int = other.count - while count > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - i += 1 - } else if y < x { - insert(y) - j += 1 - } else { - remove(x) - j += 1 - } - } - while l > j { - insert(other[j]) - j += 1 - } - } - - /** - :name: isDisjointWith - :description: Returns true if no elements in the set are in a finite sequence of Sets. - - returns: Bool - */ - public func isDisjoint(with other: SortedMultiSet) -> Bool { - var i: Int = count - 1 - var j: Int = other.count - 1 - while 0 <= i && 0 <= j { - let x = self[i] - let y = other[j] - if x < y { - j -= 1 - } else if y < x { - i -= 1 - } else { - return false - } } - return true - } - - /** - :name: isSubsetOf - :description: Returns true if the set is a subset of a finite sequence as a Set. - - returns: Bool - */ - public func isSubset(of other: SortedMultiSet) -> Bool { - if count > other.count { - return false - } - for x in self { - if !other.contains(x) { - return false - } + + /** + :name: remove + :description: Removes elements from the SortedSet. + */ + public mutating func remove(_ elements: Element...) { + remove(elements) } - return true - } - - /** - :name: isStrictSubsetOf - :description: Returns true if the set is a subset of a finite sequence as a Set but not equal. - - returns: Bool - */ - public func isStrictSubset(of other: SortedMultiSet) -> Bool { - return count < other.count && isSubset(of: other) - } - - /** - :name: isSupersetOf - :description: Returns true if the set is a superset of a finite sequence as a Set. - - returns: Bool - */ - public func isSuperset(of other: SortedMultiSet) -> Bool { - if count < other.count { - return false - } - for x in other { - if !contains(x) { - return false - } + + /** + :name: remove + :description: Removes elements from the SortedSet. + */ + public mutating func remove(_ elements: [Element]) { + tree.removeValue(for: elements) + count = tree.count + } + + /** + :name: removeAll + :description: Remove all nodes from the tree. + */ + public mutating func removeAll() { + tree.removeAll() + count = tree.count + } + + /** + :name: intersect + :description: Return a new set with elements common to this set and a finite sequence of Sets. + - returns: SortedMultiSet + */ + public func intersection(_ other: SortedMultiSet) -> SortedMultiSet { + var s = SortedMultiSet() + var i = 0 + var j = 0 + let k: Int = count + let l: Int = other.count + while k > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + i += 1 + } else if y < x { + j += 1 + } else { + s.insert(x) + i += 1 + j += 1 + } + } + return s + } + + /** + :name: formIntersection + :description: Insert elements of a finite sequence of Sets. + */ + public mutating func formIntersection(_ other: SortedMultiSet) { + let l = other.count + if l == 0 { + removeAll() + } else { + var i = 0 + var j = 0 + while count > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + _ = tree.removeInstanceValueForKey(x) + count = tree.count + } else if y < x { + j += 1 + } else { + i += 1 + j += 1 + } + } + } + } + + /** + :name: union + :description: Return a new Set with items in both this set and a finite sequence of Sets. + - returns: SortedMultiSet + */ + public func union(_ other: SortedMultiSet) -> SortedMultiSet { + var s = SortedMultiSet() + var i = 0 + var j = 0 + let k: Int = count + let l: Int = other.count + while k > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + s.insert(x) + i += 1 + } else if y < x { + s.insert(y) + j += 1 + } else { + s.insert(x) + i += 1 + j += 1 + } + } + while k > i { + s.insert(self[i]) + i += 1 + } + while l > j { + s.insert(other[j]) + j += 1 + } + return s + } + + /** + :name: unionInPlace + :description: Return a new Set with items in both this set and a finite sequence of Sets. + */ + public mutating func formUnion(_ other: SortedMultiSet) { + var i = 0 + var j = 0 + let l: Int = other.count + while count > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + i += 1 + } else if y < x { + insert(y) + j += 1 + } else { + i += 1 + j += 1 + } + } + while l > j { + insert(other[j]) + j += 1 + } + } + + /** + :name: subtract + :description: Return a new set with elements in this set that do not occur in a finite sequence of Sets. + - returns: SortedMultiSet + */ + public func subtracting(_ other: SortedMultiSet) -> SortedMultiSet { + var s = SortedMultiSet() + var i = 0 + var j = 0 + let k: Int = count + let l: Int = other.count + while k > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + s.insert(x) + i += 1 + } else if y < x { + j += 1 + } else { + i += 1 + j += 1 + } + } + while k > i { + s.insert(self[i]) + i += 1 + } + return s + } + + /** + :name: subtract + :description: Remove all elements in the set that occur in a finite sequence of Sets. + */ + public mutating func subtract(_ other: SortedMultiSet) { + var i = 0 + var j = 0 + let l: Int = other.count + while count > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + i += 1 + } else if y < x { + j += 1 + } else { + _ = tree.removeInstanceValueForKey(x) + count = tree.count + j += 1 + } + } + } + + /** + :name: exclusiveOr + :description: Return a new set with elements that are either in the set or a finite sequence but do not occur in both. + - returns: SortedMultiSet + */ + public func symmetricDifference(_ other: SortedMultiSet) -> SortedMultiSet { + var s = SortedMultiSet() + var i = 0 + var j = 0 + let k: Int = count + let l: Int = other.count + while k > i, l > j { + let x: Element = self[i] + let y: Element = other[j] + if x < y { + s.insert(x) + i += 1 + } else if y < x { + s.insert(y) + j += 1 + } else { + i += count(of: x) + j += other.count(of: y) + } + } + while k > i { + s.insert(self[i]) + i += 1 + } + while l > j { + s.insert(other[j]) + j += 1 + } + return s + } + + /** + :name: exclusiveOrInPlace + :description: For each element of a finite sequence, remove it from the set if it is a + common element, otherwise add it to the set. Repeated elements of the sequence will be + ignored. + */ + public mutating func formSymmetricDifference(_ other: SortedMultiSet) { + var i = 0 + var j = 0 + let l: Int = other.count + while count > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + i += 1 + } else if y < x { + insert(y) + j += 1 + } else { + remove(x) + j += 1 + } + } + while l > j { + insert(other[j]) + j += 1 + } + } + + /** + :name: isDisjointWith + :description: Returns true if no elements in the set are in a finite sequence of Sets. + - returns: Bool + */ + public func isDisjoint(with other: SortedMultiSet) -> Bool { + var i: Int = count - 1 + var j: Int = other.count - 1 + while i >= 0, j >= 0 { + let x = self[i] + let y = other[j] + if x < y { + j -= 1 + } else if y < x { + i -= 1 + } else { + return false + } + } + return true + } + + /** + :name: isSubsetOf + :description: Returns true if the set is a subset of a finite sequence as a Set. + - returns: Bool + */ + public func isSubset(of other: SortedMultiSet) -> Bool { + if count > other.count { + return false + } + for x in self { + if !other.contains(x) { + return false + } + } + return true + } + + /** + :name: isStrictSubsetOf + :description: Returns true if the set is a subset of a finite sequence as a Set but not equal. + - returns: Bool + */ + public func isStrictSubset(of other: SortedMultiSet) -> Bool { + return count < other.count && isSubset(of: other) + } + + /** + :name: isSupersetOf + :description: Returns true if the set is a superset of a finite sequence as a Set. + - returns: Bool + */ + public func isSuperset(of other: SortedMultiSet) -> Bool { + if count < other.count { + return false + } + for x in other { + if !contains(x) { + return false + } + } + return true + } + + /** + :name: isStrictSupersetOf + :description: Returns true if the set is a superset of a finite sequence as a Set but not equal. + - returns: Bool + */ + public func isStrictSuperset(of other: SortedMultiSet) -> Bool { + return count > other.count && isSuperset(of: other) } - return true - } - - /** - :name: isStrictSupersetOf - :description: Returns true if the set is a superset of a finite sequence as a Set but not equal. - - returns: Bool - */ - public func isStrictSuperset(of other: SortedMultiSet) -> Bool { - return count > other.count && isSuperset(of: other) - } } -public func ==(lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { - if lhs.count != rhs.count { - return false - } - for i in 0..(lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { + if lhs.count != rhs.count { + return false } - } - return true + for i in 0 ..< lhs.count { + if lhs[i] != rhs[i] { + return false + } + } + return true } -public func !=(lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { - return !(lhs == rhs) +public func != (lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { + return !(lhs == rhs) } -public func +(lhs: SortedMultiSet, rhs: SortedMultiSet) -> SortedMultiSet { - return lhs.union(rhs) +public func + (lhs: SortedMultiSet, rhs: SortedMultiSet) -> SortedMultiSet { + return lhs.union(rhs) } -public func +=(lhs: inout SortedMultiSet, rhs: SortedMultiSet) { - lhs.formUnion(rhs) +public func += (lhs: inout SortedMultiSet, rhs: SortedMultiSet) { + lhs.formUnion(rhs) } -public func -(lhs: SortedMultiSet, rhs: SortedMultiSet) -> SortedMultiSet { - return lhs.subtracting(rhs) +public func - (lhs: SortedMultiSet, rhs: SortedMultiSet) -> SortedMultiSet { + return lhs.subtracting(rhs) } -public func -=(lhs: inout SortedMultiSet, rhs: SortedMultiSet) { - lhs.subtract(rhs) +public func -= (lhs: inout SortedMultiSet, rhs: SortedMultiSet) { + lhs.subtract(rhs) } -public func <=(lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { - return lhs.isSubset(of: rhs) +public func <= (lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { + return lhs.isSubset(of: rhs) } -public func >=(lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { - return lhs.isSuperset(of: rhs) +public func >= (lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { + return lhs.isSuperset(of: rhs) } -public func >(lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { - return lhs.isStrictSuperset(of: rhs) +public func > (lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { + return lhs.isStrictSuperset(of: rhs) } -public func <(lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { - return lhs.isStrictSubset(of: rhs) +public func < (lhs: SortedMultiSet, rhs: SortedMultiSet) -> Bool { + return lhs.isStrictSubset(of: rhs) } diff --git a/Sources/SortedSet.swift b/Sources/SortedSet.swift index d9b8906..20c1082 100644 --- a/Sources/SortedSet.swift +++ b/Sources/SortedSet.swift @@ -24,602 +24,602 @@ */ public struct SortedSet: Probable, Collection, Equatable, CustomStringConvertible where T: Hashable { - public typealias Element = T - - /// Returns the position immediately after the given index. - /// - /// - Parameter i: A valid index of the collection. `i` must be less than - /// `endIndex`. - /// - Returns: The index value immediately after `i`. - public func index(after i: Int) -> Int { - return i < endIndex ? i + 1 : 0 - } - - public typealias Iterator = AnyIterator - - /** - Total number of elements within the RedBlackTree - */ - public internal(set) var count = 0 - - /** - :name: tree - :description: Internal storage of elements. - - returns: RedBlckTree - */ - internal var tree: RedBlackTree - - /** - :name: asArray - */ - public var asArray: [Element] { - return map { $0 } - } - - /** - :name: description - :description: Conforms to the Printable Protocol. Outputs the - data in the SortedSet in a readable format. - - returns: String - */ - public var description: String { - return "[" + map { "\($0)" }.joined(separator: ",") + "]" - } - - /** - :name: first - :description: Get the first node value in the tree, this is - the first node based on the order of keys where - k1 <= k2 <= K3 ... <= Kn - - returns: Element? - */ - public var first: Element? { - return tree.first?.value - } - - /** - :name: last - :description: Get the last node value in the tree, this is - the last node based on the order of keys where - k1 <= k2 <= K3 ... <= Kn - - returns: Element? - */ - public var last: Element? { - return tree.last?.value - } - - /** - :name: startIndex - :description: Conforms to the Collection Protocol. - - returns: Int - */ - public var startIndex: Int { - return 0 - } - - /** - :name: endIndex - :description: Conforms to the Collection Protocol. - - returns: Int - */ - public var endIndex: Int { - return count - } - - /** - :name: init - :description: Constructor. - */ - public init() { - tree = RedBlackTree(uniqueKeys: true) - } - - /** - :name: init - :description: Constructor. - */ - public init(elements: Element...) { - self.init(elements: elements) - } - - /** - :name: init - :description: Constructor. - */ - public init(elements: [Element]) { - self.init() - insert(elements) - } - - public func makeIterator() -> SortedSet.Iterator { - var i = indices.makeIterator() - return AnyIterator { i.next().map { self[$0] } } - } - - /** - Conforms to Probable protocol. - */ - public func count(of elements: Element...) -> Int { - return count(of: elements) - } - - /** - Conforms to Probable protocol. - */ - public func count(of elements: [Element]) -> Int { - return tree.count(of: elements) - } - - /** - The probability of elements. - */ - public func probability(of elements: Element...) -> Double { - return probability(of: elements) - } - - /** - The probability of elements. - */ - public func probability(of elements: [Element]) -> Double { - return tree.probability(of: elements) - } - - /** - The probability of elements. - */ - public func probability(execute block: (Element) -> Bool) -> Double { - return tree.probability { (k, _) -> Bool in - return block(k) - } - } - - /** - The expected value of elements. - */ - public func expectedValue(trials: Int, for elements: Element...) -> Double { - return expectedValue(trials: trials, for: elements) - } - - /** - The expected value of elements. - */ - public func expectedValue(trials: Int, for elements: [Element]) -> Double { - return tree.expectedValue(trials: trials, for: elements) - } - - /** - :name: operator [0...count - 1] - :description: Allows array like access of the index. - Items are kept in order, so when iterating - through the items, they are returned in their - ordered form. - - returns: Element - */ - public subscript(index: Int) -> Element { - return tree[index].key - } - - /** - :name: indexOf - :description: Returns the Index of a given member, or -1 if the member is not present in the set. - - returns: Int - */ - public func index(of element: Element) -> Int { - return tree.index(of: element) - } - - /** - :name: contains - :description: A boolean check if values exists - in the set. - - returns: Bool - */ - public func contains(_ elements: Element...) -> Bool { - return contains(elements) - } - - /** - :name: contains - :description: A boolean check if an array of values exist - in the set. - - returns: Bool - */ - public func contains(_ elements: [Element]) -> Bool { - if 0 == elements.count { - return false - } - for x in elements { - if nil == tree.findValue(for: x) { - return false - } + public typealias Element = T + + /// Returns the position immediately after the given index. + /// + /// - Parameter i: A valid index of the collection. `i` must be less than + /// `endIndex`. + /// - Returns: The index value immediately after `i`. + public func index(after i: Int) -> Int { + return i < endIndex ? i + 1 : 0 } - return true - } - - /** - :name: insert - :description: Inserts new elements into the SortedSet. - */ - mutating public func insert(_ elements: Element...) { - insert(elements) - } - - /** - :name: insert - :description: Inserts new elements into the SortedSet. - */ - mutating public func insert(_ elements: [Element]) { - for x in elements { - tree.insert(value: x, for: x) - } - count = tree.count - } - - /** - :name: remove - :description: Removes elements from the SortedSet. - */ - mutating public func remove(_ elements: Element...) { - remove(elements) - } - - /** - :name: remove - :description: Removes elements from the SortedSet. - */ - mutating public func remove(_ elements: [Element]) { - tree.removeValue(for: elements) - count = tree.count - } - - /** - :name: removeAll - :description: Remove all nodes from the tree. - */ - mutating public func removeAll() { - tree.removeAll() - count = tree.count - } - - /** - :name: intersect - :description: Return a new set with elements common to this set and a finite sequence of Sets. - - returns: SortedSet - */ - public func intersection(_ other: SortedSet) -> SortedSet { - var s = SortedSet() - var i = 0 - var j = 0 - let k = count - let l = other.count - while k > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - i += 1 - } else if y < x { - j += 1 - } else { - s.insert(x) - i += 1 - j += 1 - } - } - return s - } - - /** - :name: formIntersection - :description: Insert elements of a finite sequence of Sets. - */ - mutating public func formIntersection(_ other: SortedSet) { - let l = other.count - if 0 == l { - removeAll() - } else { - var i = 0 - var j = 0 - while count > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - remove(x) - } else if y < x { - j += 1 + + public typealias Iterator = AnyIterator + + /** + Total number of elements within the RedBlackTree + */ + public internal(set) var count = 0 + + /** + :name: tree + :description: Internal storage of elements. + - returns: RedBlckTree + */ + internal var tree: RedBlackTree + + /** + :name: asArray + */ + public var asArray: [Element] { + return map { $0 } + } + + /** + :name: description + :description: Conforms to the Printable Protocol. Outputs the + data in the SortedSet in a readable format. + - returns: String + */ + public var description: String { + return "[" + map { "\($0)" }.joined(separator: ",") + "]" + } + + /** + :name: first + :description: Get the first node value in the tree, this is + the first node based on the order of keys where + k1 <= k2 <= K3 ... <= Kn + - returns: Element? + */ + public var first: Element? { + return tree.first?.value + } + + /** + :name: last + :description: Get the last node value in the tree, this is + the last node based on the order of keys where + k1 <= k2 <= K3 ... <= Kn + - returns: Element? + */ + public var last: Element? { + return tree.last?.value + } + + /** + :name: startIndex + :description: Conforms to the Collection Protocol. + - returns: Int + */ + public var startIndex: Int { + return 0 + } + + /** + :name: endIndex + :description: Conforms to the Collection Protocol. + - returns: Int + */ + public var endIndex: Int { + return count + } + + /** + :name: init + :description: Constructor. + */ + public init() { + tree = RedBlackTree(uniqueKeys: true) + } + + /** + :name: init + :description: Constructor. + */ + public init(elements: Element...) { + self.init(elements: elements) + } + + /** + :name: init + :description: Constructor. + */ + public init(elements: [Element]) { + self.init() + insert(elements) + } + + public func makeIterator() -> SortedSet.Iterator { + var i = indices.makeIterator() + return AnyIterator { i.next().map { self[$0] } } + } + + /** + Conforms to Probable protocol. + */ + public func count(of elements: Element...) -> Int { + return count(of: elements) + } + + /** + Conforms to Probable protocol. + */ + public func count(of elements: [Element]) -> Int { + return tree.count(of: elements) + } + + /** + The probability of elements. + */ + public func probability(of elements: Element...) -> Double { + return probability(of: elements) + } + + /** + The probability of elements. + */ + public func probability(of elements: [Element]) -> Double { + return tree.probability(of: elements) + } + + /** + The probability of elements. + */ + public func probability(execute block: (Element) -> Bool) -> Double { + return tree.probability { (k, _) -> Bool in + block(k) + } + } + + /** + The expected value of elements. + */ + public func expectedValue(trials: Int, for elements: Element...) -> Double { + return expectedValue(trials: trials, for: elements) + } + + /** + The expected value of elements. + */ + public func expectedValue(trials: Int, for elements: [Element]) -> Double { + return tree.expectedValue(trials: trials, for: elements) + } + + /** + :name: operator [0...count - 1] + :description: Allows array like access of the index. + Items are kept in order, so when iterating + through the items, they are returned in their + ordered form. + - returns: Element + */ + public subscript(index: Int) -> Element { + return tree[index].key + } + + /** + :name: indexOf + :description: Returns the Index of a given member, or -1 if the member is not present in the set. + - returns: Int + */ + public func index(of element: Element) -> Int { + return tree.index(of: element) + } + + /** + :name: contains + :description: A boolean check if values exists + in the set. + - returns: Bool + */ + public func contains(_ elements: Element...) -> Bool { + return contains(elements) + } + + /** + :name: contains + :description: A boolean check if an array of values exist + in the set. + - returns: Bool + */ + public func contains(_ elements: [Element]) -> Bool { + if elements.count == 0 { + return false + } + for x in elements { + if tree.findValue(for: x) == nil { + return false + } + } + return true + } + + /** + :name: insert + :description: Inserts new elements into the SortedSet. + */ + public mutating func insert(_ elements: Element...) { + insert(elements) + } + + /** + :name: insert + :description: Inserts new elements into the SortedSet. + */ + public mutating func insert(_ elements: [Element]) { + for x in elements { + tree.insert(value: x, for: x) + } + count = tree.count + } + + /** + :name: remove + :description: Removes elements from the SortedSet. + */ + public mutating func remove(_ elements: Element...) { + remove(elements) + } + + /** + :name: remove + :description: Removes elements from the SortedSet. + */ + public mutating func remove(_ elements: [Element]) { + tree.removeValue(for: elements) + count = tree.count + } + + /** + :name: removeAll + :description: Remove all nodes from the tree. + */ + public mutating func removeAll() { + tree.removeAll() + count = tree.count + } + + /** + :name: intersect + :description: Return a new set with elements common to this set and a finite sequence of Sets. + - returns: SortedSet + */ + public func intersection(_ other: SortedSet) -> SortedSet { + var s = SortedSet() + var i = 0 + var j = 0 + let k = count + let l = other.count + while k > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + i += 1 + } else if y < x { + j += 1 + } else { + s.insert(x) + i += 1 + j += 1 + } + } + return s + } + + /** + :name: formIntersection + :description: Insert elements of a finite sequence of Sets. + */ + public mutating func formIntersection(_ other: SortedSet) { + let l = other.count + if l == 0 { + removeAll() } else { - i += 1 - j += 1 + var i = 0 + var j = 0 + while count > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + remove(x) + } else if y < x { + j += 1 + } else { + i += 1 + j += 1 + } + } } - } - } - } - - /** - :name: union - :description: Return a new Set with items in both this set and a finite sequence of Sets. - - returns: SortedSet - */ - public func union(_ other: SortedSet) -> SortedSet { - var s = SortedSet() - var i = 0 - var j = 0 - let k = count - let l = other.count - while k > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - s.insert(x) - i += 1 - } else if y < x { - s.insert(y) - j += 1 - } else { - s.insert(x) - i += 1 - j += 1 - } - } - while k > i { - s.insert(self[i]) - i += 1 - } - while l > j { - s.insert(other[j]) - j += 1 - } - return s - } - - /** - :name: unionInPlace - :description: Return a new Set with items in both this set and a finite sequence of Sets. - */ - mutating public func formUnion(_ other: SortedSet) { - var a = [Element]() - other.forEach { - a.append($0) - } - insert(a) - } - - /** - :name: subtract - :description: Return a new set with elements in this set that do not occur in a finite sequence of Sets. - - returns: SortedSet - */ - public func subtracting(_ other: SortedSet) -> SortedSet { - var s = SortedSet() - var i = 0 - var j = 0 - let k = count - let l = other.count - while k > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - s.insert(x) - i += 1 - } else if y < x { - j += 1 - } else { - i += 1 - j += 1 - } - } - while k > i { - s.insert(self[i]) - i += 1 - } - return s - } - - /** - :name: subtract - :description: Remove all elements in the set that occur in a finite sequence of Sets. - */ - mutating public func subtract(_ other: SortedSet) { - var i = 0 - var j = 0 - let l = other.count - while count > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - i += 1 - } else if y < x { - j += 1 - } else { - remove(x) - j += 1 - } - } - } - - /** - :name: exclusiveOr - :description: Return a new set with elements that are either in the set or a finite sequence but do not occur in both. - - returns: SortedSet - */ - public func symmetricDifference(_ other: SortedSet) -> SortedSet { - var s = SortedSet() - var i = 0 - var j = 0 - let k = count - let l = other.count - while k > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - s.insert(x) - i += 1 - } else if y < x { - s.insert(y) - j += 1 - } else { - i += 1 - j += 1 - } - } - while k > i { - s.insert(self[i]) - i += 1 - } - while l > j { - s.insert(other[j]) - j += 1 - } - return s - } - - /** - :name: exclusiveOrInPlace - :description: For each element of a finite sequence, remove it from the set if it is a - common element, otherwise add it to the set. Repeated elements of the sequence will be - ignored. - */ - mutating public func formSymmetricDifference(_ other: SortedSet) { - var i = 0 - var j = 0 - let l = other.count - while count > i && l > j { - let x = self[i] - let y = other[j] - if x < y { - i += 1 - } else if y < x { - insert(y) - j += 1 - } else { - remove(x) - j += 1 - } - } - while l > j { - insert(other[j]) - j += 1 - } - } - - /** - :name: isDisjointWith - :description: Returns true if no elements in the set are in a finite sequence of Sets. - - returns: Bool - */ - public func isDisjoint(with other: SortedSet) -> Bool { - var i = count - 1 - var j = other.count - 1 - while 0 <= i && 0 <= j { - let x = self[i] - let y = other[j] - if x < y { - j -= 1 - } else if y < x { - i -= 1 - } else { - return false - } } - return true - } - - /** - :name: isSubsetOf - :description: Returns true if the set is a subset of a finite sequence as a Set. - - returns: Bool - */ - public func isSubset(of other: SortedSet) -> Bool { - if count > other.count { - return false - } - for x in self { - if !other.contains(x) { - return false - } + + /** + :name: union + :description: Return a new Set with items in both this set and a finite sequence of Sets. + - returns: SortedSet + */ + public func union(_ other: SortedSet) -> SortedSet { + var s = SortedSet() + var i = 0 + var j = 0 + let k = count + let l = other.count + while k > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + s.insert(x) + i += 1 + } else if y < x { + s.insert(y) + j += 1 + } else { + s.insert(x) + i += 1 + j += 1 + } + } + while k > i { + s.insert(self[i]) + i += 1 + } + while l > j { + s.insert(other[j]) + j += 1 + } + return s } - return true - } - - /** - :name: isStrictSubsetOf - :description: Returns true if the set is a subset of a finite sequence as a Set but not equal. - - returns: Bool - */ - public func isStrictSubset(of other: SortedSet) -> Bool { - return count < other.count && isSubset(of: other) - } - - /** - :name: isSupersetOf - :description: Returns true if the set is a superset of a finite sequence as a Set. - - returns: Bool - */ - public func isSuperset(of other: SortedSet) -> Bool { - if count < other.count { - return false - } - for x in other { - if !contains(x) { - return false - } + + /** + :name: unionInPlace + :description: Return a new Set with items in both this set and a finite sequence of Sets. + */ + public mutating func formUnion(_ other: SortedSet) { + var a = [Element]() + other.forEach { + a.append($0) + } + insert(a) + } + + /** + :name: subtract + :description: Return a new set with elements in this set that do not occur in a finite sequence of Sets. + - returns: SortedSet + */ + public func subtracting(_ other: SortedSet) -> SortedSet { + var s = SortedSet() + var i = 0 + var j = 0 + let k = count + let l = other.count + while k > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + s.insert(x) + i += 1 + } else if y < x { + j += 1 + } else { + i += 1 + j += 1 + } + } + while k > i { + s.insert(self[i]) + i += 1 + } + return s + } + + /** + :name: subtract + :description: Remove all elements in the set that occur in a finite sequence of Sets. + */ + public mutating func subtract(_ other: SortedSet) { + var i = 0 + var j = 0 + let l = other.count + while count > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + i += 1 + } else if y < x { + j += 1 + } else { + remove(x) + j += 1 + } + } + } + + /** + :name: exclusiveOr + :description: Return a new set with elements that are either in the set or a finite sequence but do not occur in both. + - returns: SortedSet + */ + public func symmetricDifference(_ other: SortedSet) -> SortedSet { + var s = SortedSet() + var i = 0 + var j = 0 + let k = count + let l = other.count + while k > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + s.insert(x) + i += 1 + } else if y < x { + s.insert(y) + j += 1 + } else { + i += 1 + j += 1 + } + } + while k > i { + s.insert(self[i]) + i += 1 + } + while l > j { + s.insert(other[j]) + j += 1 + } + return s + } + + /** + :name: exclusiveOrInPlace + :description: For each element of a finite sequence, remove it from the set if it is a + common element, otherwise add it to the set. Repeated elements of the sequence will be + ignored. + */ + public mutating func formSymmetricDifference(_ other: SortedSet) { + var i = 0 + var j = 0 + let l = other.count + while count > i, l > j { + let x = self[i] + let y = other[j] + if x < y { + i += 1 + } else if y < x { + insert(y) + j += 1 + } else { + remove(x) + j += 1 + } + } + while l > j { + insert(other[j]) + j += 1 + } + } + + /** + :name: isDisjointWith + :description: Returns true if no elements in the set are in a finite sequence of Sets. + - returns: Bool + */ + public func isDisjoint(with other: SortedSet) -> Bool { + var i = count - 1 + var j = other.count - 1 + while i >= 0, j >= 0 { + let x = self[i] + let y = other[j] + if x < y { + j -= 1 + } else if y < x { + i -= 1 + } else { + return false + } + } + return true + } + + /** + :name: isSubsetOf + :description: Returns true if the set is a subset of a finite sequence as a Set. + - returns: Bool + */ + public func isSubset(of other: SortedSet) -> Bool { + if count > other.count { + return false + } + for x in self { + if !other.contains(x) { + return false + } + } + return true + } + + /** + :name: isStrictSubsetOf + :description: Returns true if the set is a subset of a finite sequence as a Set but not equal. + - returns: Bool + */ + public func isStrictSubset(of other: SortedSet) -> Bool { + return count < other.count && isSubset(of: other) + } + + /** + :name: isSupersetOf + :description: Returns true if the set is a superset of a finite sequence as a Set. + - returns: Bool + */ + public func isSuperset(of other: SortedSet) -> Bool { + if count < other.count { + return false + } + for x in other { + if !contains(x) { + return false + } + } + return true + } + + /** + :name: isStrictSupersetOf + :description: Returns true if the set is a superset of a finite sequence as a Set but not equal. + - returns: Bool + */ + public func isStrictSuperset(of other: SortedSet) -> Bool { + return count > other.count && isSuperset(of: other) } - return true - } - - /** - :name: isStrictSupersetOf - :description: Returns true if the set is a superset of a finite sequence as a Set but not equal. - - returns: Bool - */ - public func isStrictSuperset(of other: SortedSet) -> Bool { - return count > other.count && isSuperset(of: other) - } } -public func ==(lhs: SortedSet, rhs: SortedSet) -> Bool { - if lhs.count != rhs.count { - return false - } - for i in 0..(lhs: SortedSet, rhs: SortedSet) -> Bool { + if lhs.count != rhs.count { + return false } - } - return true + for i in 0 ..< lhs.count { + if lhs[i] != rhs[i] { + return false + } + } + return true } -public func !=(lhs: SortedSet, rhs: SortedSet) -> Bool { - return !(lhs == rhs) +public func != (lhs: SortedSet, rhs: SortedSet) -> Bool { + return !(lhs == rhs) } -public func +(lhs: SortedSet, rhs: SortedSet) -> SortedSet { - return lhs.union(rhs) +public func + (lhs: SortedSet, rhs: SortedSet) -> SortedSet { + return lhs.union(rhs) } -public func +=(lhs: inout SortedSet, rhs: SortedSet) { - lhs.formUnion(rhs) +public func += (lhs: inout SortedSet, rhs: SortedSet) { + lhs.formUnion(rhs) } -public func -(lhs: SortedSet, rhs: SortedSet) -> SortedSet { - return lhs.subtracting(rhs) +public func - (lhs: SortedSet, rhs: SortedSet) -> SortedSet { + return lhs.subtracting(rhs) } -public func -=(lhs: inout SortedSet, rhs: SortedSet) { - lhs.subtract(rhs) +public func -= (lhs: inout SortedSet, rhs: SortedSet) { + lhs.subtract(rhs) } -public func <=(lhs: SortedSet, rhs: SortedSet) -> Bool { - return lhs.isSubset(of: rhs) +public func <= (lhs: SortedSet, rhs: SortedSet) -> Bool { + return lhs.isSubset(of: rhs) } -public func >=(lhs: SortedSet, rhs: SortedSet) -> Bool { - return lhs.isSuperset(of: rhs) +public func >= (lhs: SortedSet, rhs: SortedSet) -> Bool { + return lhs.isSuperset(of: rhs) } -public func >(lhs: SortedSet, rhs: SortedSet) -> Bool { - return lhs.isStrictSuperset(of: rhs) +public func > (lhs: SortedSet, rhs: SortedSet) -> Bool { + return lhs.isStrictSuperset(of: rhs) } -public func <(lhs: SortedSet, rhs: SortedSet) -> Bool { - return lhs.isStrictSubset(of: rhs) +public func < (lhs: SortedSet, rhs: SortedSet) -> Bool { + return lhs.isStrictSubset(of: rhs) } diff --git a/Sources/Stack.swift b/Sources/Stack.swift index ec568af..26ec18b 100644 --- a/Sources/Stack.swift +++ b/Sources/Stack.swift @@ -24,81 +24,81 @@ */ public struct Stack: CustomStringConvertible, Sequence { - public typealias Iterator = AnyIterator - - /// Underlying data structure. - private var list: DoublyLinkedList - - /// Total number of items in the Stack. - public var count: Int { - return list.count - } - - /// Get the latest element at the top of the Stack and do not remove it. - public var top: Element? { - return list.front - } - - /// A boolean of whether the Stack is empty. - public var isEmpty: Bool { - return list.isEmpty - } - - /// Conforms to the Printable Protocol. - public var description: String { - return list.description - } - - /// Initializer. - public init() { - list = DoublyLinkedList() - } - - /** - Conforms to the SequenceType Protocol. Returns the next value in the - sequence of nodes. - - Returns: Stack.Generator - */ - public func makeIterator() -> Stack.Iterator { - return list.makeIterator() - } - - /** - Insert a new element at the top of the Stack. - - Parameter _ element: An Element type. - */ - mutating public func push(_ element: Element) { - list.insert(atFront: element) - } - - /** - Get the latest element at the top of the Stack and remove it from - the Stack. - - Returns: Element? - */ - mutating public func pop() -> Element? { - return list.removeAtFront() - } - - /// Remove all elements from the Stack. - mutating public func removeAll() { - list.removeAll() - } + public typealias Iterator = AnyIterator + + /// Underlying data structure. + private var list: DoublyLinkedList + + /// Total number of items in the Stack. + public var count: Int { + return list.count + } + + /// Get the latest element at the top of the Stack and do not remove it. + public var top: Element? { + return list.front + } + + /// A boolean of whether the Stack is empty. + public var isEmpty: Bool { + return list.isEmpty + } + + /// Conforms to the Printable Protocol. + public var description: String { + return list.description + } + + /// Initializer. + public init() { + list = DoublyLinkedList() + } + + /** + Conforms to the SequenceType Protocol. Returns the next value in the + sequence of nodes. + - Returns: Stack.Generator + */ + public func makeIterator() -> Stack.Iterator { + return list.makeIterator() + } + + /** + Insert a new element at the top of the Stack. + - Parameter _ element: An Element type. + */ + public mutating func push(_ element: Element) { + list.insert(atFront: element) + } + + /** + Get the latest element at the top of the Stack and remove it from + the Stack. + - Returns: Element? + */ + public mutating func pop() -> Element? { + return list.removeAtFront() + } + + /// Remove all elements from the Stack. + public mutating func removeAll() { + list.removeAll() + } } -public func +(lhs: Stack, rhs: Stack) -> Stack { - var s = Stack() - for x in lhs { - s.push(x) - } - for x in rhs { - s.push(x) - } - return s +public func + (lhs: Stack, rhs: Stack) -> Stack { + var s = Stack() + for x in lhs { + s.push(x) + } + for x in rhs { + s.push(x) + } + return s } -public func +=(lhs: inout Stack, rhs: Stack) { - for x in rhs { - lhs.push(x) - } +public func += (lhs: inout Stack, rhs: Stack) { + for x in rhs { + lhs.push(x) + } } diff --git a/Tests/DequeTests.swift b/Tests/DequeTests.swift index 2a56a34..6b8f738 100644 --- a/Tests/DequeTests.swift +++ b/Tests/DequeTests.swift @@ -23,75 +23,74 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class DequeTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var d = Deque() - - d.insert(atFront: 1) - d.insert(atFront: 2) - d.insert(atFront: 3) - - XCTAssert(3 == d.count, "Count incorrect, got \(d.count).") - - XCTAssert(3 == d.front, "Front incorrect, got \(String(describing: d.front))") - XCTAssert(1 == d.back, "Back incorrect, got \(String(describing: d.back))") - - d.insert(atBack: 5) - d.insert(atBack: 6) - d.insert(atBack: 7) - - XCTAssert(6 == d.count, "Count incorrect, got \(d.count).") - - XCTAssert(3 == d.front, "Front incorrect, got \(String(describing: d.front))") - XCTAssert(7 == d.back, "Back incorrect, got \(String(describing: d.back))") - - XCTAssert(3 == d.removeAtFront() && 5 == d.count && 2 == d.front, "RemoveAtFront incorrect") - XCTAssert(2 == d.removeAtFront() && 4 == d.count && 1 == d.front, "RemoveAtFront incorrect") - XCTAssert(1 == d.removeAtFront() && 3 == d.count && 5 == d.front, "RemoveAtFront incorrect") - - XCTAssert(7 == d.removeAtBack() && 2 == d.count && 6 == d.back, "RemoveAtBack incorrect") - XCTAssert(6 == d.removeAtBack() && 1 == d.count && 5 == d.back, "RemoveAtBack incorrect") - XCTAssert(5 == d.removeAtBack() && 0 == d.count && nil == d.back, "RemoveAtBack incorrect") - - d.insert(atFront: 1) - d.insert(atFront: 2) - d.insert(atFront: 3) - d.removeAll() - - XCTAssert(0 == d.count, "Count incorrect, got \(d.count).") - } - - func testConcat() { - var d1 = Deque() - d1.insert(atBack: 1) - d1.insert(atBack: 2) - d1.insert(atBack: 3) - - var d2 = Deque() - d2.insert(atBack: 5) - d2.insert(atBack: 6) - d2.insert(atBack: 7) - - var d3 = d1 + d2 - - for x in d1 { - XCTAssertEqual(x, d3.removeAtFront(), "Concat incorrect.") + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() } - - for x in d2 { - XCTAssertEqual(x, d3.removeAtFront(), "Concat incorrect.") + + func testInt() { + var d = Deque() + + d.insert(atFront: 1) + d.insert(atFront: 2) + d.insert(atFront: 3) + + XCTAssert(d.count == 3, "Count incorrect, got \(d.count).") + + XCTAssert(d.front == 3, "Front incorrect, got \(String(describing: d.front))") + XCTAssert(d.back == 1, "Back incorrect, got \(String(describing: d.back))") + + d.insert(atBack: 5) + d.insert(atBack: 6) + d.insert(atBack: 7) + + XCTAssert(d.count == 6, "Count incorrect, got \(d.count).") + + XCTAssert(d.front == 3, "Front incorrect, got \(String(describing: d.front))") + XCTAssert(d.back == 7, "Back incorrect, got \(String(describing: d.back))") + + XCTAssert(d.removeAtFront() == 3 && d.count == 5 && d.front == 2, "RemoveAtFront incorrect") + XCTAssert(d.removeAtFront() == 2 && d.count == 4 && d.front == 1, "RemoveAtFront incorrect") + XCTAssert(d.removeAtFront() == 1 && d.count == 3 && d.front == 5, "RemoveAtFront incorrect") + + XCTAssert(d.removeAtBack() == 7 && d.count == 2 && d.back == 6, "RemoveAtBack incorrect") + XCTAssert(d.removeAtBack() == 6 && d.count == 1 && d.back == 5, "RemoveAtBack incorrect") + XCTAssert(d.removeAtBack() == 5 && d.count == 0 && d.back == nil, "RemoveAtBack incorrect") + + d.insert(atFront: 1) + d.insert(atFront: 2) + d.insert(atFront: 3) + d.removeAll() + + XCTAssert(d.count == 0, "Count incorrect, got \(d.count).") + } + + func testConcat() { + var d1 = Deque() + d1.insert(atBack: 1) + d1.insert(atBack: 2) + d1.insert(atBack: 3) + + var d2 = Deque() + d2.insert(atBack: 5) + d2.insert(atBack: 6) + d2.insert(atBack: 7) + + var d3 = d1 + d2 + + for x in d1 { + XCTAssertEqual(x, d3.removeAtFront(), "Concat incorrect.") + } + + for x in d2 { + XCTAssertEqual(x, d3.removeAtFront(), "Concat incorrect.") + } } - } } diff --git a/Tests/DoublyLinkedListTests.swift b/Tests/DoublyLinkedListTests.swift index b5c7c81..6d64ebf 100644 --- a/Tests/DoublyLinkedListTests.swift +++ b/Tests/DoublyLinkedListTests.swift @@ -23,142 +23,141 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class DoublyLinkedListTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var l = DoublyLinkedList() - - l.insert(atFront: 1) - l.insert(atFront: 2) - l.insert(atFront: 3) - - XCTAssert(3 == l.count, "Count incorrect, got \(l.count).") - - XCTAssert(3 == l.front, "Front incorrect, got \(String(describing: l.front))") - XCTAssert(1 == l.back, "Back incorrect, got \(String(describing: l.back))") - - l.insert(atBack: 5) - l.insert(atBack: 6) - l.insert(atBack: 7) - - l.cursorToFront() - while !l.isCursorAtBack { - l.next() + override func setUp() { + super.setUp() } - - l.cursorToBack() - while !l.isCursorAtFront { - l.previous() + + override func tearDown() { + super.tearDown() } - - XCTAssert(6 == l.count, "Count incorrect, got \(l.count).") - - XCTAssert(3 == l.front, "Front incorrect, got \(String(describing: l.front))") - XCTAssert(7 == l.back, "Back incorrect, got \(String(describing: l.back))") - - l.cursorToFront() - XCTAssert(3 == l.front && l.front == l.cursor, "Current incorrect, got \(String(describing: l.cursor))") - XCTAssert(2 == l.next(), "Test failed, got \(String(describing: l.cursor))") - XCTAssert(1 == l.next(), "Test failed, got \(String(describing: l.cursor))") - XCTAssert(5 == l.next(), "Test failed, got \(String(describing: l.cursor))") - XCTAssert(6 == l.next(), "Test failed, got \(String(describing: l.cursor))") - XCTAssert(7 == l.next(), "Test failed, got \(String(describing: l.cursor))") - - l.cursorToBack() - XCTAssert(7 == l.back && l.back == l.cursor, "Current incorrect, got \(String(describing: l.cursor))") - XCTAssert(6 == l.previous(), "Test failed, got \(String(describing: l.cursor))") - XCTAssert(5 == l.previous(), "Test failed, got \(String(describing: l.cursor))") - XCTAssert(1 == l.previous(), "Test failed, got \(String(describing: l.cursor))") - XCTAssert(2 == l.previous(), "Test failed, got \(String(describing: l.cursor))") - XCTAssert(3 == l.previous(), "Test failed, got \(String(describing: l.cursor))") - - l.cursorToFront() - XCTAssert(3 == l.removeAtFront() && 5 == l.count, "Test failed.") - XCTAssert(2 == l.removeAtFront() && 4 == l.count, "Test failed.") - XCTAssert(1 == l.removeAtFront() && 3 == l.count, "Test failed.") - - l.cursorToBack() - XCTAssert(7 == l.removeAtBack() && 2 == l.count, "Test failed.") - XCTAssert(6 == l.removeAtBack() && 1 == l.count, "Test failed.") - XCTAssert(5 == l.removeAtBack() && 0 == l.count, "Test failed.") - - l.removeAll() - l.cursorToFront() - XCTAssert(nil == l.cursor && 0 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.insert(beforeCursor: 1) - XCTAssert(1 == l.cursor && 1 == l.count, "Test failed, got \(String(describing: l.cursor))") - - l.removeAll() - l.cursorToBack() - XCTAssert(nil == l.cursor && 0 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.insert(afterCursor: 1) - XCTAssert(1 == l.cursor && 1 == l.count, "Test failed, got \(String(describing: l.cursor))") - - l.removeAll() - l.insert(atBack: 1) - XCTAssert(1 == l.cursor && 1 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.insert(afterCursor: 2) - l.insert(afterCursor: 6) - l.next() - XCTAssert(6 == l.cursor && 3 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.insert(beforeCursor: 3) - l.insert(beforeCursor: 5) - l.previous() - XCTAssert(5 == l.cursor && 5 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.insert(atBack: 4) - l.previous() - l.removeAtCursor() - XCTAssert(5 == l.cursor && 5 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.removeAtCursor() - XCTAssert(6 == l.cursor && 4 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.removeAtCursor() - XCTAssert(2 == l.cursor && 3 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.removeAtCursor() - XCTAssert(1 == l.previous() && 2 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.removeAtCursor() - XCTAssert(l.front == l.cursor && l.back == l.cursor && 1 == l.count, "Test failed, got \(String(describing: l.cursor))") - l.removeAtCursor() - XCTAssert(nil == l.cursor && 0 == l.count, "Test failed, got \(String(describing: l.cursor))") - - l.insert(atFront: 1) - l.insert(atBack: 2) - l.insert(atFront: 3) - } - - func testConcat() { - var l1 = DoublyLinkedList() - l1.insert(atFront: 3) - l1.insert(atFront: 2) - l1.insert(atFront: 1) - - var l2 = DoublyLinkedList() - l2.insert(atBack: 4) - l2.insert(atBack: 5) - l2.insert(atBack: 6) - - var l3 = l1 + l2 - - for x in l1 { - XCTAssert(x == l3.removeAtFront(), "Concat incorrect.") + + func testInt() { + var l = DoublyLinkedList() + + l.insert(atFront: 1) + l.insert(atFront: 2) + l.insert(atFront: 3) + + XCTAssert(l.count == 3, "Count incorrect, got \(l.count).") + + XCTAssert(l.front == 3, "Front incorrect, got \(String(describing: l.front))") + XCTAssert(l.back == 1, "Back incorrect, got \(String(describing: l.back))") + + l.insert(atBack: 5) + l.insert(atBack: 6) + l.insert(atBack: 7) + + l.cursorToFront() + while !l.isCursorAtBack { + l.next() + } + + l.cursorToBack() + while !l.isCursorAtFront { + l.previous() + } + + XCTAssert(l.count == 6, "Count incorrect, got \(l.count).") + + XCTAssert(l.front == 3, "Front incorrect, got \(String(describing: l.front))") + XCTAssert(l.back == 7, "Back incorrect, got \(String(describing: l.back))") + + l.cursorToFront() + XCTAssert(l.front == 3 && l.front == l.cursor, "Current incorrect, got \(String(describing: l.cursor))") + XCTAssert(l.next() == 2, "Test failed, got \(String(describing: l.cursor))") + XCTAssert(l.next() == 1, "Test failed, got \(String(describing: l.cursor))") + XCTAssert(l.next() == 5, "Test failed, got \(String(describing: l.cursor))") + XCTAssert(l.next() == 6, "Test failed, got \(String(describing: l.cursor))") + XCTAssert(l.next() == 7, "Test failed, got \(String(describing: l.cursor))") + + l.cursorToBack() + XCTAssert(l.back == 7 && l.back == l.cursor, "Current incorrect, got \(String(describing: l.cursor))") + XCTAssert(l.previous() == 6, "Test failed, got \(String(describing: l.cursor))") + XCTAssert(l.previous() == 5, "Test failed, got \(String(describing: l.cursor))") + XCTAssert(l.previous() == 1, "Test failed, got \(String(describing: l.cursor))") + XCTAssert(l.previous() == 2, "Test failed, got \(String(describing: l.cursor))") + XCTAssert(l.previous() == 3, "Test failed, got \(String(describing: l.cursor))") + + l.cursorToFront() + XCTAssert(l.removeAtFront() == 3 && l.count == 5, "Test failed.") + XCTAssert(l.removeAtFront() == 2 && l.count == 4, "Test failed.") + XCTAssert(l.removeAtFront() == 1 && l.count == 3, "Test failed.") + + l.cursorToBack() + XCTAssert(l.removeAtBack() == 7 && l.count == 2, "Test failed.") + XCTAssert(l.removeAtBack() == 6 && l.count == 1, "Test failed.") + XCTAssert(l.removeAtBack() == 5 && l.count == 0, "Test failed.") + + l.removeAll() + l.cursorToFront() + XCTAssert(l.cursor == nil && l.count == 0, "Test failed, got \(String(describing: l.cursor))") + l.insert(beforeCursor: 1) + XCTAssert(l.cursor == 1 && l.count == 1, "Test failed, got \(String(describing: l.cursor))") + + l.removeAll() + l.cursorToBack() + XCTAssert(l.cursor == nil && l.count == 0, "Test failed, got \(String(describing: l.cursor))") + l.insert(afterCursor: 1) + XCTAssert(l.cursor == 1 && l.count == 1, "Test failed, got \(String(describing: l.cursor))") + + l.removeAll() + l.insert(atBack: 1) + XCTAssert(l.cursor == 1 && l.count == 1, "Test failed, got \(String(describing: l.cursor))") + l.insert(afterCursor: 2) + l.insert(afterCursor: 6) + l.next() + XCTAssert(l.cursor == 6 && l.count == 3, "Test failed, got \(String(describing: l.cursor))") + l.insert(beforeCursor: 3) + l.insert(beforeCursor: 5) + l.previous() + XCTAssert(l.cursor == 5 && l.count == 5, "Test failed, got \(String(describing: l.cursor))") + l.insert(atBack: 4) + l.previous() + l.removeAtCursor() + XCTAssert(l.cursor == 5 && l.count == 5, "Test failed, got \(String(describing: l.cursor))") + l.removeAtCursor() + XCTAssert(l.cursor == 6 && l.count == 4, "Test failed, got \(String(describing: l.cursor))") + l.removeAtCursor() + XCTAssert(l.cursor == 2 && l.count == 3, "Test failed, got \(String(describing: l.cursor))") + l.removeAtCursor() + XCTAssert(l.previous() == 1 && l.count == 2, "Test failed, got \(String(describing: l.cursor))") + l.removeAtCursor() + XCTAssert(l.front == l.cursor && l.back == l.cursor && l.count == 1, "Test failed, got \(String(describing: l.cursor))") + l.removeAtCursor() + XCTAssert(l.cursor == nil && l.count == 0, "Test failed, got \(String(describing: l.cursor))") + + l.insert(atFront: 1) + l.insert(atBack: 2) + l.insert(atFront: 3) } - - for x in l2 { - XCTAssert(x == l3.removeAtFront(), "Concat incorrect.") + + func testConcat() { + var l1 = DoublyLinkedList() + l1.insert(atFront: 3) + l1.insert(atFront: 2) + l1.insert(atFront: 1) + + var l2 = DoublyLinkedList() + l2.insert(atBack: 4) + l2.insert(atBack: 5) + l2.insert(atBack: 6) + + var l3 = l1 + l2 + + for x in l1 { + XCTAssert(x == l3.removeAtFront(), "Concat incorrect.") + } + + for x in l2 { + XCTAssert(x == l3.removeAtFront(), "Concat incorrect.") + } + } + + func testPerformance() { + measure {} } - } - - func testPerformance() { - self.measure() {} - } } diff --git a/Tests/ProbabilityTests.swift b/Tests/ProbabilityTests.swift index d7b655d..f8aebe0 100644 --- a/Tests/ProbabilityTests.swift +++ b/Tests/ProbabilityTests.swift @@ -23,167 +23,167 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class ProbabilityTests: XCTestCase { - var saveExpectation: XCTestExpectation? - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testSortedSet() { - var s = SortedSet() - XCTAssertEqual(0, s.probability { _ -> Bool in return true}) - - s.insert(1, 2, 3, 3) - - let ev1: Double = 16 * s.probability(of: 2, 3) - - XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - let ev2: Double = 16 * s.probability { (element: Int) -> Bool in - return 2 == element || 3 == element + var saveExpectation: XCTestExpectation? + + override func setUp() { + super.setUp() } - - XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testSortedMultiSet() { - var s = SortedSet() - XCTAssertEqual(0, s.probability { _ -> Bool in return true}) - - s.insert(1, 2, 3, 3) - - let ev1: Double = 16 * s.probability(of: 2, 3) - - XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - let ev2: Double = 16 * s.probability { (element: Int) -> Bool in - return 2 == element || 3 == element + + override func tearDown() { + super.tearDown() } - - XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testSortedDictionary() { - var s = SortedDictionary() - XCTAssertEqual(0, s.probability { _, _ -> Bool in return true}) - - s.insert((1, 1)) - s.insert((2, 2)) - s.insert((3, 3)) - s.insert((3, 3)) - - let ev1: Double = 16 * s.probability(of: 2, 3) - - XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - let ev2: Double = 16 * s.probability { (key: Int, value: Int?) -> Bool in - return 2 == value || 3 == value + + func testSortedSet() { + var s = SortedSet() + XCTAssertEqual(0, s.probability { _ -> Bool in true }) + + s.insert(1, 2, 3, 3) + + let ev1: Double = 16 * s.probability(of: 2, 3) + + XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + let ev2: Double = 16 * s.probability { (element: Int) -> Bool in + element == 2 || element == 3 + } + + XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") } - - XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testSortedMultiDictionary() { - var s = SortedMultiDictionary() - XCTAssertEqual(0, s.probability { _, _ -> Bool in return true}) - - s.insert((1, 1)) - s.insert((2, 2)) - s.insert((3, 3)) - s.insert((3, 3)) - - let ev1: Double = 16 * s.probability(of: 2, 3) - - XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - let ev2: Double = 16 * s.probability { (key: Int, value: Int?) -> Bool in - return 2 == value || 3 == value + + func testSortedMultiSet() { + var s = SortedSet() + XCTAssertEqual(0, s.probability { _ -> Bool in true }) + + s.insert(1, 2, 3, 3) + + let ev1: Double = 16 * s.probability(of: 2, 3) + + XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + let ev2: Double = 16 * s.probability { (element: Int) -> Bool in + element == 2 || element == 3 + } + + XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") } - - XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testArray() { - var s: Array = Array() - XCTAssertEqual(0, s.probability { _ -> Bool in return true}) - - s.append(1) - s.append(2) - s.append(3) - s.append(4) - - let ev1: Double = 16 * s.probability(of: 2, 3) - - XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - let ev2: Double = 16 * s.probability { (element: Int) -> Bool in - return 2 == element || 3 == element + + func testSortedDictionary() { + var s = SortedDictionary() + XCTAssertEqual(0, s.probability { _, _ -> Bool in true }) + + s.insert((1, 1)) + s.insert((2, 2)) + s.insert((3, 3)) + s.insert((3, 3)) + + let ev1: Double = 16 * s.probability(of: 2, 3) + + XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + let ev2: Double = 16 * s.probability { (_: Int, value: Int?) -> Bool in + value == 2 || value == 3 + } + + XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") } - - XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testSet() { - var s: Set = Set() - XCTAssertEqual(0, s.probability { _ -> Bool in return true}) - - s.insert(1) - s.insert(2) - s.insert(3) - s.insert(4) - - let ev1: Double = 16 * s.probability(of: 2, 3) - - XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - let ev2: Double = 16 * s.probability { (element: Int) -> Bool in - return 2 == element || 3 == element + + func testSortedMultiDictionary() { + var s = SortedMultiDictionary() + XCTAssertEqual(0, s.probability { _, _ -> Bool in true }) + + s.insert((1, 1)) + s.insert((2, 2)) + s.insert((3, 3)) + s.insert((3, 3)) + + let ev1: Double = 16 * s.probability(of: 2, 3) + + XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + let ev2: Double = 16 * s.probability { (_: Int, value: Int?) -> Bool in + value == 2 || value == 3 + } + + XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") + } + + func testArray() { + var s: [Int] = [Int]() + XCTAssertEqual(0, s.probability { _ -> Bool in true }) + + s.append(1) + s.append(2) + s.append(3) + s.append(4) + + let ev1: Double = 16 * s.probability(of: 2, 3) + + XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + let ev2: Double = 16 * s.probability { (element: Int) -> Bool in + element == 2 || element == 3 + } + + XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") } - - XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") - - s.removeAll() - XCTAssertEqual(0, s.count) - } - - func testBlock() { - let die: Array = Array(arrayLiteral: 1, 2, 3, 4, 5, 6) - - let probabilityOfX: Double = die.probability { (number: Int) in - if 5 < number || 0 == number % 3 { - // Do more. - return true - } - return false + + func testSet() { + var s: Set = Set() + XCTAssertEqual(0, s.probability { _ -> Bool in true }) + + s.insert(1) + s.insert(2) + s.insert(3) + s.insert(4) + + let ev1: Double = 16 * s.probability(of: 2, 3) + + XCTAssertEqual(ev1, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + let ev2: Double = 16 * s.probability { (element: Int) -> Bool in + element == 2 || element == 3 + } + + XCTAssertEqual(ev2, s.expectedValue(trials: 16, for: 2, 3), "Test failed.") + + s.removeAll() + XCTAssertEqual(0, s.count) + } + + func testBlock() { + let die: [Int] = [Int](arrayLiteral: 1, 2, 3, 4, 5, 6) + + let probabilityOfX: Double = die.probability { (number: Int) in + if number > 5 || number % 3 == 0 { + // Do more. + return true + } + return false + } + + XCTAssertTrue(probabilityOfX > 0.33, "Test failed.") + } + + func testPerformance() { + measure {} } - - XCTAssertTrue(0.33 < probabilityOfX, "Test failed.") - } - - func testPerformance() { - self.measure() {} - } } diff --git a/Tests/QueueTests.swift b/Tests/QueueTests.swift index 55a8866..2969100 100644 --- a/Tests/QueueTests.swift +++ b/Tests/QueueTests.swift @@ -23,84 +23,83 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class QueueTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var q = Queue() - - q.enqueue(1) - q.enqueue(2) - q.enqueue(3) - - XCTAssert(3 == q.count, "Count incorrect, got \(q.count).") - XCTAssert(1 == q.peek, "Peek incorrect, got \(String(describing: q.peek))") - - q.enqueue(5) - q.enqueue(6) - q.enqueue(7) - - XCTAssert(6 == q.count, "Count incorrect, got \(q.count).") - XCTAssert(1 == q.peek, "Peek incorrect, got \(String(describing: q.peek))") - - XCTAssert(1 == q.dequeue() && 5 == q.count && 2 == q.peek, "Dequeue incorrect") - XCTAssert(2 == q.dequeue() && 4 == q.count && 3 == q.peek, "Dequeue incorrect") - XCTAssert(3 == q.dequeue() && 3 == q.count && 5 == q.peek, "Dequeue incorrect") - XCTAssert(5 == q.dequeue() && 2 == q.count && 6 == q.peek, "Dequeue incorrect") - XCTAssert(6 == q.dequeue() && 1 == q.count && 7 == q.peek, "Dequeue incorrect") - XCTAssert(7 == q.dequeue() && 0 == q.count && nil == q.peek, "Dequeue incorrect") - - q.enqueue(1) - q.enqueue(2) - q.enqueue(3) - q.removeAll() - - XCTAssert(0 == q.count, "Count incorrect, got \(q.count).") - - q.enqueue(1) - q.enqueue(2) - q.enqueue(3) - } - - func testConcat() { - var q1 = Queue() - q1.enqueue(1) - q1.enqueue(2) - q1.enqueue(3) - - var q2 = Queue() - q2.enqueue(4) - q2.enqueue(5) - q2.enqueue(6) - - var q3 = q1 + q2 - - for x in q1 { - XCTAssert(x == q3.dequeue(), "Concat incorrect.") + override func setUp() { + super.setUp() } - - for x in q2 { - XCTAssert(x == q3.dequeue(), "Concat incorrect.") + + override func tearDown() { + super.tearDown() } - - q3.removeAll() - var q4 = q1 + q2 + q3 - for x in q4 { - XCTAssert(x == q4.dequeue(), "Concat incorrect.") + + func testInt() { + var q = Queue() + + q.enqueue(1) + q.enqueue(2) + q.enqueue(3) + + XCTAssert(q.count == 3, "Count incorrect, got \(q.count).") + XCTAssert(q.peek == 1, "Peek incorrect, got \(String(describing: q.peek))") + + q.enqueue(5) + q.enqueue(6) + q.enqueue(7) + + XCTAssert(q.count == 6, "Count incorrect, got \(q.count).") + XCTAssert(q.peek == 1, "Peek incorrect, got \(String(describing: q.peek))") + + XCTAssert(q.dequeue() == 1 && q.count == 5 && q.peek == 2, "Dequeue incorrect") + XCTAssert(q.dequeue() == 2 && q.count == 4 && q.peek == 3, "Dequeue incorrect") + XCTAssert(q.dequeue() == 3 && q.count == 3 && q.peek == 5, "Dequeue incorrect") + XCTAssert(q.dequeue() == 5 && q.count == 2 && q.peek == 6, "Dequeue incorrect") + XCTAssert(q.dequeue() == 6 && q.count == 1 && q.peek == 7, "Dequeue incorrect") + XCTAssert(q.dequeue() == 7 && q.count == 0 && q.peek == nil, "Dequeue incorrect") + + q.enqueue(1) + q.enqueue(2) + q.enqueue(3) + q.removeAll() + + XCTAssert(q.count == 0, "Count incorrect, got \(q.count).") + + q.enqueue(1) + q.enqueue(2) + q.enqueue(3) + } + + func testConcat() { + var q1 = Queue() + q1.enqueue(1) + q1.enqueue(2) + q1.enqueue(3) + + var q2 = Queue() + q2.enqueue(4) + q2.enqueue(5) + q2.enqueue(6) + + var q3 = q1 + q2 + + for x in q1 { + XCTAssert(x == q3.dequeue(), "Concat incorrect.") + } + + for x in q2 { + XCTAssert(x == q3.dequeue(), "Concat incorrect.") + } + + q3.removeAll() + var q4 = q1 + q2 + q3 + for x in q4 { + XCTAssert(x == q4.dequeue(), "Concat incorrect.") + } + } + + func testPerformance() { + measure {} } - } - - func testPerformance() { - self.measure() {} - } } diff --git a/Tests/RedBlackTreeTests.swift b/Tests/RedBlackTreeTests.swift index 7878826..98c78d5 100644 --- a/Tests/RedBlackTreeTests.swift +++ b/Tests/RedBlackTreeTests.swift @@ -23,149 +23,148 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class RedBlackTreeTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var s = RedBlackTree(uniqueKeys: true) - - XCTAssert(0 == s.count, "Test failed, got \(s.count).") - - for _ in 0..<1000 { - s.insert(value: 1, for: 1) - s.insert(value: 2, for: 2) - s.insert(value: 3, for: 3) + override func setUp() { + super.setUp() } - - XCTAssert(3 == s.count, "Test failed.\(s)") - XCTAssert(1 == s[0].value, "Test failed.") - XCTAssert(2 == s[1].value, "Test failed.") - XCTAssert(3 == s[2].value, "Test failed.") - - for _ in 0..<500 { - s.removeValue(for: 1) - s.removeValue(for: 3) + + override func tearDown() { + super.tearDown() } - - XCTAssert(1 == s.count, "Test failed.") - s.removeValue(for: 2) - - XCTAssert(true == s.insert(value: 10, for: 2), "Test failed.") - XCTAssertEqual(1, s.count, "Test failed.") - XCTAssertEqual(10, s.findValue(for: 2), "Test failed.") - XCTAssertEqual(10, s[0].value, "Test failed.") - - s.removeValue(for: 2) - XCTAssertEqual(0, s.count, "Test failed.") - - s.insert(value: 1, for: 1) - s.insert(value: 2, for: 2) - s.insert(value: 3, for: 3) - - for i in s.startIndex..(uniqueKeys: true) + + XCTAssert(s.count == 0, "Test failed, got \(s.count).") + + for _ in 0 ..< 1000 { + s.insert(value: 1, for: 1) + s.insert(value: 2, for: 2) + s.insert(value: 3, for: 3) + } + + XCTAssert(s.count == 3, "Test failed.\(s)") + XCTAssert(s[0].value == 1, "Test failed.") + XCTAssert(s[1].value == 2, "Test failed.") + XCTAssert(s[2].value == 3, "Test failed.") + + for _ in 0 ..< 500 { + s.removeValue(for: 1) + s.removeValue(for: 3) + } + + XCTAssert(s.count == 1, "Test failed.") + s.removeValue(for: 2) + + XCTAssert(s.insert(value: 10, for: 2) == true, "Test failed.") + XCTAssertEqual(1, s.count, "Test failed.") + XCTAssertEqual(10, s.findValue(for: 2), "Test failed.") + XCTAssertEqual(10, s[0].value, "Test failed.") + + s.removeValue(for: 2) + XCTAssertEqual(0, s.count, "Test failed.") + + s.insert(value: 1, for: 1) + s.insert(value: 2, for: 2) + s.insert(value: 3, for: 3) + + for i in s.startIndex ..< s.endIndex { + s[i] = (s[i].key, 100) + XCTAssert(s[i].value == 100, "Test failed.") + } + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") } - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testPropertyKey() { - var s = RedBlackTree>(uniqueKeys: false) - s.insert(value: [1, 2, 3], for: "friends") - s["menu"] = [11, 22, 33] - - XCTAssert(s["friends"]! == s[0].value!, "Test failed.") - XCTAssert(s["menu"]! == s[1].value!, "Test failed.") - XCTAssert(s["empty"] == nil, "Test failed.") - s["menu"] = [22, 33, 44] - XCTAssert(s["menu"]! == [22, 33, 44], "Test failed.") - s["menu"] = nil - XCTAssert(2 == s.count, "Test failed.") - } - - func testValue() { - var t1 = RedBlackTree() - t1.insert(value: 1, for: 1) - t1.insert(value: 2, for: 2) - t1.insert(value: 3, for: 3) - - var t2 = RedBlackTree() - t2.insert(value: 4, for: 4) - t2.insert(value: 5, for: 5) - t2.insert(value: 6, for: 6) - - let t3 = t1 + t2 - - for i in 0..(uniqueKeys: false) + s.insert(value: [1, 2, 3], for: "friends") + s["menu"] = [11, 22, 33] + + XCTAssert(s["friends"]! == s[0].value!, "Test failed.") + XCTAssert(s["menu"]! == s[1].value!, "Test failed.") + XCTAssert(s["empty"] == nil, "Test failed.") + s["menu"] = [22, 33, 44] + XCTAssert(s["menu"]! == [22, 33, 44], "Test failed.") + s["menu"] = nil + XCTAssert(s.count == 2, "Test failed.") } - - for i in 0..() + t1.insert(value: 1, for: 1) + t1.insert(value: 2, for: 2) + t1.insert(value: 3, for: 3) + + var t2 = RedBlackTree() + t2.insert(value: 4, for: 4) + t2.insert(value: 5, for: 5) + t2.insert(value: 6, for: 6) + + let t3 = t1 + t2 + + for i in 0 ..< t1.count { + XCTAssert(t1[i].value == t3.findValue(for: t1[i].value!), "Test failed.") + } + + for i in 0 ..< t2.count { + XCTAssert(t2[i].value == t3.findValue(for: t2[i].value!), "Test failed.") + } + } + + func testIndexOfUniqueKeys() { + var t1 = RedBlackTree(uniqueKeys: true) + t1.insert(value: 1, for: 1) + t1.insert(value: 2, for: 2) + t1.insert(value: 3, for: 3) + t1.insert(value: 4, for: 4) + t1.insert(value: 5, for: 5) + t1.insert(value: 5, for: 5) + t1.insert(value: 6, for: 6) + + XCTAssert(t1.index(of: 1) == 0, "Test failed.") + XCTAssert(t1.index(of: 6) == 5, "Test failed.") + XCTAssert(t1.index(of: 100) == -1, "Test failed.") + } + + func testIndexOfNonUniqueKeys() { + var t1 = RedBlackTree() + t1.insert(value: 1, for: 1) + t1.insert(value: 2, for: 2) + t1.insert(value: 3, for: 3) + t1.insert(value: 4, for: 4) + t1.insert(value: 5, for: 5) + t1.insert(value: 5, for: 5) + t1.insert(value: 6, for: 6) + + XCTAssert(t1.index(of: 1) == 0, "Test failed.") + XCTAssert(t1.index(of: 6) == 6, "Test failed.") + XCTAssert(t1.index(of: 100) == -1, "Test failed.") + } + + func testOperands() { + var t1 = RedBlackTree(uniqueKeys: true) + t1.insert((1, 1), (2, 2), (3, 3), (4, 4)) + XCTAssertEqual(4, t1.count, "Test failed.") + + var t2 = RedBlackTree(uniqueKeys: true) + t2.insert((5, 5), (6, 6), (7, 7), (8, 8)) + XCTAssertEqual(4, t2.count, "Test failed.") + + let t3 = t1 + t2 + XCTAssertEqual(8, t3.count, "Test failed.") + + XCTAssert(t1 != t2, "Test failed.") + XCTAssert(t3 != t2, "Test failed.") + + XCTAssert(t3 == (t1 + t2), "Test failed.") + } + + func testPerformance() { + measure {} } - } - - func testIndexOfUniqueKeys() { - var t1 = RedBlackTree(uniqueKeys: true) - t1.insert(value: 1, for: 1) - t1.insert(value: 2, for: 2) - t1.insert(value: 3, for: 3) - t1.insert(value: 4, for: 4) - t1.insert(value: 5, for: 5) - t1.insert(value: 5, for: 5) - t1.insert(value: 6, for: 6) - - XCTAssert(0 == t1.index(of: 1), "Test failed.") - XCTAssert(5 == t1.index(of: 6), "Test failed.") - XCTAssert(-1 == t1.index(of: 100), "Test failed.") - } - - func testIndexOfNonUniqueKeys() { - var t1 = RedBlackTree() - t1.insert(value: 1, for: 1) - t1.insert(value: 2, for: 2) - t1.insert(value: 3, for: 3) - t1.insert(value: 4, for: 4) - t1.insert(value: 5, for: 5) - t1.insert(value: 5, for: 5) - t1.insert(value: 6, for: 6) - - XCTAssert(0 == t1.index(of: 1), "Test failed.") - XCTAssert(6 == t1.index(of: 6), "Test failed.") - XCTAssert(-1 == t1.index(of: 100), "Test failed.") - } - - func testOperands() { - var t1 = RedBlackTree(uniqueKeys: true) - t1.insert((1, 1), (2, 2), (3, 3), (4, 4)) - XCTAssertEqual(4, t1.count, "Test failed.") - - var t2 = RedBlackTree(uniqueKeys: true) - t2.insert((5, 5), (6, 6), (7, 7), (8, 8)) - XCTAssertEqual(4, t2.count, "Test failed.") - - let t3 = t1 + t2 - XCTAssertEqual(8, t3.count, "Test failed.") - - XCTAssert(t1 != t2, "Test failed.") - XCTAssert(t3 != t2, "Test failed.") - - XCTAssert(t3 == (t1 + t2), "Test failed.") - } - - func testPerformance() { - self.measure() {} - } } diff --git a/Tests/SortedDictionaryTests.swift b/Tests/SortedDictionaryTests.swift index 459337a..3319c8f 100644 --- a/Tests/SortedDictionaryTests.swift +++ b/Tests/SortedDictionaryTests.swift @@ -23,135 +23,134 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class SortedDictionaryTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var s = SortedDictionary() - - XCTAssert(0 == s.count, "Test failed, got \(s.count).") - - for _ in 0..<1000 { - s.insert((1, 1)) - s.insert((2, 2)) - s.insert((3, 3)) + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testInt() { + var s = SortedDictionary() + + XCTAssert(s.count == 0, "Test failed, got \(s.count).") + + for _ in 0 ..< 1000 { + s.insert((1, 1)) + s.insert((2, 2)) + s.insert((3, 3)) + } + + XCTAssert(s.count == 3, "Test failed.") + XCTAssert(s[0].value == 1, "Test failed.") + XCTAssert(s[1].value == 2, "Test failed.") + XCTAssert(s[2].value == 3, "Test failed.") + + for _ in 0 ..< 500 { + s.removeValue(for: 1) + s.removeValue(for: 3) + } + + XCTAssert(s.count == 1, "Test failed.") + s.removeValue(for: 2) + + s.insert((2, 10)) + XCTAssert(s.count == 1, "Test failed.") + XCTAssert(s.findValue(for: 2) == 10, "Test failed.") + XCTAssert(s[0].value! == 10, "Test failed.") + + s.removeValue(for: 2) + XCTAssert(s.count == 0, "Test failed.") + + s.insert((1, 1)) + s.insert((2, 2)) + s.insert((3, 3)) + s.insert((3, 3)) + s.update(value: 5, for: 3) + + let subs: SortedDictionary = s.search(for: 3) + XCTAssert(subs.count == 1, "Test failed.") + + let generator = subs.makeIterator() + while let x = generator.next() { + XCTAssert(x.value == 5, "Test failed.") + } + + for i in 0 ..< s.endIndex { + s[i] = (s[i].key, 100) + XCTAssert(s[i].value == 100, "Test failed.") + } + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") + } + + func testIndexOf() { + var d1 = SortedDictionary() + d1.insert(value: 1, for: 1) + d1.insert(value: 2, for: 2) + d1.insert(value: 3, for: 3) + d1.insert(value: 4, for: 4) + d1.insert(value: 5, for: 5) + d1.insert(value: 5, for: 5) + d1.insert(value: 6, for: 6) + + XCTAssert(d1.index(of: 1) == 0, "Test failed.") + XCTAssert(d1.index(of: 6) == 5, "Test failed.") + XCTAssert(d1.index(of: 100) == -1, "Test failed.") } - - XCTAssert(3 == s.count, "Test failed.") - XCTAssert(1 == s[0].value, "Test failed.") - XCTAssert(2 == s[1].value, "Test failed.") - XCTAssert(3 == s[2].value, "Test failed.") - - for _ in 0..<500 { - s.removeValue(for: 1) - s.removeValue(for: 3) + + func testKeys() { + let s = SortedDictionary(elements: ("adam", 1), ("daniel", 2), ("mike", 3), ("natalie", 4)) + XCTAssert(s.keys == ["adam", "daniel", "mike", "natalie"], "Test failed.") } - - XCTAssert(1 == s.count, "Test failed.") - s.removeValue(for: 2) - - s.insert((2, 10)) - XCTAssert(1 == s.count, "Test failed.") - XCTAssert(10 == s.findValue(for: 2), "Test failed.") - XCTAssert(10 == s[0].value!, "Test failed.") - - s.removeValue(for: 2) - XCTAssert(0 == s.count, "Test failed.") - - s.insert((1, 1)) - s.insert((2, 2)) - s.insert((3, 3)) - s.insert((3, 3)) - s.update(value: 5, for: 3) - - let subs: SortedDictionary = s.search(for: 3) - XCTAssert(1 == subs.count, "Test failed.") - - let generator = subs.makeIterator() - while let x = generator.next() { - XCTAssert(5 == x.value, "Test failed.") + + func testValues() { + let s = SortedDictionary(elements: ("adam", 1), ("daniel", 2), ("mike", 3), ("natalie", 4)) + let values = [1, 2, 3, 4] + XCTAssert(values == s.values, "Test failed.") } - - for i in 0..(elements: (1, 1), (2, 2), (3, 3), (5, 5), (8, 8), (13, 13), (21, 21), (34, 34)) + + XCTAssert(s.findLowerEntry(for: -15) == nil, "Test failed.") + XCTAssert(s.findLowerEntry(for: 0) == nil, "Test failed.") + XCTAssert(s.findLowerEntry(for: 1) == 1, "Test failed.") + XCTAssert(s.findLowerEntry(for: 2) == 2, "Test failed.") + XCTAssert(s.findLowerEntry(for: 3) == 3, "Test failed.") + XCTAssert(s.findLowerEntry(for: 4) == 3, "Test failed.") + XCTAssert(s.findLowerEntry(for: 5) == 5, "Test failed.") + XCTAssert(s.findLowerEntry(for: 6) == 5, "Test failed.") + XCTAssert(s.findLowerEntry(for: 7) == 5, "Test failed.") + XCTAssert(s.findLowerEntry(for: 8) == 8, "Test failed.") + XCTAssert(s.findLowerEntry(for: 9) == 8, "Test failed.") + XCTAssert(s.findLowerEntry(for: 10) == 8, "Test failed.") + XCTAssert(s.findLowerEntry(for: 40) == 34, "Test failed.") + XCTAssert(s.findLowerEntry(for: 50) == 34, "Test failed.") + } + + func testCeilingEntry() { + let s = SortedDictionary(elements: (1, 1), (2, 2), (3, 3), (5, 5), (8, 8), (13, 13), (21, 21), (34, 34)) + + XCTAssert(s.findCeilingEntry(for: -15) == 1, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 0) == 1, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 1) == 1, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 2) == 2, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 3) == 3, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 4) == 5, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 5) == 5, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 6) == 8, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 7) == 8, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 8) == 8, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 9) == 13, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 10) == 13, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 40) == nil, "Test failed.") + XCTAssert(s.findCeilingEntry(for: 50) == nil, "Test failed.") } - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testIndexOf() { - var d1 = SortedDictionary() - d1.insert(value: 1, for: 1) - d1.insert(value: 2, for: 2) - d1.insert(value: 3, for: 3) - d1.insert(value: 4, for: 4) - d1.insert(value: 5, for: 5) - d1.insert(value: 5, for: 5) - d1.insert(value: 6, for: 6) - - XCTAssert(0 == d1.index(of: 1), "Test failed.") - XCTAssert(5 == d1.index(of: 6), "Test failed.") - XCTAssert(-1 == d1.index(of: 100), "Test failed.") - } - - func testKeys() { - let s = SortedDictionary(elements: ("adam", 1), ("daniel", 2), ("mike", 3), ("natalie", 4)) - XCTAssert(["adam", "daniel", "mike", "natalie"] == s.keys, "Test failed.") - } - - func testValues() { - let s = SortedDictionary(elements: ("adam", 1), ("daniel", 2), ("mike", 3), ("natalie", 4)) - let values = [1, 2, 3, 4] - XCTAssert(values == s.values, "Test failed.") - } - - func testLowerEntry() { - let s = SortedDictionary(elements: (1, 1), (2, 2), (3, 3), (5, 5), (8, 8), (13, 13), (21, 21), (34, 34)) - - XCTAssert(s.findLowerEntry(for: -15) == nil, "Test failed.") - XCTAssert(s.findLowerEntry(for: 0) == nil, "Test failed.") - XCTAssert(s.findLowerEntry(for: 1) == 1, "Test failed.") - XCTAssert(s.findLowerEntry(for: 2) == 2, "Test failed.") - XCTAssert(s.findLowerEntry(for: 3) == 3, "Test failed.") - XCTAssert(s.findLowerEntry(for: 4) == 3, "Test failed.") - XCTAssert(s.findLowerEntry(for: 5) == 5, "Test failed.") - XCTAssert(s.findLowerEntry(for: 6) == 5, "Test failed.") - XCTAssert(s.findLowerEntry(for: 7) == 5, "Test failed.") - XCTAssert(s.findLowerEntry(for: 8) == 8, "Test failed.") - XCTAssert(s.findLowerEntry(for: 9) == 8, "Test failed.") - XCTAssert(s.findLowerEntry(for: 10) == 8, "Test failed.") - XCTAssert(s.findLowerEntry(for: 40) == 34, "Test failed.") - XCTAssert(s.findLowerEntry(for: 50) == 34, "Test failed.") - } - - func testCeilingEntry() { - let s = SortedDictionary(elements: (1, 1), (2, 2), (3, 3), (5, 5), (8, 8), (13, 13), (21, 21), (34, 34)) - - XCTAssert(s.findCeilingEntry(for: -15) == 1, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 0) == 1, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 1) == 1, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 2) == 2, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 3) == 3, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 4) == 5, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 5) == 5, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 6) == 8, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 7) == 8, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 8) == 8, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 9) == 13, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 10) == 13, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 40) == nil, "Test failed.") - XCTAssert(s.findCeilingEntry(for: 50) == nil, "Test failed.") - } } diff --git a/Tests/SortedMultiDictionaryTests.swift b/Tests/SortedMultiDictionaryTests.swift index d286342..61b5e31 100644 --- a/Tests/SortedMultiDictionaryTests.swift +++ b/Tests/SortedMultiDictionaryTests.swift @@ -23,102 +23,101 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class SortedMultiDictionaryTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var s = SortedMultiDictionary() - - XCTAssert(0 == s.count, "Test failed, got \(s.count).") - - for _ in 0..<1000 { - s.insert((1, 1)) - s.insert((2, 2)) - s.insert((3, 3)) + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testInt() { + var s = SortedMultiDictionary() + + XCTAssert(s.count == 0, "Test failed, got \(s.count).") + + for _ in 0 ..< 1000 { + s.insert((1, 1)) + s.insert((2, 2)) + s.insert((3, 3)) + } + + XCTAssert(s.count == 3000, "Test failed.") + XCTAssert(s[0].value == 1, "Test failed.") + XCTAssert(s[1].value == 1, "Test failed.") + XCTAssert(s[2].value == 1, "Test failed.") + + for _ in 0 ..< 500 { + s.removeValue(for: 1) + s.removeValue(for: 3) + } + + XCTAssert(s.count == 1000, "Test failed.") + s.removeValue(for: 2) + + s.insert((2, 10)) + XCTAssert(s.count == 1, "Test failed.") + XCTAssert(s.findValue(for: 2) == 10, "Test failed.") + XCTAssert(s[0].value! == 10, "Test failed.") + + s.removeValue(for: 2) + XCTAssert(s.count == 0, "Test failed.") + + s.insert((1, 1)) + s.insert((2, 2)) + s.insert((3, 3)) + s.insert((3, 3)) + s.update(value: 5, for: 3) + + let subs = s.search(for: 3) + XCTAssert(subs.count == 2, "Test failed.") + + let generator = subs.makeIterator() + while let x = generator.next() { + XCTAssert(x.value == 5, "Test failed.") + } + + for i in 0 ..< s.endIndex { + s[i] = (s[i].key, 100) + XCTAssert(s[i].value == 100, "Test failed.") + } + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") } - - XCTAssert(3000 == s.count, "Test failed.") - XCTAssert(1 == s[0].value, "Test failed.") - XCTAssert(1 == s[1].value, "Test failed.") - XCTAssert(1 == s[2].value, "Test failed.") - - for _ in 0..<500 { - s.removeValue(for: 1) - s.removeValue(for: 3) + + func testIndexOf() { + var d1 = SortedMultiDictionary() + d1.insert(value: 1, for: 1) + d1.insert(value: 2, for: 2) + d1.insert(value: 3, for: 3) + d1.insert(value: 4, for: 4) + d1.insert(value: 5, for: 5) + d1.insert(value: 5, for: 5) + d1.insert(value: 6, for: 6) + + XCTAssert(d1.index(of: 1) == 0, "Test failed.") + XCTAssert(d1.index(of: 6) == 6, "Test failed.") + XCTAssert(d1.index(of: 100) == -1, "Test failed.") + } + + func testKeys() { + let s = SortedMultiDictionary(elements: ("adam", 1), ("daniel", 2), ("mike", 3), ("natalie", 4)) + let keys = SortedMultiSet(elements: "adam", "daniel", "mike", "natalie") + XCTAssert(keys.asArray == s.keys, "Test failed.") } - - XCTAssert(1000 == s.count, "Test failed.") - s.removeValue(for: 2) - - s.insert((2, 10)) - XCTAssert(1 == s.count, "Test failed.") - XCTAssert(10 == s.findValue(for: 2), "Test failed.") - XCTAssert(10 == s[0].value!, "Test failed.") - - s.removeValue(for: 2) - XCTAssert(0 == s.count, "Test failed.") - - s.insert((1, 1)) - s.insert((2, 2)) - s.insert((3, 3)) - s.insert((3, 3)) - s.update(value: 5, for: 3) - - let subs = s.search(for: 3) - XCTAssert(2 == subs.count, "Test failed.") - - let generator = subs.makeIterator() - while let x = generator.next() { - XCTAssert(5 == x.value, "Test failed.") + + func testValues() { + let s = SortedMultiDictionary(elements: ("adam", 1), ("daniel", 2), ("mike", 3), ("natalie", 4)) + let values = [1, 2, 3, 4] + XCTAssert(values == s.values, "Test failed.") } - - for i in 0..() - d1.insert(value: 1, for: 1) - d1.insert(value: 2, for: 2) - d1.insert(value: 3, for: 3) - d1.insert(value: 4, for: 4) - d1.insert(value: 5, for: 5) - d1.insert(value: 5, for: 5) - d1.insert(value: 6, for: 6) - - XCTAssert(0 == d1.index(of: 1), "Test failed.") - XCTAssert(6 == d1.index(of: 6), "Test failed.") - XCTAssert(-1 == d1.index(of: 100), "Test failed.") - } - - func testKeys() { - let s = SortedMultiDictionary(elements: ("adam", 1), ("daniel", 2), ("mike", 3), ("natalie", 4)) - let keys = SortedMultiSet(elements: "adam", "daniel", "mike", "natalie") - XCTAssert(keys.asArray == s.keys, "Test failed.") - } - - func testValues() { - let s = SortedMultiDictionary(elements: ("adam", 1), ("daniel", 2), ("mike", 3), ("natalie", 4)) - let values = [1, 2, 3, 4] - XCTAssert(values == s.values, "Test failed.") - } - - func testPerformance() { - self.measure() {} - } } diff --git a/Tests/SortedMultiSetTests.swift b/Tests/SortedMultiSetTests.swift index 0779292..eda5009 100644 --- a/Tests/SortedMultiSetTests.swift +++ b/Tests/SortedMultiSetTests.swift @@ -23,215 +23,214 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class SortedMultiSetTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var s = SortedMultiSet() - - XCTAssert(0 == s.count, "Test failed, got \(s.count).") - - for _ in 0..<1000 { - s.insert(1) - s.insert(2) - s.insert(3) - } - - XCTAssert(3000 == s.count, "Test failed.\(s)") - XCTAssert(1 == s[0], "Test failed.") - XCTAssert(2 == s[1000], "Test failed.") - XCTAssert(3 == s[2000], "Test failed.") - - for _ in 0..<500 { - s.remove(1) - s.remove(3) - } - - XCTAssert(1000 == s.count, "Test failed.") - s.remove(2) - s.remove(2) - s.insert(10) - XCTAssert(1 == s.count, "Test failed.") - - s.remove(10) - XCTAssert(0 == s.count, "Test failed.") - - s.insert(1) - s.insert(2) - s.insert(3) - - s.remove(1, 2) - XCTAssert(1 == s.count, "Test failed.") - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testRemove() { - var s1 = SortedMultiSet(elements: 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9) - s1.remove(1, 2, 3, 5) - XCTAssert(5 == s1.count, "Test failed.") - } - - func testIntersect() { - let s1 = SortedMultiSet(elements: 1, 1, 2, 3, 4, 5, 5) - let s2 = SortedMultiSet(elements: 1, 1, 2, 5, 6, 7, 8, 9, 10) - let s3 = SortedMultiSet(elements: 1, 1, 2, 5, 5, 10, 11, 12, 13, 14, 15) - - XCTAssert(SortedMultiSet(elements: 1, 1, 2, 5) == s1.intersection(s2), "Test failed. \(s1.intersection(s2))") - XCTAssert(SortedMultiSet(elements: 1, 1, 2, 5, 5) == s1.intersection(s3), "Test failed. \(s1.intersection(s3))") - } - - func testIntersectInPlace() { - var s1 = SortedMultiSet(elements: 1, 1, 2, 3, 4, 5) - var s2 = SortedMultiSet(elements: 1, 1, 2, 5, 6, 7, 8, 9, 10) - - s1.formIntersection(s2) - XCTAssert(SortedMultiSet(elements: 1, 1, 2, 5) == s1, "Test failed. \(s1)") - - s1.insert(3, 4, 5, 5, 5) - s2.insert(5) - - s1.formIntersection(s2) - XCTAssert(SortedMultiSet(elements: 1, 1, 2, 5, 5) == s1, "Test failed. \(s1)") - } - - func testIsDisjointWith() { - let s1 = SortedMultiSet(elements: 1, 2, 3) - let s2 = SortedMultiSet(elements: 3, 4, 5) - let s3 = SortedMultiSet(elements: 5, 6, 7) - - XCTAssertFalse(s1.isDisjoint(with: s2), "Test failed.") - XCTAssert(s1.isDisjoint(with: s3), "Test failed.") - XCTAssertFalse(s2.isDisjoint(with: s3), "Test failed.") - } - - func testSubtract() { - let s1 = SortedMultiSet(elements: 1, 2, 3, 3, 3, 4, 5) - let s2 = SortedMultiSet(elements: 4, 5, -1) - let s3 = SortedMultiSet(elements: 3, 5, 0, -7) - - XCTAssert(SortedMultiSet(elements: 1, 2, 3, 3, 3) == s1.subtracting(s2), "Test failed. \(s1.subtracting(s2))") - XCTAssert(SortedMultiSet(elements: 1, 2, 3, 3, 4) == s1.subtracting(s3), "Test failed. \(s1.subtracting(s3))") - } - - func testSubtractInPlace() { - var s1 = SortedMultiSet(elements: 1, 2, 3, 3, 3, 4, 5) - let s2 = SortedMultiSet(elements: 4, 5, -1) - let s3 = SortedMultiSet(elements: 3, 5, 0, -7) - - s1.subtract(s2) - XCTAssert(SortedMultiSet(elements: 1, 2, 3, 3, 3) == s1, "Test failed. \(s1)") - s1 = SortedMultiSet(elements: 1, 2, 3, 3, 3, 4, 5) - s1.subtract(s3) - XCTAssert(SortedMultiSet(elements: 1, 2, 3, 3, 4) == s1, "Test failed. \(s1)") - } - - func testUnion() { - let s1 = SortedMultiSet(elements: 0, 0, 1, 2, 3, 4, 7, 7, 5) - let s2 = SortedMultiSet(elements: 5, -1, 6, 8, 7, 9, 9) - - XCTAssert(SortedMultiSet(elements: -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9) == s1.union(s2), "Test failed. \(s1.union(s2))") - } - - func testUnionInPlace() { - var s1 = SortedMultiSet(elements: 0, 0, 1, 2, 3, 4, 7, 7, 5) - let s2 = SortedMultiSet(elements: 5, -1, 0, 6, 8, 7, 9, 9) - - s1.formUnion(s2) - XCTAssert(SortedMultiSet(elements: -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9) == s1, "Test failed. \(s1)") - } - - func testIsSubsetOf() { - let s1 = SortedMultiSet(elements: 1, 2, 2, 3) - let s2 = SortedMultiSet(elements: 1, 2, 2, 3, 4, 5) - let s3 = SortedMultiSet(elements: 2, 2, 3, 4, 5) - - XCTAssert(s1 <= s1, "Test failed. \(s1.intersection(s2))") - XCTAssert(s1 <= s2, "Test failed.") - XCTAssertFalse(s1 <= s3, "Test failed.") - } - - func testIsSupersetOf() { - let s1 = SortedMultiSet(elements: 1, 2, 3, 4, 5, 6, 7) - let s2 = SortedMultiSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedMultiSet(elements: 5, 6, 7, 8) - - XCTAssert(s1 >= s1, "Test failed.") - XCTAssert(s1 >= s2, "Test failed.") - XCTAssertFalse(s1 >= s3, "Test failed.") - } - - func testIsStrictSubsetOf() { - let s1 = SortedMultiSet(elements: 1, 2, 3) - let s2 = SortedMultiSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedMultiSet(elements: 2, 3, 4, 5) - - XCTAssert(s1 < s2, "Test failed.") - XCTAssertFalse(s1 < s3, "Test failed.") - } - - func testIsStrictSupersetOf() { - let s1 = SortedMultiSet(elements: 1, 2, 3, 4, 5, 6, 7) - let s2 = SortedMultiSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedMultiSet(elements: 5, 6, 7, 8) - - XCTAssert(s1 > s2, "Test failed.") - XCTAssertFalse(s1 > s3, "Test failed.") - } - - func testContains() { - let s1 = SortedMultiSet(elements: 1, 2, 3, 4, 5, 6, 7) - XCTAssert(s1.contains(1, 2, 3), "Test failed.") - XCTAssertFalse(s1.contains(1, 2, 3, 10), "Test failed.") - } - - func testExclusiveOr() { - let s1 = SortedMultiSet(elements: 1, 2, 2, 3, 4, 5, 6, 7) - let s2 = SortedMultiSet(elements: 1, 2, 3, 3, 4, 5) - let s3 = SortedMultiSet(elements: 5, 6, 7, 8) - - XCTAssert(SortedMultiSet(elements: 6, 7) == s1.symmetricDifference(s2), "Test failed. \(s1.symmetricDifference(s2))") - XCTAssert(SortedMultiSet(elements: 1, 2, 2, 3, 4, 8) == s1.symmetricDifference(s3), "Test failed. \(s1.symmetricDifference(s3))") - XCTAssert(SortedMultiSet(elements: 1, 2, 3, 3, 4, 6, 7, 8) == s2.symmetricDifference(s3), "Test failed.") - } - - func testExclusiveOrInPlace() { - var s1 = SortedMultiSet(elements: 1, 2, 2, 3, 4, 5, 6, 7) - var s2 = SortedMultiSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedMultiSet(elements: 5, 6, 7, 8) - - s1.formSymmetricDifference(s2) - XCTAssert(SortedMultiSet(elements: 6, 7) == s1, "Test failed.") - - s1 = SortedMultiSet(elements: 1, 2, 2, 3, 4, 5, 6, 7) - s1.formSymmetricDifference(s3) - XCTAssert(SortedMultiSet(elements: 1, 2, 2, 3, 4, 8) == s1, "Test failed. \(s1)") - - s2.formSymmetricDifference(s3) - XCTAssert(SortedMultiSet(elements: 1, 2, 3, 4, 6, 7, 8) == s2, "Test failed. \(s2)") - } - - func testIndexOf() { - var s1 = SortedMultiSet() - s1.insert(1, 2, 3, 4, 5, 5, 6, 7) - - XCTAssert(0 == s1.index(of: 1), "Test failed.") - XCTAssert(6 == s1.index(of: 6), "Test failed.") - XCTAssert(-1 == s1.index(of: 100), "Test failed.") - } - - func testPerformance() { - self.measure() {} - } + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testInt() { + var s = SortedMultiSet() + + XCTAssert(s.count == 0, "Test failed, got \(s.count).") + + for _ in 0 ..< 1000 { + s.insert(1) + s.insert(2) + s.insert(3) + } + + XCTAssert(s.count == 3000, "Test failed.\(s)") + XCTAssert(s[0] == 1, "Test failed.") + XCTAssert(s[1000] == 2, "Test failed.") + XCTAssert(s[2000] == 3, "Test failed.") + + for _ in 0 ..< 500 { + s.remove(1) + s.remove(3) + } + + XCTAssert(s.count == 1000, "Test failed.") + s.remove(2) + s.remove(2) + s.insert(10) + XCTAssert(s.count == 1, "Test failed.") + + s.remove(10) + XCTAssert(s.count == 0, "Test failed.") + + s.insert(1) + s.insert(2) + s.insert(3) + + s.remove(1, 2) + XCTAssert(s.count == 1, "Test failed.") + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") + } + + func testRemove() { + var s1 = SortedMultiSet(elements: 1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 9) + s1.remove(1, 2, 3, 5) + XCTAssert(s1.count == 5, "Test failed.") + } + + func testIntersect() { + let s1 = SortedMultiSet(elements: 1, 1, 2, 3, 4, 5, 5) + let s2 = SortedMultiSet(elements: 1, 1, 2, 5, 6, 7, 8, 9, 10) + let s3 = SortedMultiSet(elements: 1, 1, 2, 5, 5, 10, 11, 12, 13, 14, 15) + + XCTAssert(SortedMultiSets1.intersection(s2) == (elements: 1, 1, 2, 5), "Test failed. \(s1.intersection(s2))") + XCTAssert(SortedMultiSets1.intersection(s3) == (elements: 1, 1, 2, 5, 5), "Test failed. \(s1.intersection(s3))") + } + + func testIntersectInPlace() { + var s1 = SortedMultiSet(elements: 1, 1, 2, 3, 4, 5) + var s2 = SortedMultiSet(elements: 1, 1, 2, 5, 6, 7, 8, 9, 10) + + s1.formIntersection(s2) + XCTAssert(SortedMultiSets1 == (elements: 1, 1, 2, 5), "Test failed. \(s1)") + + s1.insert(3, 4, 5, 5, 5) + s2.insert(5) + + s1.formIntersection(s2) + XCTAssert(SortedMultiSets1 == (elements: 1, 1, 2, 5, 5), "Test failed. \(s1)") + } + + func testIsDisjointWith() { + let s1 = SortedMultiSet(elements: 1, 2, 3) + let s2 = SortedMultiSet(elements: 3, 4, 5) + let s3 = SortedMultiSet(elements: 5, 6, 7) + + XCTAssertFalse(s1.isDisjoint(with: s2), "Test failed.") + XCTAssert(s1.isDisjoint(with: s3), "Test failed.") + XCTAssertFalse(s2.isDisjoint(with: s3), "Test failed.") + } + + func testSubtract() { + let s1 = SortedMultiSet(elements: 1, 2, 3, 3, 3, 4, 5) + let s2 = SortedMultiSet(elements: 4, 5, -1) + let s3 = SortedMultiSet(elements: 3, 5, 0, -7) + + XCTAssert(SortedMultiSets1.subtracting(s2) == (elements: 1, 2, 3, 3, 3), "Test failed. \(s1.subtracting(s2))") + XCTAssert(SortedMultiSets1.subtracting(s3) == (elements: 1, 2, 3, 3, 4), "Test failed. \(s1.subtracting(s3))") + } + + func testSubtractInPlace() { + var s1 = SortedMultiSet(elements: 1, 2, 3, 3, 3, 4, 5) + let s2 = SortedMultiSet(elements: 4, 5, -1) + let s3 = SortedMultiSet(elements: 3, 5, 0, -7) + + s1.subtract(s2) + XCTAssert(SortedMultiSets1 == (elements: 1, 2, 3, 3, 3), "Test failed. \(s1)") + s1 = SortedMultiSet(elements: 1, 2, 3, 3, 3, 4, 5) + s1.subtract(s3) + XCTAssert(SortedMultiSets1 == (elements: 1, 2, 3, 3, 4), "Test failed. \(s1)") + } + + func testUnion() { + let s1 = SortedMultiSet(elements: 0, 0, 1, 2, 3, 4, 7, 7, 5) + let s2 = SortedMultiSet(elements: 5, -1, 6, 8, 7, 9, 9) + + XCTAssert(SortedMultiSet(elements: -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9) == s1.union(s2), "Test failed. \(s1.union(s2))") + } + + func testUnionInPlace() { + var s1 = SortedMultiSet(elements: 0, 0, 1, 2, 3, 4, 7, 7, 5) + let s2 = SortedMultiSet(elements: 5, -1, 0, 6, 8, 7, 9, 9) + + s1.formUnion(s2) + XCTAssert(SortedMultiSet(elements: -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9) == s1, "Test failed. \(s1)") + } + + func testIsSubsetOf() { + let s1 = SortedMultiSet(elements: 1, 2, 2, 3) + let s2 = SortedMultiSet(elements: 1, 2, 2, 3, 4, 5) + let s3 = SortedMultiSet(elements: 2, 2, 3, 4, 5) + + XCTAssert(s1 <= s1, "Test failed. \(s1.intersection(s2))") + XCTAssert(s1 <= s2, "Test failed.") + XCTAssertFalse(s1 <= s3, "Test failed.") + } + + func testIsSupersetOf() { + let s1 = SortedMultiSet(elements: 1, 2, 3, 4, 5, 6, 7) + let s2 = SortedMultiSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedMultiSet(elements: 5, 6, 7, 8) + + XCTAssert(s1 >= s1, "Test failed.") + XCTAssert(s1 >= s2, "Test failed.") + XCTAssertFalse(s1 >= s3, "Test failed.") + } + + func testIsStrictSubsetOf() { + let s1 = SortedMultiSet(elements: 1, 2, 3) + let s2 = SortedMultiSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedMultiSet(elements: 2, 3, 4, 5) + + XCTAssert(s1 < s2, "Test failed.") + XCTAssertFalse(s1 < s3, "Test failed.") + } + + func testIsStrictSupersetOf() { + let s1 = SortedMultiSet(elements: 1, 2, 3, 4, 5, 6, 7) + let s2 = SortedMultiSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedMultiSet(elements: 5, 6, 7, 8) + + XCTAssert(s1 > s2, "Test failed.") + XCTAssertFalse(s1 > s3, "Test failed.") + } + + func testContains() { + let s1 = SortedMultiSet(elements: 1, 2, 3, 4, 5, 6, 7) + XCTAssert(s1.contains(1, 2, 3), "Test failed.") + XCTAssertFalse(s1.contains(1, 2, 3, 10), "Test failed.") + } + + func testExclusiveOr() { + let s1 = SortedMultiSet(elements: 1, 2, 2, 3, 4, 5, 6, 7) + let s2 = SortedMultiSet(elements: 1, 2, 3, 3, 4, 5) + let s3 = SortedMultiSet(elements: 5, 6, 7, 8) + + XCTAssert(SortedMultiSets1.symmetricDifference(s2) == (elements: 6, 7), "Test failed. \(s1.symmetricDifference(s2))") + XCTAssert(SortedMultiSets1.symmetricDifference(s3) == (elements: 1, 2, 2, 3, 4, 8), "Test failed. \(s1.symmetricDifference(s3))") + XCTAssert(SortedMultiSets2.symmetricDifference(s3) == (elements: 1, 2, 3, 3, 4, 6, 7, 8), "Test failed.") + } + + func testExclusiveOrInPlace() { + var s1 = SortedMultiSet(elements: 1, 2, 2, 3, 4, 5, 6, 7) + var s2 = SortedMultiSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedMultiSet(elements: 5, 6, 7, 8) + + s1.formSymmetricDifference(s2) + XCTAssert(SortedMultiSets1 == (elements: 6, 7), "Test failed.") + + s1 = SortedMultiSet(elements: 1, 2, 2, 3, 4, 5, 6, 7) + s1.formSymmetricDifference(s3) + XCTAssert(SortedMultiSets1 == (elements: 1, 2, 2, 3, 4, 8), "Test failed. \(s1)") + + s2.formSymmetricDifference(s3) + XCTAssert(SortedMultiSets2 == (elements: 1, 2, 3, 4, 6, 7, 8), "Test failed. \(s2)") + } + + func testIndexOf() { + var s1 = SortedMultiSet() + s1.insert(1, 2, 3, 4, 5, 5, 6, 7) + + XCTAssert(s1.index(of: 1) == 0, "Test failed.") + XCTAssert(s1.index(of: 6) == 6, "Test failed.") + XCTAssert(s1.index(of: 100) == -1, "Test failed.") + } + + func testPerformance() { + measure {} + } } diff --git a/Tests/SortedSetTest.swift b/Tests/SortedSetTest.swift index 649db1e..a88372e 100644 --- a/Tests/SortedSetTest.swift +++ b/Tests/SortedSetTest.swift @@ -23,256 +23,255 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class SortedSetTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var s = SortedSet() - - XCTAssert(0 == s.count, "Test failed, got \(s.count).") - - for _ in 0..<1000 { - s.insert(1) - s.insert(2) - s.insert(3) + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testInt() { + var s = SortedSet() + + XCTAssert(s.count == 0, "Test failed, got \(s.count).") + + for _ in 0 ..< 1000 { + s.insert(1) + s.insert(2) + s.insert(3) + } + + XCTAssert(s.count == 3, "Test failed.\(s)") + XCTAssert(s[0] == 1, "Test failed.") + XCTAssert(s[1] == 2, "Test failed.") + XCTAssert(s[2] == 3, "Test failed.") + + for _ in 0 ..< 500 { + s.remove(1) + s.remove(3) + } + + XCTAssert(s.count == 1, "Test failed.") + + s.remove(2) + s.insert(10) + XCTAssert(s.count == 1, "Test failed.") + + s.remove(10) + XCTAssert(s.count == 0, "Test failed.") + + s.insert(1) + s.insert(2) + s.insert(3) + s.remove(1, 2) + XCTAssert(s.count == 1, "Test failed.") + + s.removeAll() + XCTAssert(s.count == 0, "Test failed.") + } + + func testRemove() { + var s1 = SortedSet(elements: 22, 23, 1, 2, 3, 4, 5) + s1.remove(1, 2, 3) + XCTAssert(s1.count == 4, "Test failed.") + } + + func testIntersect() { + let s1 = SortedSet(elements: 22, 23, 1, 2, 3, 4, 5) + let s2 = SortedSet(elements: 22, 23, 5, 6, 7, 8, 9, 10) + + XCTAssert(SortedSets1.intersection(s2) == (elements: 22, 23, 5), "Test failed. \(s1.intersection(s2))") + + XCTAssert(SortedSets1.intersection(SortedSet()) == (), "Test failed. \(s1)") + + let s3 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9) + let s4 = SortedSet(elements: 11, 9, 7, 3, 8, 100, 99, 88, 77) + XCTAssert(SortedSets3.intersection(s4) == (elements: 9, 3, 7, 8), "Test failed.") + } + + func testIntersectInPlace() { + var s1 = SortedSet(elements: 22, 23, 1, 2, 3, 4, 5) + let s2 = SortedSet(elements: 22, 23, 5, 6, 7, 8, 9, 10) + + s1.formIntersection(s2) + XCTAssert(SortedSets1 == (elements: 22, 23, 5), "Test failed. \(s1)") + + s1.formIntersection(SortedSet()) + XCTAssert(SortedSets1 == (), "Test failed. \(s1)") + + var s3 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9) + let s4 = SortedSet(elements: 11, 9, 7, 3, 8, 100, 99, 88, 77) + s3.formIntersection(s4) + XCTAssert(SortedSets3 == (elements: 9, 3, 7, 8), "Test failed.") + } + + func testSubtract() { + let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 7, 8, 9, 10) + let s2 = SortedSet(elements: 4, 5, 6, 7) + + XCTAssert(SortedSets1.subtracting(s2) == (elements: 1, 2, 3, 8, 9, 10), "Test failed. \(s1.subtracting(s2))") + + let s3 = SortedSet(elements: 0, -1, -2, -7, 99, 100) + let s4 = SortedSet(elements: -3, -5, -7, 99) + XCTAssert(SortedSet(elements: 0, -1, -2, 100) == s3.subtracting(s4), "Test failed. \(s3.subtracting(s4))") + } + + func testSubtractInPlace() { + var s1 = SortedSet(elements: 1, 2, 3, 4, 5, 7, 8, 9, 10) + let s2 = SortedSet(elements: 4, 5, 6, 7) + + s1.subtract(s2) + XCTAssert(SortedSets1 == (elements: 1, 2, 3, 8, 9, 10), "Test failed. \(s1)") + + var s3 = SortedSet(elements: 0, -1, -2, -7, 99, 100) + let s4 = SortedSet(elements: -3, -5, -7, 99) + s3.subtract(s4) + XCTAssert(SortedSet(elements: 0, -1, -2, 100) == s3, "Test failed. \(s3)") + } + + func testUnion() { + let s1 = SortedSet(elements: 1, 2, 3, 4, 5) + let s2 = SortedSet(elements: 5, 6, 7, 8, 9) + let s3 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7, 8, 9) + + XCTAssert(s3 == s1.union(s2), "Test failed.") + } + + func testUnionInPlace() { + var s1 = SortedSet(elements: 1, 2, 3, 4, 5) + let s2 = SortedSet(elements: 5, 6, 7, 8, 9) + let s3 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7, 8, 9) + + s1.formUnion(s2) + XCTAssert(s3 == s1, "Test failed.") + } + + func testExclusiveOr() { + let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) + let s2 = SortedSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedSet(elements: 5, 6, 7, 8) + + XCTAssert(SortedSets1.symmetricDifference(s2) == (elements: 6, 7), "Test failed. \(s1.symmetricDifference(s2))") + XCTAssert(SortedSets1.symmetricDifference(s3) == (elements: 1, 2, 3, 4, 8), "Test failed.") + XCTAssert(SortedSets2.symmetricDifference(s3) == (elements: 1, 2, 3, 4, 6, 7, 8), "Test failed.") + } + + func testExclusiveOrInPlace() { + var s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) + var s2 = SortedSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedSet(elements: 5, 6, 7, 8) + + s1.formSymmetricDifference(s2) + XCTAssert(SortedSets1 == (elements: 6, 7), "Test failed. \(s1)") + + s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) + s1.formSymmetricDifference(s3) + XCTAssert(SortedSets1 == (elements: 1, 2, 3, 4, 8), "Test failed. \(s1)") + + s2.formSymmetricDifference(s3) + XCTAssert(SortedSets2 == (elements: 1, 2, 3, 4, 6, 7, 8), "Test failed. \(s2)") + } + + func testIsDisjointWith() { + let s1 = SortedSet(elements: 1, 2, 3) + let s2 = SortedSet(elements: 3, 4, 5) + let s3 = SortedSet(elements: 5, 6, 7) + + XCTAssertFalse(s1.isDisjoint(with: s2), "Test failed. \(s1.isDisjoint(with: s2))") + XCTAssert(s1.isDisjoint(with: s3), "Test failed.") + XCTAssertFalse(s2.isDisjoint(with: s3), "Test failed.") + } + + func testIsSubsetOf() { + let s1 = SortedSet(elements: 1, 2, 3) + let s2 = SortedSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedSet(elements: 2, 3, 4, 5) + + XCTAssert(s1 <= s1, "Test failed.") + XCTAssert(s1 <= s2, "Test failed.") + XCTAssertFalse(s1 <= s3, "Test failed.") + } + + func testIsSupersetOf() { + let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) + let s2 = SortedSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedSet(elements: 5, 6, 7, 8) + + XCTAssert(s1 >= s1, "Test failed.") + XCTAssert(s1 >= s2, "Test failed.") + XCTAssertFalse(s1 >= s3, "Test failed.") + } + + func testIsStrictSubsetOf() { + let s1 = SortedSet(elements: 1, 2, 3) + let s2 = SortedSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedSet(elements: 2, 3, 4, 5) + + XCTAssert(s1 < s2, "Test failed.") + XCTAssertFalse(s1 < s3, "Test failed.") + } + + func testIsStrictSupersetOf() { + let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) + let s2 = SortedSet(elements: 1, 2, 3, 4, 5) + let s3 = SortedSet(elements: 5, 6, 7, 8) + + XCTAssert(s1 > s2, "Test failed.") + XCTAssertFalse(s1 > s3, "Test failed.") + } + + func testContains() { + let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) + XCTAssert(s1.contains(1, 2, 3), "Test failed.") + XCTAssertFalse(s1.contains(1, 2, 3, 10), "Test failed.") + } + + func testIndexOf() { + var s1 = SortedSet() + s1.insert(1, 2, 3, 4, 5, 6, 7) + + XCTAssert(s1.index(of: 1) == 0, "Test failed.") + XCTAssert(s1.index(of: 6) == 5, "Test failed.") + XCTAssert(s1.index(of: 100) == -1, "Test failed.") + } + + func testExample() { + let setA = SortedSet(elements: 1, 2, 3) // Sorted: [1, 2, 3] + let setB = SortedSet(elements: 4, 3, 6) // Sorted: [3, 4, 6] + + let setC = SortedSet(elements: 7, 1, 2) // Sorted: [1, 2, 7] + let setD = SortedSet(elements: 1, 7) // Sorted: [1, 7] + + let setE = SortedSet(elements: 1, 6, 7) // Sorted: [1, 6, 7] + + // Union. + print((setA + setB).count) // Output: 5 + print(setA.union(setB).count) // Output: 5 + + // Intersect. + print(setC.intersection(setD).count) // Output: 2 + + // Subset. + print(setD < setC) // true + print(setD.isSubset(of: setC)) // true + + // Superset. + print(setD > setC) // false + print(setD.isSuperset(of: setC)) // false + + // Contains. + print(setE.contains(setA.first!)) // true + + // Probability. + print(setE.probability(of: setA.first!, setA.last!)) // 0.333333333333333 } - - XCTAssert(3 == s.count, "Test failed.\(s)") - XCTAssert(1 == s[0], "Test failed.") - XCTAssert(2 == s[1], "Test failed.") - XCTAssert(3 == s[2], "Test failed.") - - for _ in 0..<500 { - s.remove(1) - s.remove(3) + + func testPerformance() { + measure {} } - - XCTAssert(1 == s.count, "Test failed.") - - s.remove(2) - s.insert(10) - XCTAssert(1 == s.count, "Test failed.") - - s.remove(10) - XCTAssert(0 == s.count, "Test failed.") - - s.insert(1) - s.insert(2) - s.insert(3) - s.remove(1, 2) - XCTAssert(1 == s.count, "Test failed.") - - s.removeAll() - XCTAssert(0 == s.count, "Test failed.") - } - - func testRemove() { - var s1 = SortedSet(elements: 22, 23, 1, 2, 3, 4, 5) - s1.remove(1, 2, 3) - XCTAssert(4 == s1.count, "Test failed.") - } - - func testIntersect() { - let s1 = SortedSet(elements: 22, 23, 1, 2, 3, 4, 5) - let s2 = SortedSet(elements: 22, 23, 5, 6, 7, 8, 9, 10) - - XCTAssert(SortedSet(elements: 22, 23, 5) == s1.intersection(s2), "Test failed. \(s1.intersection(s2))") - - XCTAssert(SortedSet() == s1.intersection(SortedSet()), "Test failed. \(s1)") - - let s3 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9) - let s4 = SortedSet(elements: 11, 9, 7, 3, 8, 100, 99, 88, 77) - XCTAssert(SortedSet(elements: 9, 3, 7, 8) == s3.intersection(s4), "Test failed.") - } - - func testIntersectInPlace() { - var s1 = SortedSet(elements: 22, 23, 1, 2, 3, 4, 5) - let s2 = SortedSet(elements: 22, 23, 5, 6, 7, 8, 9, 10) - - s1.formIntersection(s2) - XCTAssert(SortedSet(elements: 22, 23, 5) == s1, "Test failed. \(s1)") - - s1.formIntersection(SortedSet()) - XCTAssert(SortedSet() == s1, "Test failed. \(s1)") - - var s3 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9) - let s4 = SortedSet(elements: 11, 9, 7, 3, 8, 100, 99, 88, 77) - s3.formIntersection(s4) - XCTAssert(SortedSet(elements: 9, 3, 7, 8) == s3, "Test failed.") - } - - func testSubtract() { - let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 7, 8, 9, 10) - let s2 = SortedSet(elements: 4, 5, 6, 7) - - XCTAssert(SortedSet(elements: 1, 2, 3, 8, 9, 10) == s1.subtracting(s2), "Test failed. \(s1.subtracting(s2))") - - let s3 = SortedSet(elements: 0, -1, -2, -7, 99, 100) - let s4 = SortedSet(elements: -3, -5, -7, 99) - XCTAssert(SortedSet(elements: 0, -1, -2, 100) == s3.subtracting(s4), "Test failed. \(s3.subtracting(s4))") - } - - func testSubtractInPlace() { - var s1 = SortedSet(elements: 1, 2, 3, 4, 5, 7, 8, 9, 10) - let s2 = SortedSet(elements: 4, 5, 6, 7) - - s1.subtract(s2) - XCTAssert(SortedSet(elements: 1, 2, 3, 8, 9, 10) == s1, "Test failed. \(s1)") - - var s3 = SortedSet(elements: 0, -1, -2, -7, 99, 100) - let s4 = SortedSet(elements: -3, -5, -7, 99) - s3.subtract(s4) - XCTAssert(SortedSet(elements: 0, -1, -2, 100) == s3, "Test failed. \(s3)") - } - - func testUnion() { - let s1 = SortedSet(elements: 1, 2, 3, 4, 5) - let s2 = SortedSet(elements: 5, 6, 7, 8, 9) - let s3 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7, 8, 9) - - XCTAssert(s3 == s1.union(s2), "Test failed.") - } - - func testUnionInPlace() { - var s1 = SortedSet(elements: 1, 2, 3, 4, 5) - let s2 = SortedSet(elements: 5, 6, 7, 8, 9) - let s3 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7, 8, 9) - - s1.formUnion(s2) - XCTAssert(s3 == s1, "Test failed.") - } - - func testExclusiveOr() { - let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) - let s2 = SortedSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedSet(elements: 5, 6, 7, 8) - - XCTAssert(SortedSet(elements: 6, 7) == s1.symmetricDifference(s2), "Test failed. \(s1.symmetricDifference(s2))") - XCTAssert(SortedSet(elements: 1, 2, 3, 4, 8) == s1.symmetricDifference(s3), "Test failed.") - XCTAssert(SortedSet(elements: 1, 2, 3, 4, 6, 7, 8) == s2.symmetricDifference(s3), "Test failed.") - } - - func testExclusiveOrInPlace() { - var s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) - var s2 = SortedSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedSet(elements: 5, 6, 7, 8) - - s1.formSymmetricDifference(s2) - XCTAssert(SortedSet(elements: 6, 7) == s1, "Test failed. \(s1)") - - s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) - s1.formSymmetricDifference(s3) - XCTAssert(SortedSet(elements: 1, 2, 3, 4, 8) == s1, "Test failed. \(s1)") - - s2.formSymmetricDifference(s3) - XCTAssert(SortedSet(elements: 1, 2, 3, 4, 6, 7, 8) == s2, "Test failed. \(s2)") - } - - func testIsDisjointWith() { - let s1 = SortedSet(elements: 1, 2, 3) - let s2 = SortedSet(elements: 3, 4, 5) - let s3 = SortedSet(elements: 5, 6, 7) - - XCTAssertFalse(s1.isDisjoint(with: s2), "Test failed. \(s1.isDisjoint(with: s2))") - XCTAssert(s1.isDisjoint(with: s3), "Test failed.") - XCTAssertFalse(s2.isDisjoint(with: s3), "Test failed.") - } - - func testIsSubsetOf() { - let s1 = SortedSet(elements: 1, 2, 3) - let s2 = SortedSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedSet(elements: 2, 3, 4, 5) - - XCTAssert(s1 <= s1, "Test failed.") - XCTAssert(s1 <= s2, "Test failed.") - XCTAssertFalse(s1 <= s3, "Test failed.") - } - - func testIsSupersetOf() { - let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) - let s2 = SortedSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedSet(elements: 5, 6, 7, 8) - - XCTAssert(s1 >= s1, "Test failed.") - XCTAssert(s1 >= s2, "Test failed.") - XCTAssertFalse(s1 >= s3, "Test failed.") - } - - func testIsStrictSubsetOf() { - let s1 = SortedSet(elements: 1, 2, 3) - let s2 = SortedSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedSet(elements: 2, 3, 4, 5) - - XCTAssert(s1 < s2, "Test failed.") - XCTAssertFalse(s1 < s3, "Test failed.") - } - - func testIsStrictSupersetOf() { - let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) - let s2 = SortedSet(elements: 1, 2, 3, 4, 5) - let s3 = SortedSet(elements: 5, 6, 7, 8) - - XCTAssert(s1 > s2, "Test failed.") - XCTAssertFalse(s1 > s3, "Test failed.") - } - - func testContains() { - let s1 = SortedSet(elements: 1, 2, 3, 4, 5, 6, 7) - XCTAssert(s1.contains(1, 2, 3), "Test failed.") - XCTAssertFalse(s1.contains(1, 2, 3, 10), "Test failed.") - } - - func testIndexOf() { - var s1 = SortedSet() - s1.insert(1, 2, 3, 4, 5, 6, 7) - - XCTAssert(0 == s1.index(of: 1), "Test failed.") - XCTAssert(5 == s1.index(of: 6), "Test failed.") - XCTAssert(-1 == s1.index(of: 100), "Test failed.") - } - - func testExample() { - let setA = SortedSet(elements: 1, 2, 3) // Sorted: [1, 2, 3] - let setB = SortedSet(elements: 4, 3, 6) // Sorted: [3, 4, 6] - - let setC = SortedSet(elements: 7, 1, 2) // Sorted: [1, 2, 7] - let setD = SortedSet(elements: 1, 7) // Sorted: [1, 7] - - let setE = SortedSet(elements: 1, 6, 7) // Sorted: [1, 6, 7] - - // Union. - print((setA + setB).count) // Output: 5 - print(setA.union(setB).count) // Output: 5 - - // Intersect. - print(setC.intersection(setD).count) // Output: 2 - - // Subset. - print(setD < setC) // true - print(setD.isSubset(of: setC)) // true - - // Superset. - print(setD > setC) // false - print(setD.isSuperset(of: setC)) // false - - // Contains. - print(setE.contains(setA.first!)) // true - - // Probability. - print(setE.probability(of: setA.first!, setA.last!)) // 0.333333333333333 - } - - func testPerformance() { - self.measure() {} - } } diff --git a/Tests/StackTests.swift b/Tests/StackTests.swift index 68536ce..5016b4b 100644 --- a/Tests/StackTests.swift +++ b/Tests/StackTests.swift @@ -23,67 +23,66 @@ * THE SOFTWARE. */ -import XCTest @testable import Algorithm +import XCTest class StackTests: XCTestCase { - - override func setUp() { - super.setUp() - } - - override func tearDown() { - super.tearDown() - } - - func testInt() { - var s = Stack() - - s.push(1) - s.push(2) - s.push(3) - - XCTAssert(3 == s.count, "Count incorrect, got \(s.count).") - XCTAssert(3 == s.top, "Top incorrect, got \(String(describing: s.top))") - - s.push(5) - s.push(6) - s.push(7) - - XCTAssert(6 == s.count, "Count incorrect, got \(s.count).") - XCTAssert(7 == s.top, "Top incorrect, got \(String(describing: s.top))") - - XCTAssert(7 == s.pop() && 5 == s.count && 6 == s.top, "Pop incorrect") - XCTAssert(6 == s.pop() && 4 == s.count && 5 == s.top, "Pop incorrect") - XCTAssert(5 == s.pop() && 3 == s.count && 3 == s.top, "Pop incorrect") - XCTAssert(3 == s.pop() && 2 == s.count && 2 == s.top, "Pop incorrect") - XCTAssert(2 == s.pop() && 1 == s.count && 1 == s.top, "Pop incorrect") - XCTAssert(1 == s.pop() && 0 == s.count && nil == s.top, "Pop incorrect") - - s.push(1) - s.push(2) - s.push(3) - s.removeAll() - - XCTAssert(0 == s.count, "Count incorrect, got \(s.count).") - } - - func testConcat() { - var s1 = Stack() - s1.push(1) - s1.push(2) - s1.push(3) - - var s2 = Stack() - s2.push(4) - s2.push(5) - s2.push(6) - - let s3 = s1 + s2 - XCTAssert(6 == s3.count, "Concat incorrect.") - } - - func testPerformance() { - self.measure() {} - } + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testInt() { + var s = Stack() + + s.push(1) + s.push(2) + s.push(3) + + XCTAssert(s.count == 3, "Count incorrect, got \(s.count).") + XCTAssert(s.top == 3, "Top incorrect, got \(String(describing: s.top))") + + s.push(5) + s.push(6) + s.push(7) + + XCTAssert(s.count == 6, "Count incorrect, got \(s.count).") + XCTAssert(s.top == 7, "Top incorrect, got \(String(describing: s.top))") + + XCTAssert(s.pop() == 7 && s.count == 5 && s.top == 6, "Pop incorrect") + XCTAssert(s.pop() == 6 && s.count == 4 && s.top == 5, "Pop incorrect") + XCTAssert(s.pop() == 5 && s.count == 3 && s.top == 3, "Pop incorrect") + XCTAssert(s.pop() == 3 && s.count == 2 && s.top == 2, "Pop incorrect") + XCTAssert(s.pop() == 2 && s.count == 1 && s.top == 1, "Pop incorrect") + XCTAssert(s.pop() == 1 && s.count == 0 && s.top == nil, "Pop incorrect") + + s.push(1) + s.push(2) + s.push(3) + s.removeAll() + + XCTAssert(s.count == 0, "Count incorrect, got \(s.count).") + } + + func testConcat() { + var s1 = Stack() + s1.push(1) + s1.push(2) + s1.push(3) + + var s2 = Stack() + s2.push(4) + s2.push(5) + s2.push(6) + + let s3 = s1 + s2 + XCTAssert(s3.count == 6, "Concat incorrect.") + } + + func testPerformance() { + measure {} + } }