From 3f9c37812eba1df395887dc161171d5706dc2498 Mon Sep 17 00:00:00 2001 From: Daniel Dahan Date: Fri, 18 Nov 2016 15:12:12 -0600 Subject: [PATCH] development: prepare for release Algorithm 2.0 --- Algorithm.podspec | 6 +- Algorithm.xcodeproj/project.pbxproj | 6 + README.md | 222 ++++++++++++++++------------ Sources/Info.plist | 2 +- Tests/SampleTests.swift | 194 ++++++++++++++++++++++++ 5 files changed, 328 insertions(+), 102 deletions(-) create mode 100644 Tests/SampleTests.swift diff --git a/Algorithm.podspec b/Algorithm.podspec index 4c13768..a38ca8b 100644 --- a/Algorithm.podspec +++ b/Algorithm.podspec @@ -1,10 +1,10 @@ Pod::Spec.new do |s| s.name = 'Algorithm' - s.version = '1.0.8' + s.version = '2.0.0' s.license = 'BSD-3-Clause' s.summary = 'A toolset for writing algorithms in Swift.' - s.homepage = 'http://cosmicmind.com' - s.social_media_url = 'https://www.facebook.com/graphkit' + s.homepage = 'http://algorithmswift.io' + s.social_media_url = 'https://www.facebook.com/cosmicmindio' s.authors = { 'CosmicMind, Inc.' => 'support@cosmicmind.com' } s.source = { :git => 'https://github.com/CosmicMind/Algorithm.git', :tag => s.version } s.ios.deployment_target = '8.0' diff --git a/Algorithm.xcodeproj/project.pbxproj b/Algorithm.xcodeproj/project.pbxproj index f4d3b18..5554fad 100644 --- a/Algorithm.xcodeproj/project.pbxproj +++ b/Algorithm.xcodeproj/project.pbxproj @@ -89,6 +89,8 @@ 65744D421C554F410011C977 /* SortedMultiSet.swift in Headers */ = {isa = PBXBuildFile; fileRef = 65744CE91C554EDA0011C977 /* SortedMultiSet.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 65744D431C554F410011C977 /* SortedSet.swift in Headers */ = {isa = PBXBuildFile; fileRef = 65744CEA1C554EDA0011C977 /* SortedSet.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 65744D441C554F410011C977 /* Stack.swift in Headers */ = {isa = PBXBuildFile; fileRef = 65744CEB1C554EDA0011C977 /* Stack.swift */; settings = {ATTRIBUTES = (Public, ); }; }; + 961E6C3D1DDF9E64004E6C93 /* SampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961E6C3C1DDF9E64004E6C93 /* SampleTests.swift */; }; + 961E6C3E1DDF9E64004E6C93 /* SampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961E6C3C1DDF9E64004E6C93 /* SampleTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -141,6 +143,7 @@ 65744D111C554F0E0011C977 /* SortedMultiSetTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortedMultiSetTests.swift; sourceTree = ""; }; 65744D121C554F0E0011C977 /* SortedSetTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortedSetTest.swift; sourceTree = ""; }; 65744D131C554F0E0011C977 /* StackTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackTests.swift; sourceTree = ""; }; + 961E6C3C1DDF9E64004E6C93 /* SampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleTests.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -235,6 +238,7 @@ 65744D111C554F0E0011C977 /* SortedMultiSetTests.swift */, 65744D121C554F0E0011C977 /* SortedSetTest.swift */, 65744D131C554F0E0011C977 /* StackTests.swift */, + 961E6C3C1DDF9E64004E6C93 /* SampleTests.swift */, ); path = Tests; sourceTree = ""; @@ -474,6 +478,7 @@ 65744D161C554F0E0011C977 /* DoublyLinkedListTests.swift in Sources */, 65744D1A1C554F0E0011C977 /* QueueTests.swift in Sources */, 65744D1C1C554F0E0011C977 /* RedBlackTreeTests.swift in Sources */, + 961E6C3D1DDF9E64004E6C93 /* SampleTests.swift in Sources */, 65744D201C554F0E0011C977 /* SortedMultiDictionaryTests.swift in Sources */, 65744D221C554F0E0011C977 /* SortedMultiSetTests.swift in Sources */, ); @@ -512,6 +517,7 @@ 65744D171C554F0E0011C977 /* DoublyLinkedListTests.swift in Sources */, 65744D1B1C554F0E0011C977 /* QueueTests.swift in Sources */, 65744D1D1C554F0E0011C977 /* RedBlackTreeTests.swift in Sources */, + 961E6C3E1DDF9E64004E6C93 /* SampleTests.swift in Sources */, 65744D211C554F0E0011C977 /* SortedMultiDictionaryTests.swift in Sources */, 65744D231C554F0E0011C977 /* SortedMultiSetTests.swift in Sources */, ); diff --git a/README.md b/README.md index 83e860b..074d522 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,33 @@ -![CosmicMind](http://www.cosmicmind.com/algorithm/index/images/AlgorithmIcon.png) +![Algorithm](http://www.cosmicmind.com/algorithm/github/algorithm-logo.png) ## Welcome to Algorithm -Algorithm is a collection of data structures that are empowered by a probability toolset. +Algorithm is a library of tools that is used to create intelligent applications. -Algorithm's architecture is designed for beginners and professionals. Its robust API requires no setup and is ready for the simplest and most extensive applications. +## Features + +- [x] Probability Tools +- [x] Expected Value +- [x] Programmable Probability Blocks +- [x] Array Extensions +- [x] Set Extensions + +## Data Structures + +- [x] DoublyLinkedList +- [x] Stack +- [x] Queue +- [x] Deque +- [x] RedBlackTree +- [x] SortedSet +- [x] SortedMultiSet +- [x] SortedDictionary +- [x] SortedMultiDictionary ## Requirements -* iOS 8.0+ / Mac OS X 10.9+ -* Xcode 7.3+ +* iOS 8.0+ / Mac OS X 10.10+ +* Xcode 8.0+ ## Communication @@ -21,8 +39,8 @@ Algorithm's architecture is designed for beginners and professionals. Its robust ## Installation -> **Embedded frameworks require a minimum deployment target of iOS 8 or OS X Mavericks (10.9).** -> - [Download Algorithm](https://github.com/CosmicMind/Algorithm/archive/master.zip) +> **Embedded frameworks require a minimum deployment target of iOS 8 or OS X Mavericks (10.10).** +> - [Download Graph](https://github.com/CosmicMind/Algorithm/archive/master.zip) Visit the [Installation](https://github.com/CosmicMind/Algorithm/wiki/Installation) page to learn how to install Algorithm using [CocoaPods](http://cocoapods.org) and [Carthage](https://github.com/Carthage/Carthage). @@ -30,7 +48,11 @@ Visit the [Installation](https://github.com/CosmicMind/Algorithm/wiki/Installati Algorithm is a growing project and will encounter changes throughout its development. It is recommended that the [Changelog](https://github.com/CosmicMind/Algorithm/wiki/Changelog) be reviewed prior to updating versions. -## A Tour +# Samples + +The following are samples to see how Algorithm may be used within your applications. + +* Visit the [Samples](https://github.com/CosmicMind/Samples) repo to see example projects using Algorithm. * [Probability](#probability) * [ExpectedValue](#expectedvalue) @@ -54,8 +76,11 @@ Each data structure within Algorithm is equipped with probability tools. For example, determining the probability of rolling a 3 using a die of 6 numbers. ```swift -let die: Array = Array(arrayLiteral: 1, 2, 3, 4, 5, 6) -print(die.probabilityOf(3)) // Output: 0.166666666666667 +let die = [Int](arrayLiteral: 1, 2, 3, 4, 5, 6) + +if 0.1 < die.probability(of: 3) + // Do something ... +} ``` #### Conditional Probability @@ -63,18 +88,14 @@ print(die.probabilityOf(3)) // Output: 0.166666666666667 For conditional probabilities that require a more complex calculation, use block statements. ```swift -let die: Array = Array(arrayLiteral: 1, 2, 3, 4, 5, 6) - -let probabilityOfX: Double = die.probabilityOf { (number: Int) in - if 5 < number || 0 == number % 3 { - // Do more. - return true - } - return false +let die = [Int](arrayLiteral: 1, 2, 3, 4, 5, 6) + +let pOfX = die.probability { (number) in + return 5 < number || 0 == number % 3 } -if 0.33 < probabilityOfX { - // Do something. +if 0.33 < pOfX { + // Do something ... } ``` @@ -84,8 +105,11 @@ if 0.33 < probabilityOfX { The expected value of rolling a 3 or 6 with 100 trials using a die of 6 numbers. ```swift -let die: Array = Array(arrayLiteral: 1, 2, 3, 4, 5, 6) -print(die.expectedValueOf(100, elements: 3, 6)) // Output: 33.3333333333333 +let die = [Int](arrayLiteral: 1, 2, 3, 4, 5, 6) + +if 20 < die.expectedValue(trials: 100, for: 3, 6) { + // Do something ... +} ``` @@ -94,29 +118,29 @@ print(die.expectedValueOf(100, elements: 3, 6)) // Output: 33.3333333333333 The DoublyLinkedList data structure is excellent for large growing collections of data. Below is an example of its usage. ```swift -let listA: DoublyLinkedList = DoublyLinkedList() -listA.insertAtFront(3) -listA.insertAtFront(2) -listA.insertAtFront(1) +var listA = DoublyLinkedList() + +listA.insert(atFront: 3) +listA.insert(atFront: 2) +listA.insert(atFront: 1) + +var listB = DoublyLinkedList() -let listB: DoublyLinkedList = DoublyLinkedList() -listB.insertAtBack(4) -listB.insertAtBack(5) -listB.insertAtBack(6) +listB.insert(atBack: 4) +listB.insert(atBack: 5) +listB.insert(atBack: 6) -let listC: DoublyLinkedList = listA + listB +var listC = listA + listB listC.cursorToFront() -repeat { - print(listC.cursor) -} while nil != listC.next -// Output: -// 1 -// 2 -// 3 -// 4 -// 5 -// 6 + +var value = listC.cursor + +while nil != value { + // Do something ... + + value = listC.next() +} ``` @@ -125,18 +149,17 @@ repeat { The Stack data structure is a container of objects that are inserted and removed according to the last-in-first-out (LIFO) principle. Below is an example of its usage. ```swift -let stack: Stack = Stack() +var stack = Stack() + stack.push(1) stack.push(2) stack.push(3) while !stack.isEmpty { - print(stack.pop()) + let value = stack.pop() + + // Do something ... } -// Output: -// 3 -// 2 -// 1 ``` @@ -145,18 +168,17 @@ while !stack.isEmpty { The Queue data structure is a container of objects that are inserted and removed according to the first-in-first-out (FIFO) principle. Below is an example of its usage. ```swift -let queue: Queue = Queue() +var queue = Queue() + queue.enqueue(1) queue.enqueue(2) queue.enqueue(3) while !queue.isEmpty { - print(queue.dequeue()) + let value = queue.dequeue() + + // Do something ... } -// Output: -// 1 -// 2 -// 3 ``` @@ -165,31 +187,27 @@ while !queue.isEmpty { The Deque data structure is a container of objects that are inserted and removed according to the first-in-first-out (FIFO) and last-in-first-out (LIFO) principle. Essentially, a Deque is a Stack and Queue combined. Below are examples of its usage. ```swift -let dequeA: Deque = Deque() -dequeA.insertAtBack(1) -dequeA.insertAtBack(2) -dequeA.insertAtBack(3) +var dequeA = Deque() +dequeA.insert(atBack: 1) +dequeA.insert(atBack: 2) +dequeA.insert(atBack: 3) while !dequeA.isEmpty { - print(dequeA.removeAtFront()) + let value = dequeA.removeAtFront() + + // Do something ... } -// Output: -// 1 -// 2 -// 3 -let dequeB: Deque = Deque() -dequeB.insertAtBack(4) -dequeB.insertAtBack(5) -dequeB.insertAtBack(6) +var dequeB = Deque() +dequeB.insert(atBack: 4) +dequeB.insert(atBack: 5) +dequeB.insert(atBack: 6) while !dequeB.isEmpty { - print(dequeB.removeAtBack()) + let value = dequeB.removeAtFront() + + // Do something ... } -// Output: -// 6 -// 5 -// 4 ``` @@ -198,14 +216,17 @@ while !dequeB.isEmpty { A RedBlackTree is a Balanced Binary Search Tree that maintains insert, remove, update, and search operations in a complexity of O(logn). The following implementation of a RedBlackTree also includes an order-statistic, which allows the data structure to be accessed using subscripts like an array or dictionary. RedBlackTrees may store unique keys or non-unique key values. Below is an example of its usage. ```swift -let rbA: RedBlackTree = RedBlackTree(uniqueKeys: true) +var ages = RedBlackTree(uniqueKeys: true) + +ages.insert(value: 16, for: "Sarah") +ages.insert(value: 12, for: "Peter") +ages.insert(value: 23, for: "Alex") -for var i: Int = 1000; 0 < i; --i { - rbA.insert(1, value: 1) - rbA.insert(2, value: 2) - rbA.insert(3, value: 3) +let node = ages[1] + +if "Peter" == node.key { + // Do something ... } -print(rbA.count) // Output: 3 ``` @@ -214,34 +235,32 @@ print(rbA.count) // Output: 3 SortedSets are a powerful data structure for algorithm and analysis design. Elements within a SortedSet are unique and insert, remove, and search operations have a complexity of O(logn). The following implementation of a SortedSet also includes an order-statistic, which allows the data structure to be accessed using an index subscript like an array. Below are examples of its usage. ```swift -let setA: SortedSet = SortedSet(elements: 1, 2, 3) // Sorted: [1, 2, 3] -let setB: SortedSet = SortedSet(elements: 4, 3, 6) // Sorted: [3, 4, 6] - -let setC: SortedSet = SortedSet(elements: 7, 1, 2) // Sorted: [1, 2, 7] -let setD: SortedSet = SortedSet(elements: 1, 7) // Sorted: [1, 7] - -let setE: SortedSet = SortedSet(elements: 1, 6, 7) // Sorted: [1, 6, 7] +let setA = SortedSet(elements: 1, 2, 3) +let setB = SortedSet(elements: 4, 3, 6) +let setC = SortedSet(elements: 7, 1, 2) +let setD = SortedSet(elements: 1, 7) +let setE = SortedSet(elements: 1, 6, 7) // Union. -print((setA + setB).count) // Output: 5 -print(setA.union(setB).count) // Output: 5 +setA + setB +setA.union(setB) -// Intersect. -print(setC.intersect(setD).count) // Output: 2 +// Intersection. +setC.intersection(setD) // Subset. -print(setD < setC) // true -print(setD.isSubsetOf(setC)) // true +setD < setC +setD.isSubset(of: setC) // Superset. -print(setD > setC) // false -print(setD.isSupersetOf(setC)) // false +setD > setC +setD.isSuperset(of: setC) // Contains. -print(setE.contains(setA.first!)) // true +setE.contains(setA.first!) // Probability. -print(setE.probabilityOf(setA.first!, setA.last!)) // 0.333333333333333 +setE.probability(of: setA.first!, setA.last!) ``` @@ -264,17 +283,24 @@ struct Student { var name: String } -let dict: SortedMultiDictionary = SortedMultiDictionary() +let sarah = Student(name: "Sarah") +let peter = Student(name: "Peter") +let alex = Student(name: "Alex") + +var students = SortedMultiDictionary() + +students.insert(value: sarah, for: sarah.name) +students.insert(value: peter, for: peter.name) +students.insert(value: alex, for: alex.name) -// Do something with an alphabetically SortedMultiDictionary of Student structs. for student in students { - dict.insert(student.name, value: student) + // Do something ... } ``` ## License -Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. . All rights reserved. +Copyright (C) 2015 - 2016, CosmicMind, Inc. . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/Sources/Info.plist b/Sources/Info.plist index a70ac6a..7e7479f 100644 --- a/Sources/Info.plist +++ b/Sources/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.8 + 2.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Tests/SampleTests.swift b/Tests/SampleTests.swift new file mode 100644 index 0000000..fce13fe --- /dev/null +++ b/Tests/SampleTests.swift @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of CosmicMind nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +@testable import Algorithm + +class SampleTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testInt() { +// let die = [Int](arrayLiteral: 1, 2, 3, 4, 5, 6) +// +// if 0.1 < die.probability(of: 3) { +// // Do something ... +// } + +// let die = [Int](arrayLiteral: 1, 2, 3, 4, 5, 6) +// +// let pOfX = die.probability { (number) in +// return 5 < number || 0 == number % 3 +// } +// +// if 0.33 < pOfX { +// // Do something. +// } + +// let die = [Int](arrayLiteral: 1, 2, 3, 4, 5, 6) +// +// if 20 < die.expectedValue(trials: 100, for: 3, 6) { +// // Do something ... +// } + +// var listA = DoublyLinkedList() +// +// listA.insert(atFront: 3) +// listA.insert(atFront: 2) +// listA.insert(atFront: 1) +// +// var listB = DoublyLinkedList() +// +// listB.insert(atBack: 4) +// listB.insert(atBack: 5) +// listB.insert(atBack: 6) +// +// var listC = listA + listB +// +// listC.cursorToFront() +// +// var value = listC.cursor +// +// while nil != value { +// // Do something ... +// +// value = listC.next() +// } +// +// var stack = Stack() +// +// stack.push(1) +// stack.push(2) +// stack.push(3) +// +// while !stack.isEmpty { +// let value = stack.pop() +// +// // Do something ... +// } +// +// var queue = Queue() +// +// queue.enqueue(1) +// queue.enqueue(2) +// queue.enqueue(3) +// +// while !queue.isEmpty { +// let value = queue.dequeue() +// +// // Do something ... +// } +// +// var dequeA = Deque() +// dequeA.insert(atBack: 1) +// dequeA.insert(atBack: 2) +// dequeA.insert(atBack: 3) +// +// while !dequeA.isEmpty { +// let value = dequeA.removeAtFront() +// +// // Do something ... +// } +// +// var dequeB = Deque() +// dequeB.insert(atBack: 4) +// dequeB.insert(atBack: 5) +// dequeB.insert(atBack: 6) +// +// while !dequeB.isEmpty { +// let value = dequeB.removeAtFront() +// +// // Do something ... +// } + +// var ages = RedBlackTree(uniqueKeys: true) +// +// ages.insert(value: 16, for: "Sarah") +// ages.insert(value: 12, for: "Peter") +// ages.insert(value: 23, for: "Alex") +// +// let node = ages[1] +// +// if "Peter" == node.key { +// // Do something ... +// } + +// let setA = SortedSet(elements: 1, 2, 3) +// let setB = SortedSet(elements: 4, 3, 6) +// let setC = SortedSet(elements: 7, 1, 2) +// let setD = SortedSet(elements: 1, 7) +// let setE = SortedSet(elements: 1, 6, 7) +// +// // Union. +// setA + setB +// setA.union(setB) +// +// // Intersection. +// setC.intersection(setD) +// +// // Subset. +// setD < setC +// setD.isSubset(of: setC) +// +// // Superset. +// setD > setC +// setD.isSuperset(of: setC) +// +// // Contains. +// setE.contains(setA.first!) +// +// // Probability. +// setE.probability(of: setA.first!, setA.last!) + + struct Student { + var name: String + } + + let sarah = Student(name: "Sarah") + let peter = Student(name: "Peter") + let alex = Student(name: "Alex") + + var students = SortedMultiDictionary() + + students.insert(value: sarah, for: sarah.name) + students.insert(value: peter, for: peter.name) + students.insert(value: alex, for: alex.name) + + for student in students { + // Do something ... + } + } +}