Repository: kodecocodes/swift-algorithm-club Branch: master Commit: 05c6d0bc5fa9 Files: 1063 Total size: 4.1 MB Directory structure: gitextract_cau619vu/ ├── .github/ │ ├── CONTRIBUTING.md │ ├── ISSUE_TEMPLATE.md │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .swiftlint.yml ├── 3Sum and 4Sum/ │ ├── 3Sum.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── 4Sum.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── README.md ├── A-Star/ │ ├── AStar.swift │ ├── Images/ │ │ ├── graph.dot │ │ ├── step1.dot │ │ ├── step2.dot │ │ ├── step3.dot │ │ ├── step4.dot │ │ ├── step5.dot │ │ ├── step6.dot │ │ └── step7.dot │ ├── README.md │ └── Tests/ │ ├── AStarTests.swift │ ├── AStarTests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── AStarTests.xcscheme │ └── Info.plist ├── AVL Tree/ │ ├── AVLTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── AVLTree.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── AVLTree.swift │ ├── Images/ │ │ ├── BalanceNotOK.graffle │ │ ├── BalanceOK.graffle │ │ ├── Balanced.graffle │ │ ├── Height.graffle │ │ └── Unbalanced.graffle │ ├── README.markdown │ └── Tests/ │ ├── AVLTreeTests.swift │ ├── Info.plist │ ├── Tests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Tests.xcscheme │ └── TreeNodeTests.swift ├── Algorithm Design.markdown ├── All-Pairs Shortest Paths/ │ ├── APSP/ │ │ ├── APSP/ │ │ │ ├── APSP.h │ │ │ ├── APSP.swift │ │ │ ├── FloydWarshall.swift │ │ │ ├── Helpers.swift │ │ │ └── Info.plist │ │ ├── APSP.playground/ │ │ │ ├── Contents.swift │ │ │ ├── contents.xcplayground │ │ │ ├── playground.xcworkspace/ │ │ │ │ └── contents.xcworkspacedata │ │ │ └── timeline.xctimeline │ │ ├── APSP.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace/ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata/ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ └── xcshareddata/ │ │ │ └── xcschemes/ │ │ │ ├── APSP.xcscheme │ │ │ └── APSPTests.xcscheme │ │ ├── APSP.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ │ └── APSPTests/ │ │ ├── APSPTests.swift │ │ └── Info.plist │ └── README.markdown ├── Array2D/ │ ├── Array2D.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── Array2D.swift │ ├── README.markdown │ └── Tests/ │ ├── Array2DTests.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── B-Tree/ │ ├── BTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── BTree.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── BTree.swift │ ├── README.md │ └── Tests/ │ ├── Tests/ │ │ ├── BTreeNodeTests.swift │ │ ├── BTreeTests.swift │ │ └── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Big-O Notation.markdown ├── Binary Search/ │ ├── BinarySearch.playground/ │ │ ├── Contents.swift │ │ └── contents.xcplayground │ ├── BinarySearch.swift │ ├── README.markdown │ └── Tests/ │ ├── BinarySearchTests.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Binary Search Tree/ │ ├── Images/ │ │ ├── DeleteLeaf.graffle │ │ ├── DeleteOneChild.graffle │ │ ├── DeleteTwoChildren.graffle │ │ ├── MinimumMaximum.graffle │ │ ├── Searching.graffle │ │ ├── Traversing.graffle │ │ ├── Tree1.graffle │ │ └── Tree2.graffle │ ├── README.markdown │ ├── Solution 1/ │ │ ├── BinarySearchTree.playground/ │ │ │ ├── Contents.swift │ │ │ ├── Sources/ │ │ │ │ └── BinarySearchTree.swift │ │ │ ├── contents.xcplayground │ │ │ └── playground.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── Tests/ │ │ ├── BinarySearchTreeTests.swift │ │ ├── Info.plist │ │ └── Tests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Tests.xcscheme │ └── Solution 2/ │ ├── BinarySearchTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── BinarySearchTree.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── BinarySearchTree.swift ├── Binary Tree/ │ ├── BinaryTree.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── BinaryTree.swift │ ├── Images/ │ │ ├── BinaryTree.graffle │ │ └── Operations.graffle │ └── README.markdown ├── Bit Set/ │ ├── BitSet.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── BitSet.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── README.markdown ├── Bloom Filter/ │ ├── BloomFilter.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── BloomFilter.swift │ ├── README.markdown │ └── Tests/ │ ├── BloomFilterTests.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Bounded Priority Queue/ │ ├── BoundedPriorityQueue.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── BoundedPriorityQueue.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── BoundedPriorityQueue.swift │ ├── README.markdown │ └── Tests/ │ ├── BoundedPriorityQueueTests.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Boyer-Moore-Horspool/ │ ├── BoyerMooreHorspool.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── timeline.xctimeline │ ├── BoyerMooreHorspool.swift │ ├── README.markdown │ └── Tests/ │ ├── BoyerMooreHorspoolTests.swift │ ├── BoyerMooreTests.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Breadth-First Search/ │ ├── BreadthFirstSearch.playground/ │ │ ├── Pages/ │ │ │ └── Simple example.xcplaygroundpage/ │ │ │ └── Contents.swift │ │ ├── Sources/ │ │ │ ├── Edge.swift │ │ │ ├── Graph.swift │ │ │ ├── Node.swift │ │ │ └── Queue.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── BreadthFirstSearch.swift │ ├── Images/ │ │ ├── AnimatedExample.graffle │ │ ├── AnimatedExample.psd │ │ └── TraversalTree.graffle │ ├── README.markdown │ └── Tests/ │ ├── BreadthFirstSearchTests.swift │ ├── Graph.swift │ ├── Info.plist │ ├── Queue.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Brute-Force String Search/ │ ├── BruteForceStringSearch.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── BruteForceStringSearch.swift │ └── README.markdown ├── Bubble Sort/ │ ├── MyPlayground.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── BubbleSort.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── README.markdown ├── Bucket Sort/ │ ├── BucketSort.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── BucketSort.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── BucketSort.swift │ ├── README.markdown │ └── Tests/ │ ├── Info.plist │ ├── Tests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Closest Pair/ │ ├── ClosestPair.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── README.markdown ├── Comb Sort/ │ ├── Comb Sort.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── Comb Sort.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── Comb Sort.swift │ ├── README.markdown │ └── Tests/ │ ├── CombSortTests.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Combinatorics/ │ ├── Combinatorics.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── README.markdown ├── Convex Hull/ │ ├── Convex Hull/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ └── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ └── LaunchScreen.storyboard │ │ ├── Info.plist │ │ └── View.swift │ ├── Convex Hull.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Tests.xcscheme │ ├── README.md │ └── Tests/ │ ├── Info.plist │ └── Tests.swift ├── Count Occurrences/ │ ├── CountOccurrences.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── CountOccurrences.swift │ └── README.markdown ├── CounterClockWise/ │ ├── CounterClockWise.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── CounterClockWise.swift │ └── README.md ├── Counting Sort/ │ ├── CountingSort.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── CountingSort.swift │ ├── README.markdown │ └── Tests/ │ ├── CountingSortTest.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Depth-First Search/ │ ├── DepthFirstSearch.playground/ │ │ ├── Edge.o │ │ ├── Graph.o │ │ ├── Node.o │ │ ├── Pages/ │ │ │ └── Simple Example.xcplaygroundpage/ │ │ │ └── Contents.swift │ │ ├── Sources/ │ │ │ ├── Edge.swift │ │ │ ├── Graph.swift │ │ │ └── Node.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── DepthFirstSearch.swift │ ├── Images/ │ │ ├── AnimatedExample.graffle │ │ ├── AnimatedExample.psd │ │ └── TraversalTree.graffle │ ├── README.markdown │ └── Tests/ │ ├── DepthFirstSearchTests.swift │ ├── Graph.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Deque/ │ ├── Deque-Optimized.swift │ ├── Deque-Simple.swift │ ├── Deque.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── README.markdown ├── Dijkstra Algorithm/ │ ├── Dijkstra.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ ├── Dijkstra.swift │ │ │ └── Vertex.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── README.md │ └── VisualizedDijkstra.playground/ │ ├── Contents.swift │ ├── Sources/ │ │ ├── CustomUI/ │ │ │ ├── EdgeRepresentation.swift │ │ │ ├── ErrorView.swift │ │ │ ├── MyShapeLayer.swift │ │ │ ├── RoundedButton.swift │ │ │ └── VertexView.swift │ │ ├── Graph.swift │ │ ├── GraphColors.swift │ │ ├── GraphView.swift │ │ ├── SimpleObjects/ │ │ │ ├── Edge.swift │ │ │ └── Vertex.swift │ │ └── Window.swift │ ├── contents.xcplayground │ └── playground.xcworkspace/ │ ├── contents.xcworkspacedata │ └── xcshareddata/ │ └── IDEWorkspaceChecks.plist ├── DiningPhilosophers/ │ ├── DiningPhilosophers.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ ├── DiningPhilosophers.xcscheme │ │ └── xcschememanagement.plist │ ├── LICENSE │ ├── Package.swift │ ├── README.md │ └── Sources/ │ └── main.swift ├── Egg Drop Problem/ │ ├── EggDrop.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── EggDrop.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ ├── EggDrop.swift │ └── README.markdown ├── Encode and Decode Tree/ │ ├── EncodeAndDecodeTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── EncodeAndDecodeTree.swift │ │ └── contents.xcplayground │ ├── EncodeAndDecodeTree.swift │ └── readme.md ├── Fixed Size Array/ │ ├── FixedSizeArray.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── timeline.xctimeline │ ├── Images/ │ │ └── FixedSizeArrays.graffle │ └── README.markdown ├── Fizz Buzz/ │ ├── FizzBuzz.playground/ │ │ └── Contents.swift │ ├── FizzBuzz.swift │ └── README.markdown ├── GCD/ │ ├── GCD.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── GCD.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── README.markdown ├── Genetic/ │ ├── README.markdown │ ├── gen.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── gen.swift ├── Graph/ │ ├── Graph/ │ │ ├── AdjacencyListGraph.swift │ │ ├── AdjacencyMatrixGraph.swift │ │ ├── Edge.swift │ │ ├── Graph.h │ │ ├── Graph.swift │ │ ├── Info.plist │ │ └── Vertex.swift │ ├── Graph.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── timeline.xctimeline │ ├── Graph.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ ├── Graph.xcscheme │ │ └── GraphTests.xcscheme │ ├── Graph.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ ├── GraphTests/ │ │ ├── GraphTests.swift │ │ └── Info.plist │ ├── Images/ │ │ ├── AdjacencyList.graffle │ │ ├── AdjacencyMatrix.graffle │ │ ├── ChordMap.graffle │ │ ├── CoreData.graffle │ │ ├── DAG.graffle │ │ ├── Demo1.graffle │ │ ├── Flights.graffle │ │ ├── FlightsDirected.graffle │ │ ├── Graph.graffle │ │ ├── SocialNetwork.graffle │ │ ├── StateMachine.graffle │ │ ├── Tasks.graffle │ │ └── TreeAndList.graffle │ └── README.markdown ├── Hash Set/ │ ├── HashSet.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── HashSet.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── HashSet.swift │ ├── Images/ │ │ └── CombineSets.graffle │ └── README.markdown ├── Hash Table/ │ ├── HashTable.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── HashTable.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── README.markdown ├── Hashed Heap/ │ ├── HashedHeap.swift │ ├── README.markdown │ └── Tests/ │ ├── Hashed Heap Tests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Hashed Heap Tests.xcscheme │ ├── HashedHeapTests.swift │ └── Info.plist ├── HaversineDistance/ │ ├── HaversineDistance.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── README.md ├── Heap/ │ ├── Heap.swift │ ├── Images/ │ │ ├── Array.graffle │ │ ├── Heap1.graffle │ │ ├── HeapShape.graffle │ │ ├── Insert1.graffle │ │ ├── Insert2.graffle │ │ ├── Insert3.graffle │ │ ├── LargeHeap.graffle │ │ ├── RegularTree.graffle │ │ ├── Remove1.graffle │ │ ├── Remove2.graffle │ │ ├── Remove3.graffle │ │ ├── Remove4.graffle │ │ ├── Remove5.graffle │ │ └── SortedArray.graffle │ ├── README.markdown │ └── Tests/ │ ├── HeapTests.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Heap Sort/ │ ├── HeapSort.swift │ ├── Images/ │ │ └── MaxHeap.graffle │ ├── README.markdown │ └── Tests/ │ ├── HeapSortTests.swift │ ├── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Huffman Coding/ │ ├── Huffman.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ ├── Heap.swift │ │ │ ├── Huffman.swift │ │ │ ├── NSData+Bits.swift │ │ │ └── PriorityQueue.swift │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── timeline.xctimeline │ ├── Huffman.swift │ ├── Images/ │ │ ├── BuildTree.graffle │ │ ├── BuildTree.psd │ │ ├── Compression.graffle │ │ ├── Decompression.graffle │ │ └── Tree.graffle │ ├── NSData+Bits.swift │ └── README.markdown ├── Insertion Sort/ │ ├── InsertionSort.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── InsertionSort.swift │ ├── README.markdown │ └── Tests/ │ ├── Info.plist │ ├── InsertionSortTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Introsort/ │ ├── HeapSort.swift │ ├── InsertionSort.swift │ ├── IntroSort.swift │ ├── Introsort.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ ├── HeapSort.swift │ │ │ ├── InsertionSort.swift │ │ │ ├── Partition.swift │ │ │ ├── Randomize.swift │ │ │ └── Sort3.swift │ │ └── contents.xcplayground │ ├── Partition.swift │ ├── README.markdown │ ├── Randomize.swift │ └── Sort3.swift ├── K-Means/ │ ├── KMeans.swift │ ├── README.markdown │ └── Tests/ │ ├── Info.plist │ ├── KMeansTests.swift │ ├── Tests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Tests.xcscheme │ └── Vector.swift ├── Karatsuba Multiplication/ │ ├── KaratsubaMultiplication.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── KaratsubaMultiplication.swift │ ├── README.markdown │ └── Tests/ │ ├── KaratsubaMultiplicationTests.swift │ ├── Tests/ │ │ └── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Knuth-Morris-Pratt/ │ ├── KnuthMorrisPratt.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── KnuthMorrisPratt.swift │ └── README.markdown ├── Kth Largest Element/ │ ├── README.markdown │ └── kthLargest.playground/ │ ├── Contents.swift │ ├── Sources/ │ │ └── kthLargest.swift │ ├── contents.xcplayground │ └── playground.xcworkspace/ │ ├── contents.xcworkspacedata │ └── xcshareddata/ │ └── kthLargest.xcscmblueprint ├── LICENSE.txt ├── LRU Cache/ │ ├── LRUCache.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ ├── LRUCache.swift │ │ │ └── LinkedList.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── LRUCache.swift │ └── Readme.md ├── Linear Regression/ │ ├── LinearRegression.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── README.markdown ├── Linear Search/ │ ├── LinearSearch.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── LinearSearch.swift │ └── README.markdown ├── Linked List/ │ ├── LinkedList.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── LinkedList.swift │ ├── README.markdown │ └── Tests/ │ ├── Info.plist │ ├── LinkedListTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Longest Common Subsequence/ │ ├── LongestCommonSubsequence.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── LongestCommonSubsequence.swift │ ├── README.markdown │ └── Tests/ │ ├── LongestCommonSubsequenceTests.swift │ ├── Tests/ │ │ └── Info.plist │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Merge Sort/ │ ├── MergeSort.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── MergeSort.swift │ └── README.markdown ├── Miller-Rabin Primality Test/ │ ├── MRPrimality.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── MillerRabin.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── MRPrimality.swift │ └── README.markdown ├── Minimum Edit Distance/ │ ├── MinimumEditDistance.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── README.markdown ├── Minimum Spanning Tree/ │ ├── Kruskal.swift │ ├── MinimumSpanningTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ ├── Graph.swift │ │ │ ├── Heap.swift │ │ │ ├── PriorityQueue.swift │ │ │ └── UnionFind.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── Prim.swift │ └── README.markdown ├── Minimum Spanning Tree (Unweighted)/ │ ├── Images/ │ │ ├── Graph.sketch │ │ ├── MinimumSpanningTree.sketch │ │ └── Tree.graffle │ ├── MinimumSpanningTree.playground/ │ │ ├── Pages/ │ │ │ └── Minimum spanning tree example.xcplaygroundpage/ │ │ │ └── Contents.swift │ │ ├── Sources/ │ │ │ ├── Edge.swift │ │ │ ├── Graph.swift │ │ │ ├── Node.swift │ │ │ └── Queue.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── MinimumSpanningTree.swift │ ├── README.markdown │ └── Tests/ │ ├── Graph.swift │ ├── Info.plist │ ├── MinimumSpanningTreeTests.swift │ ├── Queue.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── MinimumCoinChange/ │ ├── LICENSE │ ├── Package.swift │ ├── README.md │ ├── Sources/ │ │ └── MinimumCoinChange.swift │ └── Tests/ │ ├── LinuxMain.swift │ └── MinimumCoinChangeTests/ │ └── MinimumCoinChangeTests.swift ├── Monty Hall Problem/ │ ├── MontyHall.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── README.markdown ├── Multiset/ │ ├── Multiset.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── Multiset.swift │ │ └── contents.xcplayground │ └── README.markdown ├── Myers Difference Algorithm/ │ ├── MyersDifferenceAlgorithm.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── MyersDifferenceAlgorithm.swift │ │ └── contents.xcplayground │ ├── MyersDifferenceAlgorithm.swift │ └── README.md ├── Naive Bayes Classifier/ │ ├── NaiveBayes.playground/ │ │ ├── Contents.swift │ │ ├── Resources/ │ │ │ └── wine.csv │ │ ├── Sources/ │ │ │ └── NaiveBayes.swift │ │ ├── contents.xcplayground │ │ ├── playground.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── timeline.xctimeline │ ├── NaiveBayes.swift │ └── README.md ├── Octree/ │ ├── Octree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── Octree.swift │ │ ├── contents.xcplayground │ │ └── timeline.xctimeline │ └── README.md ├── Ordered Array/ │ ├── OrderedArray.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── OrderedArray.swift │ └── README.markdown ├── Ordered Set/ │ ├── OrderedSet.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── OrderedSet.swift │ │ └── contents.xcplayground │ ├── OrderedSet.swift │ └── README.markdown ├── Palindromes/ │ ├── Palindromes.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── Palindrome.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── README.markdown │ └── Test/ │ ├── Palindrome.swift │ ├── Test/ │ │ ├── Info.plist │ │ └── Test.swift │ └── Test.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Test.xcscheme ├── Points Lines Planes/ │ ├── Points Lines Planes/ │ │ ├── 2D/ │ │ │ ├── Line2D.swift │ │ │ └── Point2D.swift │ │ └── main.swift │ ├── Points Lines Planes.xcodeproj/ │ │ ├── project.pbxproj │ │ └── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── README.md ├── Priority Queue/ │ ├── PriorityQueue.swift │ ├── README.markdown │ └── Tests/ │ ├── Info.plist │ ├── PriorityQueueTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── QuadTree/ │ ├── QuadTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── QuadTree.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── README.md │ └── Tests/ │ ├── Tests/ │ │ ├── Info.plist │ │ └── Tests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ └── project.xcworkspace/ │ └── contents.xcworkspacedata ├── Queue/ │ ├── Queue-Optimized.swift │ ├── Queue-Simple.swift │ ├── Queue.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── README.markdown │ └── Tests/ │ ├── Info.plist │ ├── QueueTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Quicksort/ │ ├── Images/ │ │ └── Example.graffle │ ├── Quicksort.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── Quicksort.swift │ ├── README.markdown │ └── Tests/ │ ├── Info.plist │ ├── QuicksortTests.swift │ ├── SortingTestHelpers.swift │ └── Tests-Quicksort.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests-Quicksort.xcscheme ├── README.markdown ├── Rabin-Karp/ │ ├── README.markdown │ ├── Rabin-Karp.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── rabin-karp.swift ├── Radix Sort/ │ ├── RadixSort.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── radixSort.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── RadixSortExample.swift │ ├── ReadMe.md │ ├── Tests/ │ │ ├── Info.plist │ │ ├── RadixSortTests.swift │ │ └── Tests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Tests.xcscheme │ └── radixSort.swift ├── Radix Tree/ │ ├── README.markdown │ ├── RadixTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── RadixTree.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── RadixTree.swift ├── Red-Black Tree/ │ ├── README.markdown │ ├── RedBlackTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── RedBlackTree.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── RedBlackTree.swift ├── Ring Buffer/ │ ├── README.markdown │ ├── RingBuffer.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── RingBuffer.swift ├── Rootish Array Stack/ │ ├── README.md │ ├── RootishArrayStack.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── RootishArrayStack.swift │ └── Tests/ │ ├── Info.plist │ ├── RootishArrayStack.swift │ ├── RootishArrayStackTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Run-Length Encoding/ │ ├── README.markdown │ └── RLE.playground/ │ ├── Contents.swift │ ├── Sources/ │ │ └── RLE.swift │ ├── contents.xcplayground │ └── playground.xcworkspace/ │ └── contents.xcworkspacedata ├── Segment Tree/ │ ├── LazyPropagation/ │ │ ├── LazyPropagation.playground/ │ │ │ ├── Contents.swift │ │ │ ├── contents.xcplayground │ │ │ └── playground.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── README.markdown │ ├── README.markdown │ ├── SegmentTree.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── SegmentTree.swift ├── Select Minimum Maximum/ │ ├── Maximum.swift │ ├── Minimum.swift │ ├── MinimumMaximumPairs.swift │ ├── README.markdown │ ├── SelectMinimumMaximum.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── Tests/ │ ├── Info.plist │ ├── MaximumTests.swift │ ├── MinimumMaximumPairsTests.swift │ ├── MinimumTests.swift │ ├── TestHelper.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Selection Sampling/ │ ├── README.markdown │ ├── SelectionSampling.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── SelectionSampling.swift ├── Selection Sort/ │ ├── README.markdown │ ├── SelectionSort.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── SelectionSort.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ ├── SelectionSort.swift │ └── Tests/ │ ├── Info.plist │ ├── SelectionSortTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Set Cover (Unweighted)/ │ ├── README.markdown │ ├── SetCover.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ ├── RandomArrayOfSets.swift │ │ │ └── SetCover.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── SetCover.swift ├── Shell Sort/ │ ├── README.markdown │ ├── Shell Sort.playground/ │ │ ├── Contents.swift │ │ └── contents.xcplayground │ ├── ShellSortExample.swift │ ├── Tests/ │ │ ├── Info.plist │ │ ├── ShellSortTests.swift │ │ └── Tests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Tests.xcscheme │ └── shellsort.swift ├── Shortest Path (Unweighted)/ │ ├── Images/ │ │ └── Graph.graffle │ ├── README.markdown │ ├── ShortestPath.playground/ │ │ ├── Pages/ │ │ │ └── Shortest path example.xcplaygroundpage/ │ │ │ └── Contents.swift │ │ ├── Sources/ │ │ │ ├── Edge.swift │ │ │ ├── Graph.swift │ │ │ ├── Node.swift │ │ │ └── Queue.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── ShortestPath.swift │ └── Tests/ │ ├── Graph.swift │ ├── Info.plist │ ├── Queue.swift │ ├── ShortestPathTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Shuffle/ │ ├── README.markdown │ ├── Shuffle.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── Shuffle.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── Shuffle.swift ├── Shunting Yard/ │ ├── README.markdown │ ├── ShuntingYard.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── Stack.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── ShuntingYard.swift ├── Simulated annealing/ │ ├── README.md │ ├── simann.swift │ └── simann_example.swift ├── Single-Source Shortest Paths (Weighted)/ │ ├── README.markdown │ ├── SSSP/ │ │ ├── BellmanFord.swift │ │ ├── Info.plist │ │ ├── SSSP.h │ │ └── SSSP.swift │ ├── SSSP.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── SSSP.xcodeproj/ │ │ ├── project.pbxproj │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ ├── SSSP.xcscheme │ │ └── SSSPTests.xcscheme │ ├── SSSP.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── WorkspaceSettings.xcsettings │ └── SSSPTests/ │ ├── Info.plist │ └── SSSPTests.swift ├── Singly Linked List/ │ ├── KeyValuePair.swift │ ├── README.markdown │ ├── SinglyLinkedList.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── SinglyLinkedList.swift │ └── Tests/ │ ├── Tests/ │ │ ├── Info.plist │ │ └── SinglyLinkedListTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Skip-List/ │ ├── README.md │ ├── SkipList.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── SkipList.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── SkipList.swift ├── Slow Sort/ │ ├── README.markdown │ ├── SlowSort.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── SlowSort.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── SlowSort.swift ├── Sorted Set/ │ ├── README.markdown │ ├── SortedSet.playground/ │ │ ├── Pages/ │ │ │ ├── Example 1.xcplaygroundpage/ │ │ │ │ ├── Contents.swift │ │ │ │ └── timeline.xctimeline │ │ │ ├── Example 2.xcplaygroundpage/ │ │ │ │ └── Contents.swift │ │ │ └── Example 3.xcplaygroundpage/ │ │ │ └── Contents.swift │ │ ├── Sources/ │ │ │ ├── Player.swift │ │ │ ├── Random.swift │ │ │ └── SortedSet.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── SortedSet.swift ├── Sparse Table/ │ ├── README.markdown │ └── Sparse Table.playground/ │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace/ │ └── contents.xcworkspacedata ├── Splay Tree/ │ ├── SplayTree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── SplayTree.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── SplayTree.swift │ ├── Tests/ │ │ ├── Info.plist │ │ ├── SplayTreeTests.swift │ │ ├── Tests-Bridging-Header.h │ │ └── Tests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Tests.xcscheme │ └── readme.md ├── Stack/ │ ├── README.markdown │ ├── Stack.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── Stack.swift │ └── Tests/ │ ├── Info.plist │ ├── StackTests.swift │ └── Tests.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Tests.xcscheme ├── Strassen Matrix Multiplication/ │ ├── README.markdown │ └── StrassensMatrixMultiplication.playground/ │ ├── Contents.swift │ ├── Sources/ │ │ ├── Matrix.swift │ │ └── Number.swift │ ├── contents.xcplayground │ └── playground.xcworkspace/ │ └── contents.xcworkspacedata ├── Ternary Search Tree/ │ ├── README.markdown │ ├── TST.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ ├── TSTNode.swift │ │ │ ├── TernarySearchTree.swift │ │ │ └── Utils.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── TSTNode.swift │ ├── TernarySearchTree.swift │ ├── Tests/ │ │ ├── Info.plist │ │ ├── TernarySearchTreeTests.swift │ │ └── Tests.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Tests.xcscheme │ └── Utils.swift ├── Threaded Binary Tree/ │ ├── README.markdown │ └── ThreadedBinaryTree.playground/ │ ├── Contents.swift │ ├── Sources/ │ │ └── ThreadedBinaryTree.swift │ ├── contents.xcplayground │ └── playground.xcworkspace/ │ ├── contents.xcworkspacedata │ └── xcshareddata/ │ └── IDEWorkspaceChecks.plist ├── Topological Sort/ │ ├── Graph.swift │ ├── Images/ │ │ ├── Algorithms.graffle │ │ ├── Example.graffle │ │ ├── Graph.graffle │ │ ├── GraphResult.graffle │ │ ├── InvalidSort.graffle │ │ └── TopologicalSort.graffle │ ├── README.markdown │ ├── Tests/ │ │ ├── Info.plist │ │ ├── Tests.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace/ │ │ │ │ └── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── xcschemes/ │ │ │ └── Tests.xcscheme │ │ └── TopologicalSortTests.swift │ ├── Topological Sort.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ ├── Graph.swift │ │ │ ├── TopologicalSort1.swift │ │ │ ├── TopologicalSort2.swift │ │ │ └── TopologicalSort3.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ ├── TopologicalSort1.swift │ ├── TopologicalSort2.swift │ └── TopologicalSort3.swift ├── Treap/ │ ├── Treap/ │ │ ├── Treap/ │ │ │ └── Info.plist │ │ ├── Treap.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace/ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata/ │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ └── xcshareddata/ │ │ │ └── xcschemes/ │ │ │ └── Tests.xcscheme │ │ └── TreapTests/ │ │ ├── Info.plist │ │ └── TreapTests.swift │ ├── Treap.swift │ ├── TreapCollectionType.swift │ └── TreapMergeSplit.swift ├── Tree/ │ ├── Images/ │ │ ├── Cycles.graffle │ │ ├── Example.graffle │ │ ├── ParentChildren.graffle │ │ └── Tree.graffle │ ├── README.markdown │ ├── Tree.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── Tree.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── Tree.swift ├── Trie/ │ ├── ReadMe.md │ └── Trie/ │ ├── Trie/ │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets/ │ │ │ └── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── ReadMe.md │ │ ├── Trie.swift │ │ ├── ViewController.swift │ │ └── dictionary.txt │ ├── Trie.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata/ │ │ └── xcbaselines/ │ │ └── EB798E0A1DFEF79900F0628D.xcbaseline/ │ │ ├── 6ABF2F62-9363-4450-8DE1-D20F57026950.plist │ │ └── Info.plist │ ├── TrieTests/ │ │ ├── Info.plist │ │ └── TrieTests.swift │ └── TrieUITests/ │ ├── Info.plist │ └── TrieUITests.swift ├── Two-Sum Problem/ │ ├── README.markdown │ ├── Solution 1/ │ │ └── 2Sum.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── Solution 2/ │ └── 2Sum.playground/ │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace/ │ ├── contents.xcworkspacedata │ └── xcshareddata/ │ └── IDEWorkspaceChecks.plist ├── Under Construction.markdown ├── Union-Find/ │ ├── README.markdown │ └── UnionFind.playground/ │ ├── Contents.swift │ ├── Sources/ │ │ ├── UnionFindQuickFind.swift │ │ ├── UnionFindQuickUnion.swift │ │ ├── UnionFindWeightedQuickFind.swift │ │ ├── UnionFindWeightedQuickUnion.swift │ │ └── UnionFindWeightedQuickUnionPathCompression.swift │ ├── contents.xcplayground │ └── playground.xcworkspace/ │ ├── contents.xcworkspacedata │ └── xcshareddata/ │ └── IDEWorkspaceChecks.plist ├── What are Algorithms.markdown ├── Why Algorithms.markdown ├── Z-Algorithm/ │ ├── README.markdown │ ├── ZAlgorithm.swift │ ├── ZetaAlgorithm.playground/ │ │ ├── Contents.swift │ │ ├── contents.xcplayground │ │ └── playground.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── ZetaAlgorithm.swift ├── gfm-render.sh └── install_swiftlint.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Contributing Guidelines Want to help out with the Swift Algorithm Club? Great! While we don't have strict templates on the format of each contribution, we do have a few guidelines that should be kept in mind: **Readability** Our repo is all about learning. The `README` file is the cake, and the sample code is the cherry on top. A good contribution has succinct explanations supported by diagrams. Code is best introduced in chunks, weaved into the explanations where relevant. > When choosing between brevity and performance, err to the side of brevity as long as the time complexity of the particular implementation is the same. You can make a note afterwards suggesting a more performant way of doing things. **API Design Guidelines** A good contribution abides to the [Swift API Guidelines](https://swift.org/documentation/api-design-guidelines/). We review the pull requests with this in mind. **Swift Language Guidelines** We follow the following Swift [style guide](https://github.com/raywenderlich/swift-style-guide). ## Contribution Categories ### Refinement Unit tests. Fixes for typos. No contribution is too small. :-) The repository has over 100 different data structures and algorithms. We're always interested in improvements to existing implementations and better explanations. Suggestions for making the code more Swift-like or to make it fit better with the standard library are most welcome. ### New Contributions Before writing about something new, you should do 2 things: 1. Check the main page for existing implementations 2. Check the [pull requests](https://github.com/raywenderlich/swift-algorithm-club/pulls) for "claimed" topics. More info on that below. If what you have in mind is a new addition, please follow this process when submitting your contribution: 1. Create a pull request to "claim" an algorithm or data structure. This is to avoid having multiple people working on the same thing. 2. Use this [style guide](https://github.com/raywenderlich/swift-style-guide) for writing code (more or less). 3. Write an explanation of how the algorithm works. Include **plenty of examples** for readers to follow along. Pictures are good. Take a look at [the explanation of quicksort](../Quicksort/) to get an idea. 4. Include your name in the explanation, something like *Written by Your Name* at the end of the document. 5. Add a playground and/or unit tests. For the unit tests: - Add the unit test project to `.travis.yml` so they will be run on [Travis-CI](https://travis-ci.org/raywenderlich/swift-algorithm-club). Add a line to `.travis.yml` like this: ``` - xctool test -project ./Algorithm/Tests/Tests.xcodeproj -scheme Tests ``` - Configure the Test project's scheme to run on Travis-CI: - Open **Product -> Scheme -> Manage Schemes...** - Uncheck **Autocreate schemes** - Check **Shared** ![Screenshot of scheme settings](../Images/scheme-settings-for-travis.png) ## Want to chat? This isn't just a repo with a bunch of code... If you want to learn more about how an algorithm works or want to discuss better ways of solving problems, then open a [Github issue](https://github.com/raywenderlich/swift-algorithm-club/issues) and we'll talk! ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ ### Brief Intro ### More Details ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ### Checklist - [ ] I've looked at the [contribution guidelines](https://github.com/raywenderlich/swift-algorithm-club/blob/master/.github/CONTRIBUTING.md). - [ ] This pull request is complete and ready for review. ### Description ================================================ FILE: .gitignore ================================================ # Xcode build/ DerivedData/ *.pbxuser *.mode1v3 *.mode2v3 *.perspectivev3 *.xccheckout *.moved-aside *.xcuserstate xcuserdata !default.pbxuser !default.mode1v3 !default.mode2v3 !default.perspectivev3 !default.xcworkspace profile *.hmap *.ipa # CocoaPods Pods/ !Podfile.lock # Temporary files .DS_Store .Trashes .Spotlight-V100 *.swp *.lock ================================================ FILE: .swiftlint.yml ================================================ cyclomatic_complexity: 12 file_length: 550 function_body_length: 80 function_parameter_count: 8 line_length: 150 type_body_length: 300 variable_name: min_length: error: 1 warning: 1 excluded: - N disabled_rules: - valid_docs custom_rules: smiley_face: name: "Smiley Face" regex: '( :\))' match_kinds: - comment - string message: "A closing parenthesis smiley :) creates a half-hearted smile, and thus is not preferred. Use :]" severity: warning ================================================ FILE: 3Sum and 4Sum/3Sum.playground/Contents.swift ================================================ // last checked with Xcode 10.1 #if swift(>=4.2) print("Hello, Swift 4.2!") #endif extension Collection where Element: Equatable { /// In a sorted collection, replaces the given index with a successor mapping to a unique element. /// /// - Parameter index: A valid index of the collection. `index` must be less than `endIndex` func formUniqueIndex(after index: inout Index) { var prev = index repeat { prev = index formIndex(after: &index) } while index < endIndex && self[prev] == self[index] } } extension BidirectionalCollection where Element: Equatable { /// In a sorted collection, replaces the given index with a predecessor that maps to a unique element. /// /// - Parameter index: A valid index of the collection. `index` must be greater than `startIndex`. func formUniqueIndex(before index: inout Index) { var prev = index repeat { prev = index formIndex(before: &index) } while index > startIndex && self[prev] == self[index] } } func threeSum(_ collection: T, target: T.Element) -> [[T.Element]] where T.Element: Numeric & Comparable { let sorted = collection.sorted() var ret: [[T.Element]] = [] var l = sorted.startIndex ThreeSum: while l < sorted.endIndex { defer { sorted.formUniqueIndex(after: &l) } var m = sorted.index(after: l) var r = sorted.index(before: sorted.endIndex) TwoSum: while m < r && r < sorted.endIndex { let sum = sorted[l] + sorted[m] + sorted[r] if sum == target { ret.append([sorted[l], sorted[m], sorted[r]]) sorted.formUniqueIndex(after: &m) sorted.formUniqueIndex(before: &r) } else if sum < target { sorted.formUniqueIndex(after: &m) } else { sorted.formUniqueIndex(before: &r) } } } return ret } // Answer: [[-1, 0, 1], [-1, -1, 2]] threeSum([-1, 0, 1, 2, -1, -4], target: 0) // Answer: [[-1, -1, 2], [-1, 0, 1]] threeSum([-1, -1, -1, -1, 2, 1, -4, 0], target: 0) // Answer: [[-1, -1, 2]] threeSum([-1, -1, -1, -1, -1, -1, 2], target: 0) ================================================ FILE: 3Sum and 4Sum/3Sum.playground/contents.xcplayground ================================================ ================================================ FILE: 3Sum and 4Sum/3Sum.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: 3Sum and 4Sum/3Sum.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: 3Sum and 4Sum/4Sum.playground/Contents.swift ================================================ // last checked with Xcode 10.1 #if swift(>=4.2) print("Hello, Swift 4.2!") #endif extension Collection where Element: Equatable { /// In a sorted collection, replaces the given index with a successor mapping to a unique element. /// /// - Parameter index: A valid index of the collection. `index` must be less than `endIndex` func formUniqueIndex(after index: inout Index) { var prev = index repeat { prev = index formIndex(after: &index) } while index < endIndex && self[prev] == self[index] } } extension BidirectionalCollection where Element: Equatable { /// In a sorted collection, replaces the given index with a predecessor that maps to a unique element. /// /// - Parameter index: A valid index of the collection. `index` must be greater than `startIndex`. func formUniqueIndex(before index: inout Index) { var prev = index repeat { prev = index formIndex(before: &index) } while index > startIndex && self[prev] == self[index] } } func fourSum(_ collection: T, target: T.Element) -> [[T.Element]] where T.Element: Numeric & Comparable { let sorted = collection.sorted() var ret: [[T.Element]] = [] var l = sorted.startIndex FourSum: while l < sorted.endIndex { defer { sorted.formUniqueIndex(after: &l) } var ml = sorted.index(after: l) ThreeSum: while ml < sorted.endIndex { defer { sorted.formUniqueIndex(after: &ml) } var mr = sorted.index(after: ml) var r = sorted.index(before: sorted.endIndex) TwoSum: while mr < r && r < sorted.endIndex { let sum = sorted[l] + sorted[ml] + sorted[mr] + sorted[r] if sum == target { ret.append([sorted[l], sorted[ml], sorted[mr], sorted[r]]) sorted.formUniqueIndex(after: &mr) sorted.formUniqueIndex(before: &r) } else if sum < target { sorted.formUniqueIndex(after: &mr) } else { sorted.formUniqueIndex(before: &r) } } } } return ret } // answer: [[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]] fourSum([1, 0, -1, 0, -2, 2], target: 0) ================================================ FILE: 3Sum and 4Sum/4Sum.playground/contents.xcplayground ================================================ ================================================ FILE: 3Sum and 4Sum/4Sum.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: 3Sum and 4Sum/4Sum.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: 3Sum and 4Sum/README.md ================================================ # 3Sum and 4Sum 3Sum and 4Sum are extensions of a popular algorithm question, the [2Sum][5]. ## 3Sum > Given an array of integers, find all subsets of the array with 3 values where the 3 values sum up to a target number. > > **Note**: The solution subsets must not contain duplicate triplets. > > For example, given the array [-1, 0, 1, 2, -1, -4], and the target **0**: > The solution set is: [[-1, 0, 1], [-1, -1, 2]] // The two **-1** values in the array are considered to be distinct There are 2 key procedures in solving this algorithm. Sorting the array, and avoiding duplicates. ### Sorting Sorting your input array allows for powerful assumptions: * duplicates are always adjacent to each other * moving an index to the right increases the value, while moving an index to the left decreases the value You'll make use of these two rules to create an efficient algorithm. ### Avoiding Duplicates Since you pre-sort the array, duplicates will be adjacent to each other. You just need to skip over duplicates by comparing adjacent values: ```swift extension Collection where Element: Equatable { /// In a sorted collection, replaces the given index with a successor mapping to a unique element. /// /// - Parameter index: A valid index of the collection. `index` must be less than `endIndex` func formUniqueIndex(after index: inout Index) { var prev = index repeat { prev = index formIndex(after: &index) } while index < endIndex && self[prev] == self[index] } } ``` A similar implementation is used to get the unique index *before* a given index: ```swift extension BidirectionalCollection where Element: Equatable { /// In a sorted collection, replaces the given index with a predecessor that maps to a unique element. /// /// - Parameter index: A valid index of the collection. `index` must be greater than `startIndex`. func formUniqueIndex(before index: inout Index) { var prev = index repeat { prev = index formIndex(before: &index) } while index > startIndex && self[prev] == self[index] } } ``` ### Assembling the Subsets You'll keep track of 3 indices to represent the 3 numbers. The sum at any given moment is `array[l] + array[m] + array[r]`: ```swift m -> <- r [-4, -1, -1, 0, 1, 2]  l ``` The premise is quite straightforward (given that you're familiar with 2Sum). You'll iterate `l` through the array. For every iteration, you also apply the 2Sum algorithm to elements after `l`. You'll check the sum every time you moving the indices to check if you found match. Here's the algorithm: ```swift func threeSum(_ collection: T, target: T.Element) -> [[T.Element]] where T.Element: Numeric & Comparable { let sorted = collection.sorted() var ret: [[T.Element]] = [] var l = sorted.startIndex ThreeSum: while l < sorted.endIndex { defer { sorted.formUniqueIndex(after: &l) } var m = sorted.index(after: l) var r = sorted.index(before: sorted.endIndex) TwoSum: while m < r && r < sorted.endIndex { let sum = sorted[l] + sorted[m] + sorted[r] if sum == target { ret.append([sorted[l], sorted[m], sorted[r]]) sorted.formUniqueIndex(after: &m) sorted.formUniqueIndex(before: &r) } else if sum < target { sorted.formUniqueIndex(after: &m) } else { sorted.formUniqueIndex(before: &r) } } } return ret } ``` ## 4Sum > Given an array S of n integers, find all subsets of the array with 4 values where the 4 values sum up to a target number. > > **Note**: The solution set must not contain duplicate quadruplets. ### Solution Foursum is a very straightforward extension to the threeSum algorithm. In threeSum, you kept track of 3 indices: ```swift m -> <- r [-4, -1, -1, 0, 1, 2]  l ``` For fourSum, you'll keep track of 4: ```swift mr -> <- r [-4, -1, -1, 0, 1, 2]  l ml -> ``` Here's the code for it (notice it is very similar to 3Sum): ```swift func fourSum(_ collection: T, target: T.Element) -> [[T.Element]] where T.Element: Numeric & Comparable { let sorted = collection.sorted() var ret: [[T.Element]] = [] var l = sorted.startIndex FourSum: while l < sorted.endIndex { defer { sorted.formUniqueIndex(after: &l) } var ml = sorted.index(after: l) ThreeSum: while ml < sorted.endIndex { defer { sorted.formUniqueIndex(after: &ml) } var mr = sorted.index(after: ml) var r = sorted.index(before: sorted.endIndex) TwoSum: while mr < r && r < sorted.endIndex { let sum = sorted[l] + sorted[ml] + sorted[mr] + sorted[r] if sum == target { ret.append([sorted[l], sorted[ml], sorted[mr], sorted[r]]) sorted.formUniqueIndex(after: &mr) sorted.formUniqueIndex(before: &r) } else if sum < target { sorted.formUniqueIndex(after: &mr) } else { sorted.formUniqueIndex(before: &r) } } } } return ret } ``` [5]: https://github.com/raywenderlich/swift-algorithm-club/tree/master/Two-Sum%20Problem *Written for the Swift Algorithm Club by Kai Chen and Kelvin Lau* ================================================ FILE: A-Star/AStar.swift ================================================ // Written by Alejandro Isaza. import Foundation public protocol Graph { associatedtype Vertex: Hashable associatedtype Edge: WeightedEdge where Edge.Vertex == Vertex /// Lists all edges going out from a vertex. func edgesOutgoing(from vertex: Vertex) -> [Edge] } public protocol WeightedEdge { associatedtype Vertex /// The edge's cost. var cost: Double { get } /// The target vertex. var target: Vertex { get } } public final class AStar { /// The graph to search on. public let graph: G /// The heuristic cost function that estimates the cost between two vertices. /// /// - Note: The heuristic function needs to always return a value that is lower-than or equal to the actual /// cost for the resulting path of the A* search to be optimal. public let heuristic: (G.Vertex, G.Vertex) -> Double /// Open list of nodes to expand. private var open: HashedHeap> /// Closed list of vertices already expanded. private var closed = Set() /// Actual vertex cost for vertices we already encountered (refered to as `g` on the literature). private var costs = Dictionary() /// Store the previous node for each expanded node to recreate the path. private var parents = Dictionary() /// Initializes `AStar` with a graph and a heuristic cost function. public init(graph: G, heuristic: @escaping (G.Vertex, G.Vertex) -> Double) { self.graph = graph self.heuristic = heuristic open = HashedHeap(sort: <) } /// Finds an optimal path between `source` and `target`. /// /// - Precondition: both `source` and `target` belong to `graph`. public func path(start: G.Vertex, target: G.Vertex) -> [G.Vertex] { open.insert(Node(vertex: start, cost: 0, estimate: heuristic(start, target))) while !open.isEmpty { guard let node = open.remove() else { break } costs[node.vertex] = node.cost if (node.vertex == target) { let path = buildPath(start: start, target: target) cleanup() return path } if !closed.contains(node.vertex) { expand(node: node, target: target) closed.insert(node.vertex) } } // No path found return [] } private func expand(node: Node, target: G.Vertex) { let edges = graph.edgesOutgoing(from: node.vertex) for edge in edges { let g = cost(node.vertex) + edge.cost if g < cost(edge.target) { open.insert(Node(vertex: edge.target, cost: g, estimate: heuristic(edge.target, target))) parents[edge.target] = node.vertex } } } private func cost(_ vertex: G.Edge.Vertex) -> Double { if let c = costs[vertex] { return c } let node = Node(vertex: vertex, cost: Double.greatestFiniteMagnitude, estimate: 0) if let index = open.index(of: node) { return open[index].cost } return Double.greatestFiniteMagnitude } private func buildPath(start: G.Vertex, target: G.Vertex) -> [G.Vertex] { var path = Array() path.append(target) var current = target while current != start { guard let parent = parents[current] else { return [] // no path found } current = parent path.append(current) } return path.reversed() } private func cleanup() { open.removeAll() closed.removeAll() parents.removeAll() } } private struct Node: Hashable, Comparable { /// The graph vertex. var vertex: V /// The actual cost between the start vertex and this vertex. var cost: Double /// Estimated (heuristic) cost betweent this vertex and the target vertex. var estimate: Double public init(vertex: V, cost: Double, estimate: Double) { self.vertex = vertex self.cost = cost self.estimate = estimate } static func < (lhs: Node, rhs: Node) -> Bool { return lhs.cost + lhs.estimate < rhs.cost + rhs.estimate } static func == (lhs: Node, rhs: Node) -> Bool { return lhs.vertex == rhs.vertex } var hashValue: Int { return vertex.hashValue } } ================================================ FILE: A-Star/Images/graph.dot ================================================ digraph G { rankdir=LR; { A [ label = "h = 3" ] } { rank = same; B [ label = "h = 2" ]; C [ label = "h = 2" ]; D [ label = "h = 2" ] } { rank = same; E [ label = "h = 1" ]; F [ label = "h = 1" ]; G [ label = "h = 1" ] } { H [ label = "h = 0", style = filled, color = green ] } A -> { B C D } B -> E E -> F D -> G G -> H } ================================================ FILE: A-Star/Images/step1.dot ================================================ digraph G { rankdir=LR; { A [ label = "g = 0\nh = 3", style = filled, color = deepskyblue1 ] } { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; C [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; D [ label = "g = 1\nh = 2", style = filled, color = lightgrey ] } { rank = same; E [ label = "g = \?\nh = 1" ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] } { H [ label = "g = \?\nh = 0" ] } A -> { B C D } B -> E E -> F D -> G G -> H } ================================================ FILE: A-Star/Images/step2.dot ================================================ digraph G { rankdir=LR; { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = deepskyblue1 ]; C [ label = "g = 1\nh = 2", style = filled, color = lightgrey ]; D [ label = "g = 1\nh = 2", style = filled, color = lightgrey ] } { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] } { H [ label = "g = \?\nh = 0" ] } A -> { B C D } B -> E E -> F D -> G G -> H } ================================================ FILE: A-Star/Images/step3.dot ================================================ digraph G { rankdir=LR; { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = deepskyblue1 ]; D [ label = "g = 1\nh = 2", style = filled, color = lightgrey ] } { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = \?\nh = 1" ] } { H [ label = "g = \?\nh = 0" ] } A -> { B C D } B -> E E -> F D -> G G -> H } ================================================ FILE: A-Star/Images/step4.dot ================================================ digraph G { rankdir=LR; { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = deepskyblue1 ] } { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightgrey ]; F [ label = "g = \?\nh = 1" ]; G [ label = "g = 2\nh = 1", style = filled, color = lightgrey ] } { H [ label = "g = \?\nh = 0" ] } A -> { B C D } B -> E E -> F D -> G G -> H } ================================================ FILE: A-Star/Images/step5.dot ================================================ digraph G { rankdir=LR; { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] } { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = deepskyblue1 ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = lightgrey ] } { H [ label = "g = \?\nh = 0" ] } A -> { B C D } B -> E E -> F D -> G G -> H } ================================================ FILE: A-Star/Images/step6.dot ================================================ digraph G { rankdir=LR; { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] } { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightblue ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = deepskyblue1 ] } { H [ label = "g = 3\nh = 0", style = filled, color = lightgrey ] } A -> { B C D } B -> E E -> F D -> G G -> H } ================================================ FILE: A-Star/Images/step7.dot ================================================ digraph G { rankdir=LR; { A [ label = "g = 0\nh = 3", style = filled, color = lightblue ] } { rank = same; B [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; C [ label = "g = 1\nh = 2", style = filled, color = lightblue ]; D [ label = "g = 1\nh = 2", style = filled, color = lightblue ] } { rank = same; E [ label = "g = 2\nh = 1", style = filled, color = lightblue ]; F [ label = "g = 3\nh = 1", style = filled, color = lightgrey ]; G [ label = "g = 2\nh = 1", style = filled, color = lightblue ] } { H [ label = "g = 3\nh = 0", style = filled, color = deepskyblue1 ] } A -> { B C D } B -> E E -> F D -> G G -> H } ================================================ FILE: A-Star/README.md ================================================ # A* A* (pronounced "ay star") is a heuristic best-first search algorithm. A* minimizes node expansions, therefore minimizing the search time, by using a heuristic function. The heuristic function gives an estimate of the distance between two vertices. For instance if you are searching for a path between two points in a city, you can estimate the actual street distance with the straight-line distance. A* works by expanding the most promising nodes first, according to the heuristic function. In the city example it would choose streets which go in the general direction of the target first and, only if those are dead ends, backtrack and try other streets. This speeds up search in most sitations. A* is optimal (it always find the shortest path) if the heuristic function is admissible. A heuristic function is admissible if it never overestimates the cost of reaching the goal. In the extreme case of the heuristic function always retuning `0` A* acts exactly the same as [Dijkstra's Algorithm](../Dijkstra). The closer the heuristic function is to the actual distance the faster the search. ## Example Let's run through an example on this simple directed graph. We are going to assume that all edges have a cost of 1 and the heuristic function is going to be the column starting at goal and going back: ![Graph](Images/graph.png) On the first step we expand the root node on the left (blue). We set the cost `g` to zero and add all neighbors to the open list (grey). ![Step 1](Images/step1.png) We put the first node in the closed list (light blue) so that we don't try expanding it again if there were to be loops in the graph. Next we take the node on the open list with the smallest value of `g + h` where `g` is the current cost (0) plus the edge cost (1). Since all nodes in the open list have the same value we choose the top one. ![Step 2](Images/step2.png) We repeat the process and pick the next node from the open list. In this case there are no new nodes to add to the open list. ![Step 3](Images/step3.png) We expand the next node. One more node on the open list, but nothing exciting yet. ![Step 4](Images/step4.png) Sicne the top and the bottom nodes have the same value we choose the top one. This is not a great choice but we could do better if we had a better heuristic function. ![Step 5](Images/step5.png) Now we expand the bottom node because it has a smaller value than the middle node (2 + 1 < 3 + 1). ![Step 6](Images/step6.png) And we finally reach the goal! We never even expanded that middle node. We didn't have to because its value is 4, which is equal to the total lenght of our solution and therefore guaranteed to not be part of the optimal solution. ![Step 7](Images/step7.png) The final step is to backtrack from the goal node to buld the optimal path. ================================================ FILE: A-Star/Tests/AStarTests.swift ================================================ import Foundation import XCTest struct GridGraph: Graph { struct Vertex: Hashable { var x: Int var y: Int static func == (lhs: Vertex, rhs: Vertex) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } public var hashValue: Int { return x.hashValue ^ y.hashValue } } struct Edge: WeightedEdge { var cost: Double var target: Vertex } func edgesOutgoing(from vertex: Vertex) -> [Edge] { return [ Edge(cost: 1, target: Vertex(x: vertex.x - 1, y: vertex.y)), Edge(cost: 1, target: Vertex(x: vertex.x + 1, y: vertex.y)), Edge(cost: 1, target: Vertex(x: vertex.x, y: vertex.y - 1)), Edge(cost: 1, target: Vertex(x: vertex.x, y: vertex.y + 1)), ] } } class AStarTests: XCTestCase { func testSameStartAndEnd() { let graph = GridGraph() let astar = AStar(graph: graph, heuristic: manhattanDistance) let path = astar.path(start: GridGraph.Vertex(x: 0, y: 0), target: GridGraph.Vertex(x: 0, y: 0)) XCTAssertEqual(path.count, 1) XCTAssertEqual(path[0].x, 0) XCTAssertEqual(path[0].y, 0) } func testDiagonal() { let graph = GridGraph() let astar = AStar(graph: graph, heuristic: manhattanDistance) let path = astar.path(start: GridGraph.Vertex(x: 0, y: 0), target: GridGraph.Vertex(x: 10, y: 10)) XCTAssertEqual(path.count, 21) XCTAssertEqual(path[0].x, 0) XCTAssertEqual(path[0].y, 0) XCTAssertEqual(path[20].x, 10) XCTAssertEqual(path[20].y, 10) } func manhattanDistance(_ s: GridGraph.Vertex, _ t: GridGraph.Vertex) -> Double { return Double(abs(s.x - t.x) + abs(s.y - t.y)) } } ================================================ FILE: A-Star/Tests/AStarTests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 611D099C1F8978AB00C7092B /* AStarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611D099B1F8978AB00C7092B /* AStarTests.swift */; }; 611D099E1F8978BC00C7092B /* AStar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611D099D1F8978BB00C7092B /* AStar.swift */; }; 611D09A01F89795100C7092B /* HashedHeap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611D099F1F89795100C7092B /* HashedHeap.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 611D099B1F8978AB00C7092B /* AStarTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AStarTests.swift; sourceTree = ""; }; 611D099D1F8978BB00C7092B /* AStar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AStar.swift; path = ../AStar.swift; sourceTree = ""; }; 611D099F1F89795100C7092B /* HashedHeap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HashedHeap.swift; path = "../../Hashed Heap/HashedHeap.swift"; sourceTree = ""; }; 7B2BBC801C779D720067B71D /* AStarTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AStarTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* AStarTests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 611D099F1F89795100C7092B /* HashedHeap.swift */, 611D099D1F8978BB00C7092B /* AStar.swift */, 611D099B1F8978AB00C7092B /* AStarTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* AStarTests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "AStarTests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = AStarTests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* AStarTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0900; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "AStarTests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* AStarTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 611D099C1F8978AB00C7092B /* AStarTests.swift in Sources */, 611D099E1F8978BC00C7092B /* AStar.swift in Sources */, 611D09A01F89795100C7092B /* HashedHeap.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "AStarTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "AStarTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: A-Star/Tests/AStarTests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: A-Star/Tests/AStarTests.xcodeproj/xcshareddata/xcschemes/AStarTests.xcscheme ================================================ ================================================ FILE: A-Star/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: AVL Tree/AVLTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play let tree = AVLTree() tree.insert(key: 5, payload: "five") print(tree) tree.insert(key: 4, payload: "four") print(tree) tree.insert(key: 3, payload: "three") print(tree) tree.insert(key: 2, payload: "two") print(tree) tree.insert(key: 1, payload: "one") print(tree) print(tree.debugDescription) let node = tree.search(input: 2) // "two" tree.delete(key: 5) tree.delete(key: 2) tree.delete(key: 1) tree.delete(key: 4) tree.delete(key: 3) ================================================ FILE: AVL Tree/AVLTree.playground/Sources/AVLTree.swift ================================================ // The MIT License (MIT) // Copyright (c) 2016 Mike Taghavi (mitghi[at]me.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. public class TreeNode { public typealias Node = TreeNode var payload: Payload? fileprivate var key: Key internal var leftChild: Node? internal var rightChild: Node? fileprivate var height: Int weak fileprivate var parent: Node? public init(key: Key, payload: Payload?, leftChild: Node?, rightChild: Node?, parent: Node?, height: Int) { self.key = key self.payload = payload self.leftChild = leftChild self.rightChild = rightChild self.parent = parent self.height = height self.leftChild?.parent = self self.rightChild?.parent = self } public convenience init(key: Key, payload: Payload?) { self.init(key: key, payload: payload, leftChild: nil, rightChild: nil, parent: nil, height: 1) } public convenience init(key: Key) { self.init(key: key, payload: nil) } var isRoot: Bool { return parent == nil } var isLeaf: Bool { return rightChild == nil && leftChild == nil } var isLeftChild: Bool { return parent?.leftChild === self } var isRightChild: Bool { return parent?.rightChild === self } var hasLeftChild: Bool { return leftChild != nil } var hasRightChild: Bool { return rightChild != nil } var hasAnyChild: Bool { return leftChild != nil || rightChild != nil } var hasBothChildren: Bool { return leftChild != nil && rightChild != nil } } // MARK: - The AVL tree open class AVLTree { public typealias Node = TreeNode fileprivate(set) var root: Node? fileprivate(set) var size = 0 public init() { } } // MARK: - Searching extension TreeNode { public func minimum() -> TreeNode? { return leftChild?.minimum() ?? self } public func maximum() -> TreeNode? { return rightChild?.maximum() ?? self } } extension AVLTree { subscript(key: Key) -> Payload? { get { return search(input: key) } set { insert(key: key, payload: newValue) } } public func search(input: Key) -> Payload? { return search(key: input, node: root)?.payload } fileprivate func search(key: Key, node: Node?) -> Node? { if let node = node { if key == node.key { return node } else if key < node.key { return search(key: key, node: node.leftChild) } else { return search(key: key, node: node.rightChild) } } return nil } } // MARK: - Inserting new items extension AVLTree { public func insert(key: Key, payload: Payload? = nil) { if let root = root { insert(input: key, payload: payload, node: root) } else { root = Node(key: key, payload: payload) } size += 1 } private func insert(input: Key, payload: Payload?, node: Node) { if input < node.key { if let child = node.leftChild { insert(input: input, payload: payload, node: child) } else { let child = Node(key: input, payload: payload, leftChild: nil, rightChild: nil, parent: node, height: 1) node.leftChild = child balance(node: child) } } else { if let child = node.rightChild { insert(input: input, payload: payload, node: child) } else { let child = Node(key: input, payload: payload, leftChild: nil, rightChild: nil, parent: node, height: 1) node.rightChild = child balance(node: child) } } } } // MARK: - Balancing tree extension AVLTree { fileprivate func updateHeightUpwards(node: Node?) { if let node = node { let lHeight = node.leftChild?.height ?? 0 let rHeight = node.rightChild?.height ?? 0 node.height = max(lHeight, rHeight) + 1 updateHeightUpwards(node: node.parent) } } fileprivate func lrDifference(node: Node?) -> Int { let lHeight = node?.leftChild?.height ?? 0 let rHeight = node?.rightChild?.height ?? 0 return lHeight - rHeight } fileprivate func balance(node: Node?) { guard let node = node else { return } updateHeightUpwards(node: node.leftChild) updateHeightUpwards(node: node.rightChild) var nodes = [Node?](repeating: nil, count: 3) var subtrees = [Node?](repeating: nil, count: 4) let nodeParent = node.parent let lrFactor = lrDifference(node: node) if lrFactor > 1 { // left-left or left-right if lrDifference(node: node.leftChild) > 0 { // left-left nodes[0] = node nodes[2] = node.leftChild nodes[1] = nodes[2]?.leftChild subtrees[0] = nodes[1]?.leftChild subtrees[1] = nodes[1]?.rightChild subtrees[2] = nodes[2]?.rightChild subtrees[3] = nodes[0]?.rightChild } else { // left-right nodes[0] = node nodes[1] = node.leftChild nodes[2] = nodes[1]?.rightChild subtrees[0] = nodes[1]?.leftChild subtrees[1] = nodes[2]?.leftChild subtrees[2] = nodes[2]?.rightChild subtrees[3] = nodes[0]?.rightChild } } else if lrFactor < -1 { // right-left or right-right if lrDifference(node: node.rightChild) < 0 { // right-right nodes[1] = node nodes[2] = node.rightChild nodes[0] = nodes[2]?.rightChild subtrees[0] = nodes[1]?.leftChild subtrees[1] = nodes[2]?.leftChild subtrees[2] = nodes[0]?.leftChild subtrees[3] = nodes[0]?.rightChild } else { // right-left nodes[1] = node nodes[0] = node.rightChild nodes[2] = nodes[0]?.leftChild subtrees[0] = nodes[1]?.leftChild subtrees[1] = nodes[2]?.leftChild subtrees[2] = nodes[2]?.rightChild subtrees[3] = nodes[0]?.rightChild } } else { // Don't need to balance 'node', go for parent balance(node: node.parent) return } // nodes[2] is always the head if node.isRoot { root = nodes[2] root?.parent = nil } else if node.isLeftChild { nodeParent?.leftChild = nodes[2] nodes[2]?.parent = nodeParent } else if node.isRightChild { nodeParent?.rightChild = nodes[2] nodes[2]?.parent = nodeParent } nodes[2]?.leftChild = nodes[1] nodes[1]?.parent = nodes[2] nodes[2]?.rightChild = nodes[0] nodes[0]?.parent = nodes[2] nodes[1]?.leftChild = subtrees[0] subtrees[0]?.parent = nodes[1] nodes[1]?.rightChild = subtrees[1] subtrees[1]?.parent = nodes[1] nodes[0]?.leftChild = subtrees[2] subtrees[2]?.parent = nodes[0] nodes[0]?.rightChild = subtrees[3] subtrees[3]?.parent = nodes[0] updateHeightUpwards(node: nodes[1]) // Update height from left updateHeightUpwards(node: nodes[0]) // Update height from right balance(node: nodes[2]?.parent) } } // MARK: - Displaying tree extension AVLTree { fileprivate func display(node: Node?, level: Int) { if let node = node { display(node: node.rightChild, level: level + 1) print("") if node.isRoot { print("Root -> ", terminator: "") } for _ in 0.. ================================================ FILE: AVL Tree/AVLTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: AVL Tree/AVLTree.swift ================================================ // The MIT License (MIT) // Copyright (c) 2016 Mike Taghavi (mitghi[at]me.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. public class TreeNode { public typealias Node = TreeNode var payload: Payload? // Value held by the node fileprivate var key: Key // Node's name internal var leftChild: Node? internal var rightChild: Node? fileprivate var height: Int weak fileprivate var parent: Node? public init(key: Key, payload: Payload?, leftChild: Node?, rightChild: Node?, parent: Node?, height: Int) { self.key = key self.payload = payload self.leftChild = leftChild self.rightChild = rightChild self.parent = parent self.height = height self.leftChild?.parent = self self.rightChild?.parent = self } public convenience init(key: Key, payload: Payload?) { self.init(key: key, payload: payload, leftChild: nil, rightChild: nil, parent: nil, height: 1) } public convenience init(key: Key) { self.init(key: key, payload: nil) } var isRoot: Bool { return parent == nil } var isLeaf: Bool { return rightChild == nil && leftChild == nil } var isLeftChild: Bool { return parent?.leftChild === self } var isRightChild: Bool { return parent?.rightChild === self } var hasLeftChild: Bool { return leftChild != nil } var hasRightChild: Bool { return rightChild != nil } var hasAnyChild: Bool { return leftChild != nil || rightChild != nil } var hasBothChildren: Bool { return leftChild != nil && rightChild != nil } } // MARK: - The AVL tree open class AVLTree { public typealias Node = TreeNode fileprivate(set) var root: Node? fileprivate(set) var size = 0 public init() { } } // MARK: - Searching extension TreeNode { public func minimum() -> TreeNode? { return leftChild?.minimum() ?? self } public func maximum() -> TreeNode? { return rightChild?.maximum() ?? self } } extension AVLTree { subscript(key: Key) -> Payload? { get { return search(input: key) } set { insert(key: key, payload: newValue) } } public func search(input: Key) -> Payload? { return search(key: input, node: root)?.payload } fileprivate func search(key: Key, node: Node?) -> Node? { if let node = node { if key == node.key { return node } else if key < node.key { return search(key: key, node: node.leftChild) } else { return search(key: key, node: node.rightChild) } } return nil } } // MARK: - Inserting new items extension AVLTree { public func insert(key: Key, payload: Payload? = nil) { if let root = root { insert(input: key, payload: payload, node: root) } else { root = Node(key: key, payload: payload) } size += 1 } private func insert(input: Key, payload: Payload?, node: Node) { if input < node.key { if let child = node.leftChild { insert(input: input, payload: payload, node: child) } else { let child = Node(key: input, payload: payload, leftChild: nil, rightChild: nil, parent: node, height: 1) node.leftChild = child balance(node: child) } } else if input != node.key { if let child = node.rightChild { insert(input: input, payload: payload, node: child) } else { let child = Node(key: input, payload: payload, leftChild: nil, rightChild: nil, parent: node, height: 1) node.rightChild = child balance(node: child) } } } } // MARK: - Balancing tree extension AVLTree { fileprivate func updateHeightUpwards(node: Node?) { if let node = node { let lHeight = node.leftChild?.height ?? 0 let rHeight = node.rightChild?.height ?? 0 node.height = max(lHeight, rHeight) + 1 updateHeightUpwards(node: node.parent) } } fileprivate func lrDifference(node: Node?) -> Int { let lHeight = node?.leftChild?.height ?? 0 let rHeight = node?.rightChild?.height ?? 0 return lHeight - rHeight } fileprivate func balance(node: Node?) { guard let node = node else { return } updateHeightUpwards(node: node.leftChild) updateHeightUpwards(node: node.rightChild) var nodes = [Node?](repeating: nil, count: 3) var subtrees = [Node?](repeating: nil, count: 4) let nodeParent = node.parent let lrFactor = lrDifference(node: node) if lrFactor > 1 { // left-left or left-right if lrDifference(node: node.leftChild) > 0 { // left-left nodes[0] = node nodes[2] = node.leftChild nodes[1] = nodes[2]?.leftChild subtrees[0] = nodes[1]?.leftChild subtrees[1] = nodes[1]?.rightChild subtrees[2] = nodes[2]?.rightChild subtrees[3] = nodes[0]?.rightChild } else { // left-right nodes[0] = node nodes[1] = node.leftChild nodes[2] = nodes[1]?.rightChild subtrees[0] = nodes[1]?.leftChild subtrees[1] = nodes[2]?.leftChild subtrees[2] = nodes[2]?.rightChild subtrees[3] = nodes[0]?.rightChild } } else if lrFactor < -1 { // right-left or right-right if lrDifference(node: node.rightChild) < 0 { // right-right nodes[1] = node nodes[2] = node.rightChild nodes[0] = nodes[2]?.rightChild subtrees[0] = nodes[1]?.leftChild subtrees[1] = nodes[2]?.leftChild subtrees[2] = nodes[0]?.leftChild subtrees[3] = nodes[0]?.rightChild } else { // right-left nodes[1] = node nodes[0] = node.rightChild nodes[2] = nodes[0]?.leftChild subtrees[0] = nodes[1]?.leftChild subtrees[1] = nodes[2]?.leftChild subtrees[2] = nodes[2]?.rightChild subtrees[3] = nodes[0]?.rightChild } } else { // Don't need to balance 'node', go for parent balance(node: node.parent) return } // nodes[2] is always the head if node.isRoot { root = nodes[2] root?.parent = nil } else if node.isLeftChild { nodeParent?.leftChild = nodes[2] nodes[2]?.parent = nodeParent } else if node.isRightChild { nodeParent?.rightChild = nodes[2] nodes[2]?.parent = nodeParent } nodes[2]?.leftChild = nodes[1] nodes[1]?.parent = nodes[2] nodes[2]?.rightChild = nodes[0] nodes[0]?.parent = nodes[2] nodes[1]?.leftChild = subtrees[0] subtrees[0]?.parent = nodes[1] nodes[1]?.rightChild = subtrees[1] subtrees[1]?.parent = nodes[1] nodes[0]?.leftChild = subtrees[2] subtrees[2]?.parent = nodes[0] nodes[0]?.rightChild = subtrees[3] subtrees[3]?.parent = nodes[0] updateHeightUpwards(node: nodes[1]) // Update height from left updateHeightUpwards(node: nodes[0]) // Update height from right balance(node: nodes[2]?.parent) } } // MARK: - Displaying tree extension AVLTree { fileprivate func display(node: Node?, level: Int) { if let node = node { display(node: node.rightChild, level: level + 1) print("") if node.isRoot { print("Root -> ", terminator: "") } for _ in 0.. String { var output = "" if let node = node { output = "\(inorder(node: node.leftChild)) \(print("\(node.key) ")) \(inorder(node: node.rightChild))" } return output } public func preorder(node: Node?) -> String { var output = "" if let node = node { output = "\(preorder(node: node.leftChild)) \(print("\(node.key) ")) \(preorder(node: node.rightChild))" } return output } public func postorder(node: Node?) -> String { var output = "" if let node = node { output = "\(postorder(node: node.leftChild)) \(print("\(node.key) ")) \(postorder(node: node.rightChild))" } return output } } // MARK: - Delete node extension AVLTree { public func delete(key: Key) { if size == 1 { root = nil size -= 1 } else if let node = search(key: key, node: root) { delete(node: node) size -= 1 } } private func delete(node: Node) { if node.isLeaf { // Just remove and balance up if let parent = node.parent { guard node.isLeftChild || node.isRightChild else { // just in case fatalError("Error: tree is invalid.") } if node.isLeftChild { parent.leftChild = nil } else if node.isRightChild { parent.rightChild = nil } balance(node: parent) } else { // at root root = nil } } else { // Handle stem cases if let replacement = node.leftChild?.maximum(), replacement !== node { node.key = replacement.key node.payload = replacement.payload delete(node: replacement) } else if let replacement = node.rightChild?.minimum(), replacement !== node { node.key = replacement.key node.payload = replacement.payload delete(node: replacement) } } } } // MARK: - Advanced Stuff extension AVLTree { public func doInOrder(node: Node?, _ completion: (Node) -> Void) { if let node = node { doInOrder(node: node.leftChild) { lnode in completion(lnode) } completion(node) doInOrder(node: node.rightChild) { rnode in completion(rnode) } } } public func doInPreOrder(node: Node?, _ completion: (Node) -> Void) { if let node = node { completion(node) doInPreOrder(node: node.leftChild) { lnode in completion(lnode) } doInPreOrder(node: node.rightChild) { rnode in completion(rnode) } } } public func doInPostOrder(node: Node?, _ completion: (Node) -> Void) { if let node = node { doInPostOrder(node: node.leftChild) { lnode in completion(lnode) } doInPostOrder(node: node.rightChild) { rnode in completion(rnode) } completion(node) } } } // MARK: - Debugging extension TreeNode: CustomDebugStringConvertible { public var debugDescription: String { var s = "key: \(key), payload: \(payload), height: \(height)" if let parent = parent { s += ", parent: \(parent.key)" } if let left = leftChild { s += ", left = [" + left.debugDescription + "]" } if let right = rightChild { s += ", right = [" + right.debugDescription + "]" } return s } } extension AVLTree: CustomDebugStringConvertible { public var debugDescription: String { return root?.debugDescription ?? "[]" } } extension TreeNode: CustomStringConvertible { public var description: String { var s = "" if let left = leftChild { s += "(\(left.description)) <- " } s += "\(key)" if let right = rightChild { s += " -> (\(right.description))" } return s } } extension AVLTree: CustomStringConvertible { public var description: String { return root?.description ?? "[]" } } ================================================ FILE: AVL Tree/README.markdown ================================================ # AVL Tree An AVL tree is a self-balancing form of a [binary search tree](../Binary%20Search%20Tree/), in which the height of subtrees differ at most by only 1. A binary tree is *balanced* when its left and right subtrees contain roughly the same number of nodes. That is what makes searching the tree really fast. But if a binary search tree is unbalanced, searching can become really slow. This is an example of an unbalanced tree: ![Unbalanced tree](Images/Unbalanced.png) All the children are in the left branch and none are in the right. This is essentially the same as a [linked list](../Linked%20List/). As a result, searching takes **O(n)** time instead of the much faster **O(log n)** that you'd expect from a binary search tree. A balanced version of that tree would look like this: ![Balanced tree](Images/Balanced.png) One way to make the binary search tree balanced is to insert the nodes in a totally random order. But that doesn't guarantee success, nor is it always practical. The other solution is to use a *self-balancing* binary tree. This type of data structure adjusts the tree to keep it balanced after you insert or delete nodes. The height of such a tree is guaranteed to be *log(n)* where *n* is the number nodes. On a balanced tree all insert, remove, and search operations take only **O(log n)** time. That means fast. ;-) ## Introducing the AVL tree An AVL tree fixes any imbalances by "rotating" the tree to the left or right. A node in an AVL tree is considered balanced if its subtrees differ in "height" by at most 1. The tree itself is balanced if all its nodes are balanced. The *height* of a node is how many steps it takes to get to that node's lowest leaf. For example, in the following tree it takes three steps to go from A to E, so the height of A is 3. The height of B is 2, the height of C is 1, and the height of the others is 0 because they are leaf nodes. ![Node height](Images/Height.png) As mentioned, in an AVL tree a node is balanced if its left and right subtree have the same height. It doesn't have to be the exact same height, but the difference may not be greater than 1. These are all examples of balanced trees: ![Balanced trees](Images/BalanceOK.png) But the following are trees that are unbalanced, because the height of the left subtree is too large compared to the right subtree: ![Unbalanced trees](Images/BalanceNotOK.png) The difference between the heights of the left and right subtrees is called the *balance factor*. It is calculated as follows: balance factor = abs(height(left subtree) - height(right subtree)) If after an insertion or deletion the balance factor becomes greater than 1, then we need to re-balance this part of the AVL tree. And that is done with rotations. ## Rotations Each tree node keeps track of its current balance factor in a variable. After inserting a new node, we need to update the balance factor of its parent node. If that balance factor becomes greater than 1, we "rotate" part of that tree to restore the balance. ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: * *Root* - the parent node of the subtrees that will be rotated; * *Pivot* - the node that will become parent (basically will be on the *Root*'s position) after rotation; * *RotationSubtree* - subtree of the *Pivot* upon the side of rotation * *OppositeSubtree* - subtree of the *Pivot* opposite the side of rotation Let take an example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: ![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) The steps of rotation could be described by following: 1. Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; 2. Assign the *Root* as a new *RotationSubtree* for the *Pivot*; 3. Check the final result In pseudocode the algorithm above could be written as follows: ``` Root.OS = Pivot.RS Pivot.RS = Root Root = Pivot ``` This is a constant time operation - __O(1)__ Insertion never needs more than 2 rotations. Removal might require up to __log(n)__ rotations. ## The code Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary search tree](../Binary%20Search%20Tree/) stuff. You'll find this in any implementation of a binary search tree. For example, searching the tree is exactly the same. The only things that an AVL tree does slightly differently are inserting and deleting the nodes. > **Note:** If you're a bit fuzzy on the regular operations of a binary search tree, I suggest you [catch up on those first](../Binary%20Search%20Tree/). It will make the rest of the AVL tree easier to understand. The interesting bits are in the `balance()` method which is called after inserting or deleting a node. ## See also [AVL tree on Wikipedia](https://en.wikipedia.org/wiki/AVL_tree) AVL tree was the first self-balancing binary tree. These days, the [red-black tree](../Red-Black%20Tree/) seems to be more popular. *Written for Swift Algorithm Club by [Mike Taghavi](https://github.com/mitghi) and [Matthijs Hollemans](https://github.com/hollance)* ================================================ FILE: AVL Tree/Tests/AVLTreeTests.swift ================================================ // // AVLTreeTestsTests.swift // AVLTreeTestsTests // // Created by Barbara Rodeker on 2/19/16. // Copyright © 2016 Swift Algorithm Club. All rights reserved. // import XCTest class AVLTreeTests: XCTestCase { var tree: AVLTree? func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } override func setUp() { super.setUp() tree = AVLTree() } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testAVLTreeBalancedAutoPopulate() { self.tree?.autopopulateWithNodes(10) do { try self.tree?.inOrderCheckBalanced(self.tree?.root) } catch _ { XCTFail("Tree is not balanced after autopopulate") } } func testAVLTreeBalancedInsert() { self.tree?.autopopulateWithNodes(5) for i in 6...10 { self.tree?.insert(key: i) do { try self.tree?.inOrderCheckBalanced(self.tree?.root) } catch _ { XCTFail("Tree is not balanced after inserting " + String(i)) } } } func testAVLTreeBalancedDelete() { self.tree?.autopopulateWithNodes(5) for i in 1...6 { self.tree?.delete(key: i) do { try self.tree?.inOrderCheckBalanced(self.tree?.root) } catch _ { XCTFail("Tree is not balanced after deleting " + String(i)) } } } func testEmptyInitialization() { let tree = AVLTree() XCTAssertEqual(tree.size, 0) XCTAssertNil(tree.root) } func testSingleInsertionPerformance() { self.measure { self.tree?.insert(key: 5, payload: "E") } } func testMultipleInsertionsPerformance() { self.measure { self.tree?.autopopulateWithNodes(50) } } func testSearchExistentOnSmallTreePerformance() { self.measure { print(self.tree?.search(input: 2)) } } func testSearchExistentElementOnLargeTreePerformance() { self.measure { self.tree?.autopopulateWithNodes(500) print(self.tree?.search(input: 400)) } } func testMinimumOnPopulatedTree() { self.tree?.autopopulateWithNodes(500) let min = self.tree?.root?.minimum() XCTAssertNotNil(min, "Minimum function not working") } func testMinimumOnSingleTreeNode() { let treeNode = TreeNode(key: 1, payload: "A") let min = treeNode.minimum() XCTAssertNotNil(min, "Minimum on single node should be returned") XCTAssertEqual(min?.payload, treeNode.payload) } func testDeleteExistentKey() { self.tree?.delete(key: 1) XCTAssertNil(self.tree?.search(input: 1), "Key should not exist anymore") } func testDeleteNotExistentKey() { self.tree?.delete(key: 1056) XCTAssertNil(self.tree?.search(input: 1056), "Key should not exist") } func testInsertSize() { let tree = AVLTree() for i in 0...5 { tree.insert(key: i, payload: "") XCTAssertEqual(tree.size, i + 1, "Insert didn't update size correctly!") } } func testDelete() { let permutations = [ [5, 1, 4, 2, 3], [2, 3, 1, 5, 4], [4, 5, 3, 2, 1], [3, 2, 5, 4, 1], ] for p in permutations { let tree = AVLTree() tree.insert(key: 1, payload: "five") tree.insert(key: 2, payload: "four") tree.insert(key: 3, payload: "three") tree.insert(key: 4, payload: "two") tree.insert(key: 5, payload: "one") var count = tree.size for i in p { tree.delete(key: i) count -= 1 XCTAssertEqual(tree.size, count, "Delete didn't update size correctly!") } } } } extension AVLTree where Key : SignedInteger { func autopopulateWithNodes(_ count: Int) { var k: Key = 1 for _ in 0...count { self.insert(key: k) k = k + 1 } } } enum AVLTreeError: Error { case notBalanced } extension AVLTree where Key : SignedInteger { func height(_ node: Node?) -> Int { if let node = node { let lHeight = height(node.leftChild) let rHeight = height(node.rightChild) return max(lHeight, rHeight) + 1 } return 0 } func inOrderCheckBalanced(_ node: Node?) throws { if let node = node { guard abs(height(node.leftChild) - height(node.rightChild)) <= 1 else { throw AVLTreeError.notBalanced } try inOrderCheckBalanced(node.leftChild) try inOrderCheckBalanced(node.rightChild) } } } ================================================ FILE: AVL Tree/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: AVL Tree/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3C91C77A112003CECC7 /* TreeNodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3C71C77A112003CECC7 /* TreeNodeTests.swift */; }; 7B80C3CA1C77A112003CECC7 /* AVLTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3C81C77A112003CECC7 /* AVLTreeTests.swift */; }; 7B80C3CC1C77A120003CECC7 /* AVLTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CB1C77A120003CECC7 /* AVLTree.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3C71C77A112003CECC7 /* TreeNodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TreeNodeTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3C81C77A112003CECC7 /* AVLTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AVLTreeTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3CB1C77A120003CECC7 /* AVLTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AVLTree.swift; path = ../AVLTree.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3CB1C77A120003CECC7 /* AVLTree.swift */, 7B80C3C81C77A112003CECC7 /* AVLTreeTests.swift */, 7B80C3C71C77A112003CECC7 /* TreeNodeTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3CC1C77A120003CECC7 /* AVLTree.swift in Sources */, 7B80C3C91C77A112003CECC7 /* TreeNodeTests.swift in Sources */, 7B80C3CA1C77A112003CECC7 /* AVLTreeTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: AVL Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: AVL Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: AVL Tree/Tests/TreeNodeTests.swift ================================================ // // TreeNodeTest.swift // AVLTreeTests // // Created by Barbara Rodeker on 2/19/16. // Copyright © 2016 Swift Algorithm Club. All rights reserved. // import XCTest class TreeNodeTests: XCTestCase { var root: TreeNode? var left: TreeNode? var right: TreeNode? func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } override func setUp() { super.setUp() left = TreeNode(key: "Name", payload: "Left") right = TreeNode(key: "Name", payload: "Right") root = TreeNode(key: "Name", payload: "Root", leftChild: left, rightChild: right, parent: nil, height: 0) } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testSingleNodeCreationNOPayload() { let treeNode = TreeNode(key: "Building") XCTAssertNil(treeNode.payload, "Payload for this case should be nil") } func testSingleNodeCreationWithPayload() { XCTAssertNotNil(self.root!, "Payload for this case should not be nil") } func testIsRoot() { XCTAssertTrue(self.root!.isRoot) } func testNotIsLeaf() { XCTAssertFalse(self.root!.isLeaf, "root node is not leaf") } func testNotIsLeftChild() { XCTAssertFalse(self.root!.isLeftChild, "root node is not left child") } func testNotIsRightChild() { XCTAssertFalse(self.root!.isRightChild, "root node is not right child") } func testIsLeftChild() { XCTAssertTrue(self.left!.isLeftChild) } func testIsRightChild() { XCTAssertTrue(self.right!.isRightChild) } func isLeaf() { XCTAssertTrue(self.left!.isLeaf) } func testHasAnyChild() { XCTAssertTrue(self.root!.hasAnyChild) } func testNotHasAnyChild() { XCTAssertFalse(self.left!.hasAnyChild) } func testHasBothChildren() { XCTAssertTrue(self.root!.hasBothChildren) } func testNotHasBothChildren() { XCTAssertFalse(self.left!.hasBothChildren) } } ================================================ FILE: Algorithm Design.markdown ================================================ # Algorithm design techniques What to do when you're faced with a new problem and you need to find an algorithm for it. ### Is it similar to another problem? If you can frame your problem in terms of another, more general problem, then you might be able to use an existing algorithm. Why reinvent the wheel? One thing I like about [The Algorithm Design Manual](http://www.algorist.com) by Steven Skiena is that it includes a catalog of problems and solutions you can try. (See also his [algorithm repository](http://www3.cs.stonybrook.edu/~algorith/).) ### It's OK to start with brute force Naive, brute force solutions are often too slow for practical use but they're a good starting point. By writing the brute force solution, you learn to understand what the problem is really all about. Once you have a brute force implementation you can use that to verify that any improvements you come up with are correct. And if you only work with small datasets, then a brute force approach may actually be good enough on its own. Don't fall into the trap of premature optimization! ### Divide and conquer >"When you change the way you look at things, the things you look at change."
>Max Planck, Quantum theorist and Nobel Prize Winner Divide and conquer is a way of dealing with a large problem by breaking it down into bits and pieces and working your way up towards the solution. Instead of seeing the whole problem as a single, huge and complex task you divide the problem in relatively smaller problems that are easier to understand and deal with. You solve smaller problems and aggregate the solution until you are left with the solution only. At each step the problem at hand shrinks and the solution gets mature until you have the final correct solution. Solving the smaller task and applying the same solution repetitively ( or often times recursively) to other chunks give you the result in less time. ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP/APSP.h ================================================ // // APSP.h // APSP // // Created by Andrew McKnight on 5/6/16. // #import //! Project version number for APSP. FOUNDATION_EXPORT double APSPVersionNumber; //! Project version string for APSP. FOUNDATION_EXPORT const unsigned char APSPVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP/APSP.swift ================================================ // // Base.swift // APSP // // Created by Andrew McKnight on 5/6/16. // import Foundation import Graph /** `APSPAlgorithm` is a protocol for encapsulating an All-Pairs Shortest Paths algorithm. It provides a single function `apply` that accepts a subclass of `AbstractGraph` and returns an object conforming to `APSPResult`. */ public protocol APSPAlgorithm { associatedtype Q: Hashable associatedtype P: APSPResult static func apply(_ graph: AbstractGraph) -> P } /** `APSPResult` is a protocol defining functions `distance` and `path`, allowing for opaque queries into the actual data structures that represent the APSP solution according to the algorithm used. */ public protocol APSPResult { associatedtype T: Hashable func distance(fromVertex from: Vertex, toVertex to: Vertex) -> Double? func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: AbstractGraph) -> [T]? } ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift ================================================ // // FloydWarshall.swift // APSP // // Created by Andrew McKnight on 5/5/16. // import Foundation import Graph private typealias Distances = [[Double]] private typealias Predecessors = [[Int?]] private typealias StepResult = (distances: Distances, predecessors: Predecessors) /** Encapsulation of the Floyd-Warshall All-Pairs Shortest Paths algorithm, conforming to the `APSPAlgorithm` protocol. - note: In all complexity bounds, `V` is the number of vertices in the graph, and `E` is the number of edges. */ public struct FloydWarshall: APSPAlgorithm where T: Hashable { public typealias Q = T public typealias P = FloydWarshallResult /** Floyd-Warshall algorithm for computing all-pairs shortest paths in a weighted directed graph. - precondition: `graph` must have no negative weight cycles - complexity: `Θ(V^3)` time, `Θ(V^2)` space - returns a `FloydWarshallResult` struct which can be queried for shortest paths and their total weights */ public static func apply(_ graph: AbstractGraph) -> FloydWarshallResult { var previousDistance = constructInitialDistanceMatrix(graph) var previousPredecessor = constructInitialPredecessorMatrix(previousDistance) for intermediateIdx in 0 ..< graph.vertices.count { let nextResult = nextStep(intermediateIdx, previousDistances: previousDistance, previousPredecessors: previousPredecessor, graph: graph) previousDistance = nextResult.distances previousPredecessor = nextResult.predecessors // // uncomment to see each new weight matrix // print(" D(\(k)):\n") // printMatrix(nextResult.distances) // // // uncomment to see each new predecessor matrix // print(" ∏(\(k)):\n") // printIntMatrix(nextResult.predecessors) } return FloydWarshallResult(weights: previousDistance, predecessors: previousPredecessor) } /** For each iteration of `intermediateIdx`, perform the comparison for the dynamic algorith, checking for each pair of start/end vertices, whether a path taken through another vertex produces a shorter path. - complexity: `Θ(V^2)` time/space - returns: a tuple containing the next distance matrix with weights of currently known shortest paths and the corresponding predecessor matrix */ static fileprivate func nextStep(_ intermediateIdx: Int, previousDistances: Distances, previousPredecessors: Predecessors, graph: AbstractGraph) -> StepResult { let vertexCount = graph.vertices.count var nextDistances = Array(repeating: Array(repeating: Double.infinity, count: vertexCount), count: vertexCount) var nextPredecessors = Array(repeating: Array(repeating: nil, count: vertexCount), count: vertexCount) for fromIdx in 0 ..< vertexCount { for toIndex in 0 ..< vertexCount { // printMatrix(previousDistances, i: fromIdx, j: toIdx, k: intermediateIdx) // uncomment to see each comparison being made let originalPathWeight = previousDistances[fromIdx][toIndex] let newPathWeightBefore = previousDistances[fromIdx][intermediateIdx] let newPathWeightAfter = previousDistances[intermediateIdx][toIndex] let minimum = min(originalPathWeight, newPathWeightBefore + newPathWeightAfter) nextDistances[fromIdx][toIndex] = minimum var predecessor: Int? if originalPathWeight <= newPathWeightBefore + newPathWeightAfter { predecessor = previousPredecessors[fromIdx][toIndex] } else { predecessor = previousPredecessors[intermediateIdx][toIndex] } nextPredecessors[fromIdx][toIndex] = predecessor } } return (nextDistances, nextPredecessors) } /** We need to map the graph's weight domain onto the one required by the algorithm: the graph stores either a weight as a `Double` or `nil` if no edge exists between two vertices, but the algorithm needs a lack of an edge represented as ∞ for the `min` comparison to work correctly. - complexity: `Θ(V^2)` time/space - returns: weighted adjacency matrix in form ready for processing with Floyd-Warshall */ static fileprivate func constructInitialDistanceMatrix(_ graph: AbstractGraph) -> Distances { let vertices = graph.vertices let vertexCount = graph.vertices.count var distances = Array(repeating: Array(repeating: Double.infinity, count: vertexCount), count: vertexCount) for row in vertices { for col in vertices { let rowIdx = row.index let colIdx = col.index if rowIdx == colIdx { distances[rowIdx][colIdx] = 0.0 } else if let w = graph.weightFrom(row, to: col) { distances[rowIdx][colIdx] = w } } } return distances } /** Make the initial predecessor index matrix. Initially each value is equal to it's row index, it's "from" index when querying into it. - complexity: `Θ(V^2)` time/space */ static fileprivate func constructInitialPredecessorMatrix(_ distances: Distances) -> Predecessors { let vertexCount = distances.count var predecessors = Array(repeating: Array(repeating: nil, count: vertexCount), count: vertexCount) for fromIdx in 0 ..< vertexCount { for toIdx in 0 ..< vertexCount { if fromIdx != toIdx && distances[fromIdx][toIdx] < Double.infinity { predecessors[fromIdx][toIdx] = fromIdx } } } return predecessors } } /** `FloydWarshallResult` encapsulates the result of the computation, namely the minimized distance adjacency matrix, and the matrix of predecessor indices. It conforms to the `APSPResult` procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. */ public struct FloydWarshallResult: APSPResult where T: Hashable { fileprivate var weights: Distances fileprivate var predecessors: Predecessors /** - returns: the total weight of the path from a starting vertex to a destination. This value is the minimal connected weight between the two vertices, or `nil` if no path exists - complexity: `Θ(1)` time/space */ public func distance(fromVertex from: Vertex, toVertex to: Vertex) -> Double? { return weights[from.index][to.index] } /** - returns: the reconstructed path from a starting vertex to a destination, as an array containing the data property of each vertex, or `nil` if no path exists - complexity: `Θ(V)` time, `Θ(V^2)` space */ public func path(fromVertex from: Vertex, toVertex to: Vertex, inGraph graph: AbstractGraph) -> [T]? { if let path = recursePathFrom(fromVertex: from, toVertex: to, path: [ to ], inGraph: graph) { let pathValues = path.map { vertex in vertex.data } return pathValues } return nil } /** The recursive component to rebuilding the shortest path between two vertices using the predecessor matrix. - returns: the list of predecessors discovered so far */ fileprivate func recursePathFrom(fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], inGraph graph: AbstractGraph) -> [Vertex]? { if from.index == to.index { return [ from, to ] } if let predecessor = predecessors[from.index][to.index] { let predecessorVertex = graph.vertices[predecessor] if predecessor == from.index { let newPath = [ from, to ] return newPath } else { let buildPath = recursePathFrom(fromVertex: from, toVertex: predecessorVertex, path: path, inGraph: graph) let newPath = buildPath! + [ to ] return newPath } } return nil } } ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP/Helpers.swift ================================================ // // Helpers.swift // APSP // // Created by Andrew McKnight on 5/6/16. // import Foundation /** Print a matrix, optionally specifying only the cells to display with the triplet (i, j, k) -> matrix[i][j], matrix[i][k], matrix[k][j] */ func printMatrix(_ matrix: [[Double]], i: Int = -1, j: Int = -1, k: Int = -1) { if i >= 0 { print(" k: \(k); i: \(i); j: \(j)\n") } var grid = [String]() let n = matrix.count for x in 0.. CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Graph import APSP var graph = AdjacencyListGraph() let v1 = graph.createVertex("Montreal") let v2 = graph.createVertex("New York") let v3 = graph.createVertex("Boston") let v4 = graph.createVertex("Portland") let v5 = graph.createVertex("Portsmouth") graph.addDirectedEdge(v1, to: v2, withWeight: 3) graph.addDirectedEdge(v1, to: v5, withWeight: -4) graph.addDirectedEdge(v1, to: v3, withWeight: 8) graph.addDirectedEdge(v2, to: v4, withWeight: 1) graph.addDirectedEdge(v2, to: v5, withWeight: 7) graph.addDirectedEdge(v3, to: v2, withWeight: 4) graph.addDirectedEdge(v4, to: v1, withWeight: 2) graph.addDirectedEdge(v4, to: v3, withWeight: -5) graph.addDirectedEdge(v5, to: v4, withWeight: 6) let result = FloydWarshall.apply(graph) let path = result.path(fromVertex: v1, toVertex: v4, inGraph: graph) ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.playground/contents.xcplayground ================================================ ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.playground/timeline.xctimeline ================================================ ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 491AA3821CE8C5F700A2E2C5 /* Graph.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 491AA37F1CE8C5C900A2E2C5 /* Graph.framework */; }; 493D8DE31CDD2A1C0089795A /* APSPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DE21CDD2A1C0089795A /* APSPTests.swift */; }; 493D8DF41CDD5B960089795A /* APSP.h in Headers */ = {isa = PBXBuildFile; fileRef = 493D8DF31CDD5B960089795A /* APSP.h */; settings = {ATTRIBUTES = (Public, ); }; }; 493D8DF91CDD5B9B0089795A /* FloydWarshall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DD81CDC38C60089795A /* FloydWarshall.swift */; }; 493D8DFA1CDD5B9E0089795A /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 493D8DDA1CDD29C80089795A /* Helpers.swift */; }; 49BFA27A1CDD93F400522D66 /* APSP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2791CDD93F400522D66 /* APSP.swift */; }; 49BFA2801CDE742900522D66 /* APSP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 493D8DF11CDD5B960089795A /* APSP.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 491AA37E1CE8C5C900A2E2C5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */; proxyType = 2; remoteGlobalIDString = 49BFA2FD1CDF886B00522D66; remoteInfo = Graph; }; 491AA3801CE8C5C900A2E2C5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */; proxyType = 2; remoteGlobalIDString = 49BFA3071CDF886B00522D66; remoteInfo = GraphTests; }; 491AA3831CE8C5F900A2E2C5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */; proxyType = 1; remoteGlobalIDString = 49BFA2FC1CDF886B00522D66; remoteInfo = Graph; }; 49BFA27E1CDE742700522D66 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 493D8D7E1CDC2DAE0089795A /* Project object */; proxyType = 1; remoteGlobalIDString = 493D8DF01CDD5B960089795A; remoteInfo = APSP; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Graph.xcodeproj; path = ../../Graph/Graph.xcodeproj; sourceTree = ""; }; 493D8DD81CDC38C60089795A /* FloydWarshall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloydWarshall.swift; sourceTree = ""; }; 493D8DDA1CDD29C80089795A /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; 493D8DE01CDD2A1C0089795A /* APSPTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = APSPTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 493D8DE21CDD2A1C0089795A /* APSPTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APSPTests.swift; sourceTree = ""; }; 493D8DE41CDD2A1C0089795A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 493D8DF11CDD5B960089795A /* APSP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = APSP.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 493D8DF31CDD5B960089795A /* APSP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APSP.h; sourceTree = ""; }; 493D8DF51CDD5B960089795A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49BFA2791CDD93F400522D66 /* APSP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APSP.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 493D8DDD1CDD2A1C0089795A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 49BFA2801CDE742900522D66 /* APSP.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 493D8DED1CDD5B960089795A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 491AA3821CE8C5F700A2E2C5 /* Graph.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 491AA37A1CE8C5C900A2E2C5 /* Products */ = { isa = PBXGroup; children = ( 491AA37F1CE8C5C900A2E2C5 /* Graph.framework */, 491AA3811CE8C5C900A2E2C5 /* GraphTests.xctest */, ); name = Products; sourceTree = ""; }; 493D8D7D1CDC2DAE0089795A = { isa = PBXGroup; children = ( 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */, 493D8D881CDC2DAE0089795A /* APSP */, 493D8DE11CDD2A1C0089795A /* APSPTests */, 493D8D871CDC2DAE0089795A /* Products */, ); sourceTree = ""; }; 493D8D871CDC2DAE0089795A /* Products */ = { isa = PBXGroup; children = ( 493D8DE01CDD2A1C0089795A /* APSPTests.xctest */, 493D8DF11CDD5B960089795A /* APSP.framework */, ); name = Products; sourceTree = ""; }; 493D8D881CDC2DAE0089795A /* APSP */ = { isa = PBXGroup; children = ( 493D8DF31CDD5B960089795A /* APSP.h */, 49BFA2791CDD93F400522D66 /* APSP.swift */, 493D8DD81CDC38C60089795A /* FloydWarshall.swift */, 493D8DDA1CDD29C80089795A /* Helpers.swift */, 493D8DF51CDD5B960089795A /* Info.plist */, ); path = APSP; sourceTree = ""; }; 493D8DE11CDD2A1C0089795A /* APSPTests */ = { isa = PBXGroup; children = ( 493D8DE21CDD2A1C0089795A /* APSPTests.swift */, 493D8DE41CDD2A1C0089795A /* Info.plist */, ); path = APSPTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 493D8DEE1CDD5B960089795A /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 493D8DF41CDD5B960089795A /* APSP.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 493D8DDF1CDD2A1C0089795A /* APSPTests */ = { isa = PBXNativeTarget; buildConfigurationList = 493D8DE51CDD2A1C0089795A /* Build configuration list for PBXNativeTarget "APSPTests" */; buildPhases = ( 493D8DDC1CDD2A1C0089795A /* Sources */, 493D8DDD1CDD2A1C0089795A /* Frameworks */, 493D8DDE1CDD2A1C0089795A /* Resources */, ); buildRules = ( ); dependencies = ( 49BFA27F1CDE742700522D66 /* PBXTargetDependency */, ); name = APSPTests; productName = APSPTests; productReference = 493D8DE01CDD2A1C0089795A /* APSPTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 493D8DF01CDD5B960089795A /* APSP */ = { isa = PBXNativeTarget; buildConfigurationList = 493D8DF61CDD5B960089795A /* Build configuration list for PBXNativeTarget "APSP" */; buildPhases = ( 493D8DEC1CDD5B960089795A /* Sources */, 493D8DED1CDD5B960089795A /* Frameworks */, 493D8DEE1CDD5B960089795A /* Headers */, 493D8DEF1CDD5B960089795A /* Resources */, ); buildRules = ( ); dependencies = ( 491AA3841CE8C5F900A2E2C5 /* PBXTargetDependency */, ); name = APSP; productName = APSP; productReference = 493D8DF11CDD5B960089795A /* APSP.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 493D8D7E1CDC2DAE0089795A /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 1010; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 493D8DDF1CDD2A1C0089795A = { CreatedOnToolsVersion = 7.3; LastSwiftMigration = 1010; }; 493D8DF01CDD5B960089795A = { CreatedOnToolsVersion = 7.3; LastSwiftMigration = 1010; }; }; }; buildConfigurationList = 493D8D811CDC2DAE0089795A /* Build configuration list for PBXProject "APSP" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 493D8D7D1CDC2DAE0089795A; productRefGroup = 493D8D871CDC2DAE0089795A /* Products */; projectDirPath = ""; projectReferences = ( { ProductGroup = 491AA37A1CE8C5C900A2E2C5 /* Products */; ProjectRef = 491AA3791CE8C5C900A2E2C5 /* Graph.xcodeproj */; }, ); projectRoot = ""; targets = ( 493D8DDF1CDD2A1C0089795A /* APSPTests */, 493D8DF01CDD5B960089795A /* APSP */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ 491AA37F1CE8C5C900A2E2C5 /* Graph.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = Graph.framework; remoteRef = 491AA37E1CE8C5C900A2E2C5 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 491AA3811CE8C5C900A2E2C5 /* GraphTests.xctest */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; path = GraphTests.xctest; remoteRef = 491AA3801CE8C5C900A2E2C5 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ 493D8DDE1CDD2A1C0089795A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 493D8DEF1CDD5B960089795A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 493D8DDC1CDD2A1C0089795A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 493D8DE31CDD2A1C0089795A /* APSPTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 493D8DEC1CDD5B960089795A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 49BFA27A1CDD93F400522D66 /* APSP.swift in Sources */, 493D8DF91CDD5B9B0089795A /* FloydWarshall.swift in Sources */, 493D8DFA1CDD5B9E0089795A /* Helpers.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 491AA3841CE8C5F900A2E2C5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Graph; targetProxy = 491AA3831CE8C5F900A2E2C5 /* PBXContainerItemProxy */; }; 49BFA27F1CDE742700522D66 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 493D8DF01CDD5B960089795A /* APSP */; targetProxy = 49BFA27E1CDE742700522D66 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 493D8D8B1CDC2DAE0089795A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 493D8D8C1CDC2DAE0089795A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 493D8DE61CDD2A1C0089795A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = APSPTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Debug; }; 493D8DE71CDD2A1C0089795A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = APSPTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; 493D8DF71CDD5B960089795A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = APSP/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 4.2; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 493D8DF81CDD5B960089795A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = APSP/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 4.2; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 493D8D811CDC2DAE0089795A /* Build configuration list for PBXProject "APSP" */ = { isa = XCConfigurationList; buildConfigurations = ( 493D8D8B1CDC2DAE0089795A /* Debug */, 493D8D8C1CDC2DAE0089795A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 493D8DE51CDD2A1C0089795A /* Build configuration list for PBXNativeTarget "APSPTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 493D8DE61CDD2A1C0089795A /* Debug */, 493D8DE71CDD2A1C0089795A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 493D8DF61CDD5B960089795A /* Build configuration list for PBXNativeTarget "APSP" */ = { isa = XCConfigurationList; buildConfigurations = ( 493D8DF71CDD5B960089795A /* Debug */, 493D8DF81CDD5B960089795A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 493D8D7E1CDC2DAE0089795A /* Project object */; } ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme ================================================ ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSPTests.xcscheme ================================================ ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: All-Pairs Shortest Paths/APSP/APSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: All-Pairs Shortest Paths/APSP/APSPTests/APSPTests.swift ================================================ // // APSPTests.swift // APSPTests // // Created by Andrew McKnight on 5/6/16. // import APSP import Graph import XCTest struct TestCase where T: Hashable { var from: Vertex var to: Vertex var expectedPath: [T] var expectedDistance: Double } class APSPTests: XCTestCase { /** See Figure 25.1 of “Introduction to Algorithms” by Cormen et al, 3rd ed., pg 690 */ func testExampleFromBook() { let graph = AdjacencyMatrixGraph() let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) let v4 = graph.createVertex(4) let v5 = graph.createVertex(5) graph.addDirectedEdge(v1, to: v2, withWeight: 3) graph.addDirectedEdge(v1, to: v5, withWeight: -4) graph.addDirectedEdge(v1, to: v3, withWeight: 8) graph.addDirectedEdge(v2, to: v4, withWeight: 1) graph.addDirectedEdge(v2, to: v5, withWeight: 7) graph.addDirectedEdge(v3, to: v2, withWeight: 4) graph.addDirectedEdge(v4, to: v1, withWeight: 2) graph.addDirectedEdge(v4, to: v3, withWeight: -5) graph.addDirectedEdge(v5, to: v4, withWeight: 6) let result = FloydWarshall.apply(graph) let cases = [ TestCase(from: v1, to: v4, expectedPath: [1, 5, 4], expectedDistance: 2), TestCase(from: v1, to: v5, expectedPath: [1, 5], expectedDistance: -4), TestCase(from: v2, to: v1, expectedPath: [2, 4, 1], expectedDistance: 3), TestCase(from: v2, to: v3, expectedPath: [2, 4, 3], expectedDistance: -4), TestCase(from: v2, to: v4, expectedPath: [2, 4], expectedDistance: 1), TestCase(from: v2, to: v5, expectedPath: [2, 4, 1, 5], expectedDistance: -1), TestCase(from: v3, to: v1, expectedPath: [3, 2, 4, 1], expectedDistance: 7), TestCase(from: v3, to: v2, expectedPath: [3, 2], expectedDistance: 4), TestCase(from: v3, to: v4, expectedPath: [3, 2, 4], expectedDistance: 5), TestCase(from: v3, to: v5, expectedPath: [3, 2, 4, 1, 5], expectedDistance: 3), TestCase(from: v4, to: v1, expectedPath: [4, 1], expectedDistance: 2), TestCase(from: v4, to: v2, expectedPath: [4, 3, 2], expectedDistance: -1), TestCase(from: v4, to: v3, expectedPath: [4, 3], expectedDistance: -5), TestCase(from: v4, to: v5, expectedPath: [4, 1, 5], expectedDistance: -2), TestCase(from: v5, to: v1, expectedPath: [5, 4, 1], expectedDistance: 8), TestCase(from: v5, to: v2, expectedPath: [5, 4, 3, 2], expectedDistance: 5), TestCase(from: v5, to: v3, expectedPath: [5, 4, 3], expectedDistance: 1), TestCase(from: v5, to: v4, expectedPath: [5, 4], expectedDistance: 6), ] for testCase: TestCase in cases { if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), let computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { XCTAssert(computedDistance == testCase.expectedDistance, "expected distance \(testCase.expectedDistance) but got \(computedDistance)") XCTAssert(computedPath == testCase.expectedPath, "expected path \(testCase.expectedPath) but got \(computedPath)") } } } func testExampleFromReadme() { let graph = AdjacencyMatrixGraph() let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) let v4 = graph.createVertex(4) graph.addDirectedEdge(v1, to: v2, withWeight: 4) graph.addDirectedEdge(v1, to: v3, withWeight: 1) graph.addDirectedEdge(v1, to: v4, withWeight: 3) graph.addDirectedEdge(v2, to: v3, withWeight: 8) graph.addDirectedEdge(v2, to: v4, withWeight: -2) graph.addDirectedEdge(v3, to: v4, withWeight: -5) let result = FloydWarshall.apply(graph) let cases = [ TestCase(from: v1, to: v2, expectedPath: [1, 2], expectedDistance: 4), TestCase(from: v1, to: v3, expectedPath: [1, 3], expectedDistance: 1), TestCase(from: v1, to: v4, expectedPath: [1, 3, 4], expectedDistance: -4), TestCase(from: v2, to: v3, expectedPath: [2, 3], expectedDistance: 8), TestCase(from: v2, to: v4, expectedPath: [2, 4], expectedDistance: -2), TestCase(from: v3, to: v4, expectedPath: [3, 4], expectedDistance: -5), ] for testCase: TestCase in cases { if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), let computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { XCTAssert(computedDistance == testCase.expectedDistance, "expected distance \(testCase.expectedDistance) but got \(computedDistance)") XCTAssert(computedPath == testCase.expectedPath, "expected path \(testCase.expectedPath) but got \(computedPath)") } } } } ================================================ FILE: All-Pairs Shortest Paths/APSP/APSPTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: All-Pairs Shortest Paths/README.markdown ================================================ # All-Pairs Shortest Paths The All-Pairs shortest path problem simultaneously computes the shortest path from each node in the graph to each other node, provided a path exists for each pair. In the naive approach, we could simply compute a single-source shortest path from each node to each other node. The number of shortest paths computed is then bound by `O(V^2)`, where `V` is the number of vertices in the graph. Because SSSP is also bounded by `O(V^2)`, the total running time for the naive approach would be `O(V^4)`. However, by applying a dynamic approach on the adjacency matrix of the graph, a running time of `O(V^3)` is achievable, using the `Floyd-Warshall` algorithm. Floyd-Warshall iterates through an adjacency matrix, and for each pair of start(`i`) and end(`j`) vertices it considers if the current distance between them is greater than a path taken through another vertex(`k`) in the graph (if paths `i` ~> `k` and `k` ~> `j` exist). It moves through an adjacency matrix for every vertex `k` applying its comparison for each pair (`i`, `j`), so for each `k` a new adjacency matrix `D(k)` is derived, where each value `d(k)[i][j]` is defined as: where `w[i][j]` is the weight of the edge connecting vertex `i` to vertex `j` in the graph's original adjacency matrix. When the algorithm memoizes each refined adjacency and predecessor matrix, its space complexity is `O(V^3)`, which can be optimised to `O(V^2)` by only memoizing the latest refinements. Reconstructing paths is a recursive procedure which requires `O(V)` time and `O(V^2)` space. # Example For the following weighted directed graph the adjacency matrix representation `w` is ### Calculating shortest paths' weights At the beginning of the algorithm, `D(0)` is the same as `w`, with the following exceptions to accommodate the comparison function: 1. vertices with no path connecting them have the `ø` replaced with `∞` 2. the diagonal has all `0`s Here are all the adjacency matrices derived when perform Floyd-Warshall on the above graph: with the last being the result, which tells for each pair of starting and ending vertices, the total weight of the shortest path connecting them. During the step where `k = 2`, the comparison that winds up changing the top right value from `2` to `-4` goes like this: k = 2, i = 0, j = 3 d(k-1)[i][j] => d(1)[0][3] = 2 d(k-1)[i][k] => d(1)[0][2] = 1 d(k-1)[j][k] => d(1)[2][3] = -5 therefore `min(2, 2 + -5) => min(2, -4)` produces a new weight of `-4` for the element at `d(2)[0][3]`, meaning that the shortest known path 1 ~> 4 before this step was from 1 -> 2 -> 4 with a total weight of -2, and afterwards we discovered a shorter path from 1 -> 3 -> 4 with a total weight of -4. ### Reconstructing shortest paths This algorithm finds only the lengths of the shortest paths between all pairs of nodes; a separate bookkeeping structure must be maintained to track predecessors' indices and reconstruct the shortest paths afterwards. The predecessor matrices at each step for the above graph follow: # Project Structure The provided xcworkspace allows working in the playground, which imports the APSP framework target from the xcodeproj. Build the framework target and rerun the playground to get started. There is also a test target in the xcodeproj. In the framework: - protocols for All-Pairs Shortest Paths algorithms and results structures - an implementation of the Floyd-Warshall algorithm # TODO - Implement naive `O(V^4)` method for comparison - Implement Johnson's algorithm for sparse graphs - Implement other cool optimized versions # References Chapter 25 of Introduction to Algorithms, Third Edition by Cormen, Leiserson, Rivest and Stein [https://mitpress.mit.edu/books/introduction-algorithms](https://mitpress.mit.edu/books/introduction-algorithms) *Written for Swift Algorithm Club by [Andrew McKnight](https://github.com/armcknight)* ================================================ FILE: Array2D/Array2D.playground/Contents.swift ================================================ /* Two-dimensional array with a fixed number of rows and columns. This is mostly handy for games that are played on a grid, such as chess. Performance is always O(1). */ public struct Array2D { public let columns: Int public let rows: Int fileprivate var array: [T] public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { get { precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") return array[row*columns + column] } set { precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") array[row*columns + column] = newValue } } } // initialization var matrix = Array2D(columns: 3, rows: 5, initialValue: 0) // makes an array of rows * columns elements all filled with zero print(matrix.array) // setting numbers using subscript [x, y] matrix[0, 0] = 1 matrix[1, 0] = 2 matrix[0, 1] = 3 matrix[1, 1] = 4 matrix[0, 2] = 5 matrix[1, 2] = 6 matrix[0, 3] = 7 matrix[1, 3] = 8 matrix[2, 3] = 9 // now the numbers are set in the array print(matrix.array) // print out the 2D array with a reference around the grid for i in 0.. ================================================ FILE: Array2D/Array2D.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Array2D/Array2D.swift ================================================ /* Two-dimensional array with a fixed number of rows and columns. This is mostly handy for games that are played on a grid, such as chess. Performance is always O(1). */ public struct Array2D { public let columns: Int public let rows: Int fileprivate var array: [T] public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { get { precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") return array[row*columns + column] } set { precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") array[row*columns + column] = newValue } } } ================================================ FILE: Array2D/README.markdown ================================================ # Array2D In C and Objective-C, you can write the following line, int cookies[9][7]; to make a 9x7 grid of cookies. This creates a two-dimensional array of 63 elements. To find the cookie at column 3 and row 6, you can write: myCookie = cookies[3][6]; This statement is not acceptable in Swift. To create a multi-dimensional array in Swift, you can write: ```swift var cookies = [[Int]]() for _ in 1...9 { var row = [Int]() for _ in 1...7 { row.append(0) } cookies.append(row) } ``` Then, to find a cookie, you can write: ```swift let myCookie = cookies[3][6] ``` You can also create the array in a single line of code: ```swift var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9) ``` This looks complicated, but you can simplify it with a helper function: ```swift func dim(_ count: Int, _ value: T) -> [T] { return [T](repeating: value, count: count) } ``` Then, you can create the array: ```swift var cookies = dim(9, dim(7, 0)) ``` Swift infers that the datatype of the array must be `Int` because you specified `0` as the default value of the array elements. To use a string instead, you can write: ```swift var cookies = dim(9, dim(7, "yum")) ``` The `dim()` function makes it easy to go into even more dimensions: ```swift var threeDimensions = dim(2, dim(3, dim(4, 0))) ``` The downside of using multi-dimensional arrays or multiple nested arrays in this way is to lose track of what dimension represents what. Instead, you can create your own type that acts like a 2-D array which is more convenient to use: ```swift public struct Array2D { public let columns: Int public let rows: Int fileprivate var array: [T] public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { get { precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") return array[row*columns + column] } set { precondition(column < columns, "Column \(column) Index is out of range. Array(columns: \(columns), rows:\(rows))") precondition(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") array[row*columns + column] = newValue } } } ``` `Array2D` is a generic type, so it can hold any kind of object, not just numbers. To create an instance of `Array2D`, you can write: ```swift var cookies = Array2D(columns: 9, rows: 7, initialValue: 0) ``` By using the `subscript` function, you can retrieve an object from the array: ```swift let myCookie = cookies[column, row] ``` Or, you can change it: ```swift cookies[column, row] = newCookie ``` Internally, `Array2D` uses a single one-dimensional array to store the data. The index of an object in that array is given by `(row x numberOfColumns) + column`, but as a user of `Array2D`, you only need to think in terms of "column" and "row", and the details will be done by `Array2D`. This is the advantage of wrapping primitive types into a wrapper class or struct. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Array2D/Tests/Array2DTests.swift ================================================ // // Array2DTest.swift // algorithmclub // // Created by Barbara Rodeker on 2/16/16. // Copyright © 2016 Swift Algorithm Club. All rights reserved. // import XCTest class Array2DTest: XCTestCase { override func setUp() { super.setUp() } override func tearDown() { super.tearDown() } func testIntegerArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: 0) XCTAssertEqual(array.columns, 3, "Column count setup failed") XCTAssertEqual(array.rows, 2, "Rows count setup failed") XCTAssertEqual(array[2, 1], 0, "Integer array: Initialization value is wrong") } func testStringArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: "empty") XCTAssertEqual(array.columns, 3, "Column count setup failed") XCTAssertEqual(array.rows, 2, "Rows count setup failed") XCTAssertEqual(array[2, 1], "empty", "String array: Initialization value is wrong") } func testCustomClassArrayWithPositiveRowsAndColumns() { let array = Array2D(columns: 3, rows: 2, initialValue: TestElement(identifier: "pepe")) XCTAssertEqual(array.columns, 3, "Column count setup failed") XCTAssertEqual(array.rows, 2, "Rows count setup failed") XCTAssertEqual(array[2, 1], TestElement(identifier: "pepe"), "Custom Class array: Initialization value is wrong") } func testPerformanceOnSmallArray() { self.measure { self.printArrayWith(columns: 2, rows: 2, inititalValue: 1) } } // func testPerformanceOnLargeArray() { // self.measureBlock { // self.printArrayWith(columns: 2000, rows: 2000, inititalValue: 1) // } // } fileprivate func printArrayWith(columns: Int, rows: Int, inititalValue: Int) { let array = Array2D(columns: columns, rows: rows, initialValue: 4) for r in 0.. Bool { return lhs.identifier == rhs.identifier } ================================================ FILE: Array2D/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Array2D/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B2BBC901C779DAC0067B71D /* Array2DTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2BBC8F1C779DAC0067B71D /* Array2DTests.swift */; }; 7B2BBC991C77A04F0067B71D /* Array2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2BBC981C77A04F0067B71D /* Array2D.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC8F1C779DAC0067B71D /* Array2DTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Array2DTests.swift; sourceTree = SOURCE_ROOT; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B2BBC981C77A04F0067B71D /* Array2D.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Array2D.swift; path = ../Array2D.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B2BBC981C77A04F0067B71D /* Array2D.swift */, 7B2BBC8F1C779DAC0067B71D /* Array2DTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B2BBC901C779DAC0067B71D /* Array2DTests.swift in Sources */, 7B2BBC991C77A04F0067B71D /* Array2D.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Array2D/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Array2D/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: B-Tree/BTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation // last checked with Xcode 10.0 let bTree = BTree(order: 1)! bTree.insert(1, for: 1) bTree.insert(2, for: 2) bTree.insert(3, for: 3) bTree.insert(4, for: 4) bTree.value(for: 3) bTree[3] bTree.remove(2) bTree.traverseKeysInOrder { key in print(key) } bTree.numberOfKeys bTree.order bTree.inorderArrayFromKeys ================================================ FILE: B-Tree/BTree.playground/Sources/BTree.swift ================================================ // The MIT License (MIT) // Copyright (c) 2016 Viktor Szilárd Simkó (aqviktor[at]gmail.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /* * B-Tree * * A B-Tree is a self-balancing search tree, in which nodes can have more than two children. */ // MARK: - BTreeNode class class BTreeNode { /** * The tree that owns the node. */ unowned var owner: BTree fileprivate var keys = [Key]() fileprivate var values = [Value]() var children: [BTreeNode]? var isLeaf: Bool { return children == nil } var numberOfKeys: Int { return keys.count } init(owner: BTree) { self.owner = owner } convenience init(owner: BTree, keys: [Key], values: [Value], children: [BTreeNode]? = nil) { self.init(owner: owner) self.keys += keys self.values += values self.children = children } } // MARK: BTreeNode extesnion: Searching extension BTreeNode { /** * Returns the value for a given `key`, returns nil if the `key` is not found. * * - Parameters: * - key: the key of the value to be returned */ func value(for key: Key) -> Value? { var index = keys.startIndex while (index + 1) < keys.endIndex && keys[index] < key { index = (index + 1) } if key == keys[index] { return values[index] } else if key < keys[index] { return children?[index].value(for: key) } else { return children?[(index + 1)].value(for: key) } } } // MARK: BTreeNode extension: Traversals extension BTreeNode { /** * Traverses the keys in order, executes `process` for every key. * * - Parameters: * - process: the closure to be executed for every key */ func traverseKeysInOrder(_ process: (Key) -> Void) { for i in 0.. owner.order * 2 { split(child: children![index], atIndex: index) } } } /** * Splits `child` at `index`. * The key-value pair at `index` gets moved up to the parent node, * or if there is not an parent node, then a new parent node is created. * * - Parameters: * - child: the child to be split * - index: the index of the key, which will be moved up to the parent */ private func split(child: BTreeNode, atIndex index: Int) { let middleIndex = child.numberOfKeys / 2 keys.insert(child.keys[middleIndex], at: index) values.insert(child.values[middleIndex], at: index) child.keys.remove(at: middleIndex) child.values.remove(at: middleIndex) let rightSibling = BTreeNode( owner: owner, keys: Array(child.keys[child.keys.indices.suffix(from: middleIndex)]), values: Array(child.values[child.values.indices.suffix(from: middleIndex)]) ) child.keys.removeSubrange(child.keys.indices.suffix(from: middleIndex)) child.values.removeSubrange(child.values.indices.suffix(from: middleIndex)) children!.insert(rightSibling, at: (index + 1)) if child.children != nil { rightSibling.children = Array( child.children![child.children!.indices.suffix(from: (middleIndex + 1))] ) child.children!.removeSubrange(child.children!.indices.suffix(from: (middleIndex + 1))) } } } // MARK: BTreeNode extension: Removal /** * An enumeration to indicate a node's position according to another node. * * Possible values: * - left * - right */ private enum BTreeNodePosition { case left case right } extension BTreeNode { private var inorderPredecessor: BTreeNode { if isLeaf { return self } else { return children!.last!.inorderPredecessor } } /** * Removes `key` and the value associated with it from the node * or one of its descendants. * * - Parameters: * - key: the key to be removed */ func remove(_ key: Key) { var index = keys.startIndex while (index + 1) < keys.endIndex && keys[index] < key { index = (index + 1) } if keys[index] == key { if isLeaf { keys.remove(at: index) values.remove(at: index) owner.numberOfKeys -= 1 } else { let predecessor = children![index].inorderPredecessor keys[index] = predecessor.keys.last! values[index] = predecessor.values.last! children![index].remove(keys[index]) if children![index].numberOfKeys < owner.order { fix(childWithTooFewKeys: children![index], atIndex: index) } } } else if key < keys[index] { // We should go to left child... if let leftChild = children?[index] { leftChild.remove(key) if leftChild.numberOfKeys < owner.order { fix(childWithTooFewKeys: leftChild, atIndex: index) } } else { print("The key:\(key) is not in the tree.") } } else { // We should go to right child... if let rightChild = children?[(index + 1)] { rightChild.remove(key) if rightChild.numberOfKeys < owner.order { fix(childWithTooFewKeys: rightChild, atIndex: (index + 1)) } } else { print("The key:\(key) is not in the tree") } } } /** * Fixes `childWithTooFewKeys` by either moving a key to it from * one of its neighbouring nodes, or by merging. * * - Precondition: * `childWithTooFewKeys` must have less keys than the order of the tree. * * - Parameters: * - child: the child to be fixed * - index: the index of the child to be fixed in the current node */ private func fix(childWithTooFewKeys child: BTreeNode, atIndex index: Int) { if (index - 1) >= 0 && children![(index - 1)].numberOfKeys > owner.order { move(keyAtIndex: (index - 1), to: child, from: children![(index - 1)], at: .left) } else if (index + 1) < children!.count && children![(index + 1)].numberOfKeys > owner.order { move(keyAtIndex: index, to: child, from: children![(index + 1)], at: .right) } else if (index - 1) >= 0 { merge(child: child, atIndex: index, to: .left) } else { merge(child: child, atIndex: index, to: .right) } } /** * Moves the key at the specified `index` from `node` to * the `targetNode` at `position` * * - Parameters: * - index: the index of the key to be moved in `node` * - targetNode: the node to move the key into * - node: the node to move the key from * - position: the position of the from node relative to the targetNode */ private func move(keyAtIndex index: Int, to targetNode: BTreeNode, from node: BTreeNode, at position: BTreeNodePosition) { switch position { case .left: targetNode.keys.insert(keys[index], at: targetNode.keys.startIndex) targetNode.values.insert(values[index], at: targetNode.values.startIndex) keys[index] = node.keys.last! values[index] = node.values.last! node.keys.removeLast() node.values.removeLast() if !targetNode.isLeaf { targetNode.children!.insert(node.children!.last!, at: targetNode.children!.startIndex) node.children!.removeLast() } case .right: targetNode.keys.insert(keys[index], at: targetNode.keys.endIndex) targetNode.values.insert(values[index], at: targetNode.values.endIndex) keys[index] = node.keys.first! values[index] = node.values.first! node.keys.removeFirst() node.values.removeFirst() if !targetNode.isLeaf { targetNode.children!.insert(node.children!.first!, at: targetNode.children!.endIndex) node.children!.removeFirst() } } } /** * Merges `child` at `position` to the node at the `position`. * * - Parameters: * - child: the child to be merged * - index: the index of the child in the current node * - position: the position of the node to merge into */ private func merge(child: BTreeNode, atIndex index: Int, to position: BTreeNodePosition) { switch position { case .left: // We can merge to the left sibling children![(index - 1)].keys = children![(index - 1)].keys + [keys[(index - 1)]] + child.keys children![(index - 1)].values = children![(index - 1)].values + [values[(index - 1)]] + child.values keys.remove(at: (index - 1)) values.remove(at: (index - 1)) if !child.isLeaf { children![(index - 1)].children = children![(index - 1)].children! + child.children! } case .right: // We should merge to the right sibling children![(index + 1)].keys = child.keys + [keys[index]] + children![(index + 1)].keys children![(index + 1)].values = child.values + [values[index]] + children![(index + 1)].values keys.remove(at: index) values.remove(at: index) if !child.isLeaf { children![(index + 1)].children = child.children! + children![(index + 1)].children! } } children!.remove(at: index) } } // MARK: BTreeNode extension: Conversion extension BTreeNode { /** * Returns an array which contains the keys from the current node * and its descendants in order. */ var inorderArrayFromKeys: [Key] { var array = [Key] () for i in 0.. { /** * The order of the B-Tree * * The number of keys in every node should be in the [order, 2*order] range, * except the root node which is allowed to contain less keys than the value of order. */ public let order: Int /** * The root node of the tree */ var rootNode: BTreeNode! fileprivate(set) public var numberOfKeys = 0 /** * Designated initializer for the tree * * - Parameters: * - order: The order of the tree. */ public init?(order: Int) { guard order > 0 else { print("Order has to be greater than 0.") return nil } self.order = order rootNode = BTreeNode(owner: self) } } // MARK: BTree extension: Traversals extension BTree { /** * Traverses the keys in order, executes `process` for every key. * * - Parameters: * - process: the closure to be executed for every key */ public func traverseKeysInOrder(_ process: (Key) -> Void) { rootNode.traverseKeysInOrder(process) } } // MARK: BTree extension: Subscript extension BTree { /** * Returns the value for a given `key`, returns nil if the `key` is not found. * * - Parameters: * - key: the key of the value to be returned */ public subscript (key: Key) -> Value? { return value(for: key) } } // MARK: BTree extension: Value for Key extension BTree { /** * Returns the value for a given `key`, returns nil if the `key` is not found. * * - Parameters: * - key: the key of the value to be returned */ public func value(for key: Key) -> Value? { guard rootNode.numberOfKeys > 0 else { return nil } return rootNode.value(for: key) } } // MARK: BTree extension: Insertion extension BTree { /** * Inserts the `value` for the `key` into the tree. * * - Parameters: * - value: the value to be inserted for `key` * - key: the key for the `value` */ public func insert(_ value: Value, for key: Key) { rootNode.insert(value, for: key) if rootNode.numberOfKeys > order * 2 { splitRoot() } } /** * Splits the root node of the tree. * * - Precondition: * The root node of the tree contains `order` * 2 keys. */ private func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 let newRoot = BTreeNode( owner: self, keys: [rootNode.keys[middleIndexOfOldRoot]], values: [rootNode.values[middleIndexOfOldRoot]], children: [rootNode] ) rootNode.keys.remove(at: middleIndexOfOldRoot) rootNode.values.remove(at: middleIndexOfOldRoot) let newRightChild = BTreeNode( owner: self, keys: Array(rootNode.keys[rootNode.keys.indices.suffix(from: middleIndexOfOldRoot)]), values: Array(rootNode.values[rootNode.values.indices.suffix(from: middleIndexOfOldRoot)]) ) rootNode.keys.removeSubrange(rootNode.keys.indices.suffix(from: middleIndexOfOldRoot)) rootNode.values.removeSubrange(rootNode.values.indices.suffix(from: middleIndexOfOldRoot)) if rootNode.children != nil { newRightChild.children = Array( rootNode.children![rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1))] ) rootNode.children!.removeSubrange( rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1)) ) } newRoot.children!.append(newRightChild) rootNode = newRoot } } // MARK: BTree extension: Removal extension BTree { /** * Removes `key` and the value associated with it from the tree. * * - Parameters: * - key: the key to remove */ public func remove(_ key: Key) { guard rootNode.numberOfKeys > 0 else { return } rootNode.remove(key) if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { rootNode = rootNode.children!.first! } } } // MARK: BTree extension: Conversion extension BTree { /** * The keys of the tree in order. */ public var inorderArrayFromKeys: [Key] { return rootNode.inorderArrayFromKeys } } // MARK: BTree extension: Decription extension BTree: CustomStringConvertible { /** * Returns a String containing the preorder representation of the nodes. */ public var description: String { return rootNode.description } } ================================================ FILE: B-Tree/BTree.playground/contents.xcplayground ================================================ ================================================ FILE: B-Tree/BTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: B-Tree/BTree.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: B-Tree/BTree.swift ================================================ // The MIT License (MIT) // Copyright (c) 2016 Viktor Szilárd Simkó (aqviktor[at]gmail.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /* * B-Tree * * A B-Tree is a self-balancing search tree, in which nodes can have more than two children. */ // MARK: - BTreeNode class class BTreeNode { /** * The tree that owns the node. */ unowned var owner: BTree fileprivate var keys = [Key]() fileprivate var values = [Value]() var children: [BTreeNode]? var isLeaf: Bool { return children == nil } var numberOfKeys: Int { return keys.count } init(owner: BTree) { self.owner = owner } convenience init(owner: BTree, keys: [Key], values: [Value], children: [BTreeNode]? = nil) { self.init(owner: owner) self.keys += keys self.values += values self.children = children } } // MARK: BTreeNode extesnion: Searching extension BTreeNode { /** * Returns the value for a given `key`, returns nil if the `key` is not found. * * - Parameters: * - key: the key of the value to be returned */ func value(for key: Key) -> Value? { var index = keys.startIndex while (index + 1) < keys.endIndex && keys[index] < key { index = (index + 1) } if key == keys[index] { return values[index] } else if key < keys[index] { return children?[index].value(for: key) } else { return children?[(index + 1)].value(for: key) } } } // MARK: BTreeNode extension: Travelsals extension BTreeNode { /** * Traverses the keys in order, executes `process` for every key. * * - Parameters: * - process: the closure to be executed for every key */ func traverseKeysInOrder(_ process: (Key) -> Void) { for i in 0.. owner.order * 2 { split(child: children![index], atIndex: index) } } } /** * Splits `child` at `index`. * The key-value pair at `index` gets moved up to the parent node, * or if there is not an parent node, then a new parent node is created. * * - Parameters: * - child: the child to be split * - index: the index of the key, which will be moved up to the parent */ private func split(child: BTreeNode, atIndex index: Int) { let middleIndex = child.numberOfKeys / 2 keys.insert(child.keys[middleIndex], at: index) values.insert(child.values[middleIndex], at: index) child.keys.remove(at: middleIndex) child.values.remove(at: middleIndex) let rightSibling = BTreeNode( owner: owner, keys: Array(child.keys[child.keys.indices.suffix(from: middleIndex)]), values: Array(child.values[child.values.indices.suffix(from: middleIndex)]) ) child.keys.removeSubrange(child.keys.indices.suffix(from: middleIndex)) child.values.removeSubrange(child.values.indices.suffix(from: middleIndex)) children!.insert(rightSibling, at: (index + 1)) if child.children != nil { rightSibling.children = Array( child.children![child.children!.indices.suffix(from: (middleIndex + 1))] ) child.children!.removeSubrange(child.children!.indices.suffix(from: (middleIndex + 1))) } } } // MARK: BTreeNode extension: Removal /** * An enumeration to indicate a node's position according to another node. * * Possible values: * - left * - right */ private enum BTreeNodePosition { case left case right } extension BTreeNode { private var inorderPredecessor: BTreeNode { if isLeaf { return self } else { return children!.last!.inorderPredecessor } } /** * Removes `key` and the value associated with it from the node * or one of its descendants. * * - Parameters: * - key: the key to be removed */ func remove(_ key: Key) { var index = keys.startIndex while (index + 1) < keys.endIndex && keys[index] < key { index = (index + 1) } if keys[index] == key { if isLeaf { keys.remove(at: index) values.remove(at: index) owner.numberOfKeys -= 1 } else { let predecessor = children![index].inorderPredecessor keys[index] = predecessor.keys.last! values[index] = predecessor.values.last! children![index].remove(keys[index]) if children![index].numberOfKeys < owner.order { fix(childWithTooFewKeys: children![index], atIndex: index) } } } else if key < keys[index] { // We should go to left child... if let leftChild = children?[index] { leftChild.remove(key) if leftChild.numberOfKeys < owner.order { fix(childWithTooFewKeys: leftChild, atIndex: index) } } else { print("The key:\(key) is not in the tree.") } } else { // We should go to right child... if let rightChild = children?[(index + 1)] { rightChild.remove(key) if rightChild.numberOfKeys < owner.order { fix(childWithTooFewKeys: rightChild, atIndex: (index + 1)) } } else { print("The key:\(key) is not in the tree") } } } /** * Fixes `childWithTooFewKeys` by either moving a key to it from * one of its neighbouring nodes, or by merging. * * - Precondition: * `childWithTooFewKeys` must have less keys than the order of the tree. * * - Parameters: * - child: the child to be fixed * - index: the index of the child to be fixed in the current node */ private func fix(childWithTooFewKeys child: BTreeNode, atIndex index: Int) { if (index - 1) >= 0 && children![(index - 1)].numberOfKeys > owner.order { move(keyAtIndex: (index - 1), to: child, from: children![(index - 1)], at: .left) } else if (index + 1) < children!.count && children![(index + 1)].numberOfKeys > owner.order { move(keyAtIndex: index, to: child, from: children![(index + 1)], at: .right) } else if (index - 1) >= 0 { merge(child: child, atIndex: index, to: .left) } else { merge(child: child, atIndex: index, to: .right) } } /** * Moves the key at the specified `index` from `node` to * the `targetNode` at `position` * * - Parameters: * - index: the index of the key to be moved in `node` * - targetNode: the node to move the key into * - node: the node to move the key from * - position: the position of the from node relative to the targetNode */ private func move(keyAtIndex index: Int, to targetNode: BTreeNode, from node: BTreeNode, at position: BTreeNodePosition) { switch position { case .left: targetNode.keys.insert(keys[index], at: targetNode.keys.startIndex) targetNode.values.insert(values[index], at: targetNode.values.startIndex) keys[index] = node.keys.last! values[index] = node.values.last! node.keys.removeLast() node.values.removeLast() if !targetNode.isLeaf { targetNode.children!.insert(node.children!.last!, at: targetNode.children!.startIndex) node.children!.removeLast() } case .right: targetNode.keys.insert(keys[index], at: targetNode.keys.endIndex) targetNode.values.insert(values[index], at: targetNode.values.endIndex) keys[index] = node.keys.first! values[index] = node.values.first! node.keys.removeFirst() node.values.removeFirst() if !targetNode.isLeaf { targetNode.children!.insert(node.children!.first!, at: targetNode.children!.endIndex) node.children!.removeFirst() } } } /** * Merges `child` at `position` to the node at the `position`. * * - Parameters: * - child: the child to be merged * - index: the index of the child in the current node * - position: the position of the node to merge into */ private func merge(child: BTreeNode, atIndex index: Int, to position: BTreeNodePosition) { switch position { case .left: // We can merge to the left sibling children![(index - 1)].keys = children![(index - 1)].keys + [keys[(index - 1)]] + child.keys children![(index - 1)].values = children![(index - 1)].values + [values[(index - 1)]] + child.values keys.remove(at: (index - 1)) values.remove(at: (index - 1)) if !child.isLeaf { children![(index - 1)].children = children![(index - 1)].children! + child.children! } case .right: // We should merge to the right sibling children![(index + 1)].keys = child.keys + [keys[index]] + children![(index + 1)].keys children![(index + 1)].values = child.values + [values[index]] + children![(index + 1)].values keys.remove(at: index) values.remove(at: index) if !child.isLeaf { children![(index + 1)].children = child.children! + children![(index + 1)].children! } } children!.remove(at: index) } } // MARK: BTreeNode extension: Conversion extension BTreeNode { /** * Returns an array which contains the keys from the current node * and its descendants in order. */ var inorderArrayFromKeys: [Key] { var array = [Key] () for i in 0.. { /** * The order of the B-Tree * * The number of keys in every node should be in the [order, 2*order] range, * except the root node which is allowed to contain less keys than the value of order. */ public let order: Int /** * The root node of the tree */ var rootNode: BTreeNode! fileprivate(set) public var numberOfKeys = 0 /** * Designated initializer for the tree * * - Parameters: * - order: The order of the tree. */ public init?(order: Int) { guard order > 0 else { print("Order has to be greater than 0.") return nil } self.order = order rootNode = BTreeNode(owner: self) } } // MARK: BTree extension: Travelsals extension BTree { /** * Traverses the keys in order, executes `process` for every key. * * - Parameters: * - process: the closure to be executed for every key */ public func traverseKeysInOrder(_ process: (Key) -> Void) { rootNode.traverseKeysInOrder(process) } } // MARK: BTree extension: Subscript extension BTree { /** * Returns the value for a given `key`, returns nil if the `key` is not found. * * - Parameters: * - key: the key of the value to be returned */ public subscript (key: Key) -> Value? { return value(for: key) } } // MARK: BTree extension: Value for Key extension BTree { /** * Returns the value for a given `key`, returns nil if the `key` is not found. * * - Parameters: * - key: the key of the value to be returned */ public func value(for key: Key) -> Value? { guard rootNode.numberOfKeys > 0 else { return nil } return rootNode.value(for: key) } } // MARK: BTree extension: Insertion extension BTree { /** * Inserts the `value` for the `key` into the tree. * * - Parameters: * - value: the value to be inserted for `key` * - key: the key for the `value` */ public func insert(_ value: Value, for key: Key) { rootNode.insert(value, for: key) if rootNode.numberOfKeys > order * 2 { splitRoot() } } /** * Splits the root node of the tree. * * - Precondition: * The root node of the tree contains `order` * 2 keys. */ private func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 let newRoot = BTreeNode( owner: self, keys: [rootNode.keys[middleIndexOfOldRoot]], values: [rootNode.values[middleIndexOfOldRoot]], children: [rootNode] ) rootNode.keys.remove(at: middleIndexOfOldRoot) rootNode.values.remove(at: middleIndexOfOldRoot) let newRightChild = BTreeNode( owner: self, keys: Array(rootNode.keys[rootNode.keys.indices.suffix(from: middleIndexOfOldRoot)]), values: Array(rootNode.values[rootNode.values.indices.suffix(from: middleIndexOfOldRoot)]) ) rootNode.keys.removeSubrange(rootNode.keys.indices.suffix(from: middleIndexOfOldRoot)) rootNode.values.removeSubrange(rootNode.values.indices.suffix(from: middleIndexOfOldRoot)) if rootNode.children != nil { newRightChild.children = Array( rootNode.children![rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1))] ) rootNode.children!.removeSubrange( rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1)) ) } newRoot.children!.append(newRightChild) rootNode = newRoot } } // MARK: BTree extension: Removal extension BTree { /** * Removes `key` and the value associated with it from the tree. * * - Parameters: * - key: the key to remove */ public func remove(_ key: Key) { guard rootNode.numberOfKeys > 0 else { return } rootNode.remove(key) if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { rootNode = rootNode.children!.first! } } } // MARK: BTree extension: Conversion extension BTree { /** * The keys of the tree in order. */ public var inorderArrayFromKeys: [Key] { return rootNode.inorderArrayFromKeys } } // MARK: BTree extension: Decription extension BTree: CustomStringConvertible { /** * Returns a String containing the preorder representation of the nodes. */ public var description: String { return rootNode.description } } ================================================ FILE: B-Tree/README.md ================================================ # B-Tree A B-Tree is a self-balancing search tree, in which nodes can have more than two children. ### Properties A B-Tree of order *n* satisfies the following properties: - Every node has at most *2n* keys. - Every node (except root) has at least *n* keys. - Every non-leaf node with *k* keys has *k+1* children. - The keys in all nodes are sorted in increasing order. - The subtree between two keys *k* and *l* of a non-leaf node contains all the keys between *k* and *l*. - All leaves appear at the same level. A second order B-Tree with keys from 1 to 20 looks like this: ![A B-Tree with 20 keys.](Images/BTree20.png) ### The representation of a B-Tree node in code ```swift class BTreeNode { unowned var owner: BTree fileprivate var keys = [Key]() var children: [BTreeNode]? ... } ``` The main parts of a node are two arrays: - An array containing the keys - An array containing the children ![Node.](Images/Node.png) Nodes also have a reference to the tree they belong to. This is necessary because nodes have to know the order of the tree. *Note: The array containing the children is an Optional, because leaf nodes don't have children.* ## Searching 1. Searching for a key `k` begins at the root node. 2. We perform a linear search on the keys of the node, until we find a key `l` that is not less than `k`, or reach the end of the array. 3. If `k == l` then we have found the key. 4. If `k < l`: - If the node we are on is not a leaf, then we go to the left child of `l`, and perform the steps 3 - 5 again. - If we are on a leaf, then `k` is not in the tree. 5. If we have reached the end of the array: - If we are on a non-leaf node, then we go to the last child of the node, and perform the steps 3 - 5 again. - If we are on a leaf, then `k` is not in the tree. ### The code `value(for:)` method searches for the given key and if it's in the tree, it returns the value associated with it, else it returns `nil`. ## Insertion Keys can only be inserted to leaf nodes. 1. Perform a search for the key `k` we want to insert. 2. If we haven't found it and we are on a leaf node, we can insert it. - If after the search the key `l` which we are standing on is greater than `k`: We insert `k` to the position before `l`. - Else: We insert `k` to the position after `l`. After insertion we should check if the number of keys in the node is in the correct range. If there are more keys in the node than `order*2`, we need to split the node. #### Splitting a node 1. Move up the middle key of the node we want to split, to its parent (if it has one). 2. If it hasn't got a parent(it is the root), then create a new root and insert to it. Also add the old root as the left child of the new root. 3. Split the node into two by moving the keys (and children, if it's a non-leaf) that were after the middle key to a new node. 4. Add the new node as a right child for the key that we have moved up. After splitting a node it is possible that the parent node will also contain too many keys, so we need to split it also. In the worst case the splitting goes up to the root (in this case the height of the tree increases). An insertion to a first order tree looks like this: ![Splitting](Images/InsertionSplit.png) ### The code The method `insert(_:for:)` does the insertion. After it has inserted a key, as the recursion goes up every node checks the number of keys in its child. if a node has too many keys, its parent calls the `split(child:atIndex:)` method on it. The root node is checked by the tree itself. If the root has too many nodes after the insertion the tree calls the `splitRoot()` method. ## Removal Keys can only be removed from leaf nodes. 1. Perform a search for the key `k` we want to remove. 2. If we have found it: - If we are on a leaf node: We can remove the key. - Else: We overwrite `k` with its inorder predecessor `p`, then we remove `p` from the leaf node. After a key have been removed from a node we should check that the node has enough keys. If a node has fewer keys than the order of the tree, then we should move a key to it, or merge it with one of its siblings. #### Moving a key to the child If the problematic node has a nearest sibling that has more keys than the order of the tree, we should perform this operation on the tree, else we should merge the node with one of its siblings. Let's say the child we want to fix `c1` is at index `i` in its parent node's children array. If the child `c2` at index `i-1` has more keys than the order of the tree: 1. We move the key at index `i-1` from the parent node to the child `c1`'s keys array at index `0`. 2. We move the last key from `c2` to the parent's keys array at index `i-1`. 3. (If `c1` is non-leaf) We move the last child from `c2` to `c1`'s children array at index 0. Else: 1. We move the key at index `i` from the parent node to the end of child `c1`'s keys array. 2. We move the first key from `c2` to the parent's keys array at index `i`. 3. (If `c1` isn't a leaf) We move the first child from `c2` to the end of `c1`'s children array. ![Moving Key](Images/MovingKey.png) #### Merging two nodes Let's say we want to merge the child `c1` at index `i` in its parent's children array. If `c1` has a left sibling `c2`: 1. We move the key from the parent at index `i-1` to the end of `c2`'s keys array. 2. We move the keys and the children(if it's a non-leaf) from `c1` to the end of `c2`'s keys and children array. 3. We remove the child at index `i-1` from the parent node. Else if `c1` only has a right sibling `c2`: 1. We move the key from the parent at index `i` to the beginning of `c2`'s keys array. 2. We move the keys and the children(if it's a non-leaf) from `c1` to the beginning of `c2`'s keys and children array. 3. We remove the child at index `i` from the parent node. After merging it is possible that now the parent node contains too few keys, so in the worst case merging also can go up to the root, in which case the height of the tree decreases. ![Merging Nodes](Images/MergingNodes.png) ### The code - `remove(_:)` method removes the given key from the tree. After a key has been deleted, every node checks the number of keys in its child. If a child has less nodes than the order of the tree, it calls the `fix(childWithTooFewKeys:atIndex:)` method. - `fix(childWithTooFewKeys:atIndex:)` method decides which way to fix the child (by moving a key to it, or by merging it), then calls `move(keyAtIndex:to:from:at:)` or `merge(child:atIndex:to:)` method according to its choice. ## See also [Wikipedia](https://en.wikipedia.org/wiki/B-tree) [GeeksforGeeks](http://www.geeksforgeeks.org/b-tree-set-1-introduction-2/) *Written for Swift Algorithm Club by Viktor Szilárd Simkó* ================================================ FILE: B-Tree/Tests/Tests/BTreeNodeTests.swift ================================================ // // BTreeNodeTests.swift // BTree // // Created by Viktor Szilárd Simkó on 13/06/16. // Copyright © 2016 Viktor Szilárd Simkó. All rights reserved. // import XCTest class BTreeNodeTests: XCTestCase { let owner = BTree(order: 2)! var root: BTreeNode! var leftChild: BTreeNode! var rightChild: BTreeNode! func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } override func setUp() { super.setUp() root = BTreeNode(owner: owner) leftChild = BTreeNode(owner: owner) rightChild = BTreeNode(owner: owner) root.insert(1, for: 1) root.children = [leftChild, rightChild] } func testIsLeafRoot() { XCTAssertFalse(root.isLeaf) } func testIsLeafLeaf() { XCTAssertTrue(leftChild.isLeaf) XCTAssertTrue(rightChild.isLeaf) } func testOwner() { XCTAssert(root.owner === owner) XCTAssert(leftChild.owner === owner) XCTAssert(rightChild.owner === owner) } func testNumberOfKeys() { XCTAssertEqual(root.numberOfKeys, 1) XCTAssertEqual(leftChild.numberOfKeys, 0) XCTAssertEqual(rightChild.numberOfKeys, 0) } func testChildren() { XCTAssertEqual(root.children!.count, 2) } } ================================================ FILE: B-Tree/Tests/Tests/BTreeTests.swift ================================================ // // BTreeTests.swift // BTreeTests // // Created by Viktor Szilárd Simkó on 09/06/16. // Copyright © 2016 Viktor Szilárd Simkó. All rights reserved. // import XCTest class BTreeTests: XCTestCase { var bTree: BTree! func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } override func setUp() { super.setUp() bTree = BTree(order: 3)! } // MARK: - Tests on empty tree func testOrder() { XCTAssertEqual(bTree.order, 3) } func testRootNode() { XCTAssertNotNil(bTree.rootNode) } func testNumberOfNodesOnEmptyTree() { XCTAssertEqual(bTree.numberOfKeys, 0) } func testInorderTraversalOfEmptyTree() { bTree.traverseKeysInOrder { _ in XCTFail("Inorder travelsal fail.") } } func testSubscriptOnEmptyTree() { XCTAssertEqual(bTree[1], nil) } func testSearchEmptyTree() { XCTAssertEqual(bTree.value(for: 1), nil) } func testInsertToEmptyTree() { bTree.insert(1, for: 1) XCTAssertEqual(bTree[1]!, 1) } func testRemoveFromEmptyTree() { bTree.remove(1) XCTAssertEqual(bTree.description, "[]") } func testInorderArrayFromEmptyTree() { XCTAssertEqual(bTree.inorderArrayFromKeys, [Int]()) } func testDescriptionOfEmptyTree() { XCTAssertEqual(bTree.description, "[]") } // MARK: - Travelsal func testInorderTravelsal() { for i in 1...20 { bTree.insert(i, for: i) } var j = 1 bTree.traverseKeysInOrder { i in XCTAssertEqual(i, j) j += 1 } } // MARK: - Searching func testSearchForMaximum() { for i in 1...20 { bTree.insert(i, for: i) } XCTAssertEqual(bTree.value(for: 20)!, 20) } func testSearchForMinimum() { for i in 1...20 { bTree.insert(i, for: i) } XCTAssertEqual(bTree.value(for: 1)!, 1) } // MARK: - Insertion func testInsertion() { bTree.insertKeysUpTo(20) XCTAssertEqual(bTree.numberOfKeys, 20) for i in 1...20 { XCTAssertNotNil(bTree[i]) } do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } // MARK: - Removal func testRemoveMaximum() { for i in 1...20 { bTree.insert(i, for: i) } bTree.remove(20) XCTAssertNil(bTree[20]) do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } func testRemoveMinimum() { bTree.insertKeysUpTo(20) bTree.remove(1) XCTAssertNil(bTree[1]) do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } func testRemoveSome() { bTree.insertKeysUpTo(20) bTree.remove(6) bTree.remove(9) XCTAssertNil(bTree[6]) XCTAssertNil(bTree[9]) do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } func testRemoveSomeFrom2ndOrder() { bTree = BTree(order: 2)! bTree.insertKeysUpTo(20) bTree.remove(6) bTree.remove(9) XCTAssertNil(bTree[6]) XCTAssertNil(bTree[9]) do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } } func testRemoveAll() { bTree.insertKeysUpTo(20) XCTAssertEqual(bTree.numberOfKeys, 20) for i in (1...20).reversed() { bTree.remove(i) } do { try bTree.checkBalance() } catch { XCTFail("BTree is not balanced") } XCTAssertEqual(bTree.numberOfKeys, 0) } // MARK: - InorderArray func testInorderArray() { bTree.insertKeysUpTo(20) let returnedArray = bTree.inorderArrayFromKeys let targetArray = Array(1...20) XCTAssertEqual(returnedArray, targetArray) } } enum BTreeError: Error { case tooManyNodes case tooFewNodes } extension BTreeNode { func checkBalance(isRoot root: Bool) throws { if numberOfKeys > owner.order * 2 { throw BTreeError.tooManyNodes } else if !root && numberOfKeys < owner.order { throw BTreeError.tooFewNodes } if !isLeaf { for child in children! { try child.checkBalance(isRoot: false) } } } } extension BTree where Key: SignedInteger, Value: SignedInteger { func insertKeysUpTo(_ to: Int) { var k: Key = 1 var v: Value = 1 for _ in 1...to { insert(v, for: k) k = k + 1 v = v + 1 } } func checkBalance() throws { try rootNode.checkBalance(isRoot: true) } } ================================================ FILE: B-Tree/Tests/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: B-Tree/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ C66702821D0EEE5F008CD769 /* BTreeNodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66702801D0EEE5F008CD769 /* BTreeNodeTests.swift */; }; C66702831D0EEE5F008CD769 /* BTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66702811D0EEE5F008CD769 /* BTreeTests.swift */; }; C66702851D0EEE99008CD769 /* BTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66702841D0EEE99008CD769 /* BTree.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ C66702781D0EEE25008CD769 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C667027C1D0EEE25008CD769 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C66702801D0EEE5F008CD769 /* BTreeNodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BTreeNodeTests.swift; sourceTree = ""; }; C66702811D0EEE5F008CD769 /* BTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BTreeTests.swift; sourceTree = ""; }; C66702841D0EEE99008CD769 /* BTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BTree.swift; path = ../../BTree.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ C66702751D0EEE25008CD769 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ C66702611D0EEE0D008CD769 = { isa = PBXGroup; children = ( C66702791D0EEE25008CD769 /* Tests */, C667026B1D0EEE0D008CD769 /* Products */, ); sourceTree = ""; }; C667026B1D0EEE0D008CD769 /* Products */ = { isa = PBXGroup; children = ( C66702781D0EEE25008CD769 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; C66702791D0EEE25008CD769 /* Tests */ = { isa = PBXGroup; children = ( C66702841D0EEE99008CD769 /* BTree.swift */, C66702801D0EEE5F008CD769 /* BTreeNodeTests.swift */, C66702811D0EEE5F008CD769 /* BTreeTests.swift */, C667027C1D0EEE25008CD769 /* Info.plist */, ); path = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ C66702771D0EEE25008CD769 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = C667027D1D0EEE25008CD769 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( C66702741D0EEE25008CD769 /* Sources */, C66702751D0EEE25008CD769 /* Frameworks */, C66702761D0EEE25008CD769 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = C66702781D0EEE25008CD769 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ C66702621D0EEE0D008CD769 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Viktor Szilárd Simkó"; TargetAttributes = { C66702771D0EEE25008CD769 = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = C66702651D0EEE0D008CD769 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = C66702611D0EEE0D008CD769; productRefGroup = C667026B1D0EEE0D008CD769 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( C66702771D0EEE25008CD769 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ C66702761D0EEE25008CD769 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ C66702741D0EEE25008CD769 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( C66702831D0EEE5F008CD769 /* BTreeTests.swift in Sources */, C66702821D0EEE5F008CD769 /* BTreeNodeTests.swift in Sources */, C66702851D0EEE99008CD769 /* BTree.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ C667026F1D0EEE0D008CD769 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; C66702701D0EEE0D008CD769 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; }; name = Release; }; C667027E1D0EEE25008CD769 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = viktorsimko.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; }; name = Debug; }; C667027F1D0EEE25008CD769 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = viktorsimko.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ C66702651D0EEE0D008CD769 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( C667026F1D0EEE0D008CD769 /* Debug */, C66702701D0EEE0D008CD769 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; C667027D1D0EEE25008CD769 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( C667027E1D0EEE25008CD769 /* Debug */, C667027F1D0EEE25008CD769 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = C66702621D0EEE0D008CD769 /* Project object */; } ================================================ FILE: B-Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: B-Tree/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: B-Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Big-O Notation.markdown ================================================ # A note on Big-O notation It's useful to know how fast an algorithm is and how much space it needs. This allows you to pick the right algorithm for the job. Big-O notation gives you a rough indication of the running time of an algorithm and the amount of memory it uses. When someone says, "This algorithm has worst-case running time of **O(n^2)** and uses **O(n)** space," they mean it's kinda slow but doesn't need lots of extra memory. Figuring out the Big-O of an algorithm is usually done through mathematical analysis. We're skipping the math here, but it's useful to know what the different values mean, so here's a handy table. **n** refers to the number of data items that you're processing. For example, when sorting an array of 100 items, **n = 100**. Big-O | Name | Description ------| ---- | ----------- **O(1)** | constant | **This is the best.** The algorithm always takes the same amount of time, regardless of how much data there is. Example: looking up an element of an array by its index. **O(log n)** | logarithmic | **Pretty great.** These kinds of algorithms halve the amount of data with each iteration. If you have 100 items, it takes about 7 steps to find the answer. With 1,000 items, it takes 10 steps. And 1,000,000 items only take 20 steps. This is super fast even for large amounts of data. Example: binary search. **O(n)** | linear | **Good performance.** If you have 100 items, this does 100 units of work. Doubling the number of items makes the algorithm take exactly twice as long (200 units of work). Example: sequential search. **O(n log n)** | "linearithmic" | **Decent performance.** This is slightly worse than linear but not too bad. Example: the fastest general-purpose sorting algorithms. **O(n^2)** | quadratic | **Kinda slow.** If you have 100 items, this does 100^2 = 10,000 units of work. Doubling the number of items makes it four times slower (because 2 squared equals 4). Example: algorithms using nested loops, such as insertion sort. **O(n^3)** | cubic | **Poor performance.** If you have 100 items, this does 100^3 = 1,000,000 units of work. Doubling the input size makes it eight times slower. Example: matrix multiplication. **O(2^n)** | exponential | **Very poor performance.** You want to avoid these kinds of algorithms, but sometimes you have no choice. Adding just one bit to the input doubles the running time. Example: traveling salesperson problem. **O(n!)** | factorial | **Intolerably slow.** It literally takes a million years to do anything. ![Comparison of Big O computations](https://upload.wikimedia.org/wikipedia/commons/7/7e/Comparison_computational_complexity.svg) Below are some examples for each category of performance: **O(1)** The most common example with O(1) complexity is accessing an array index. ```swift let value = array[5] ``` Another example of O(1) is pushing and popping from Stack. **O(log n)** ```swift var j = 1 while j < n { // do constant time stuff j *= 2 } ``` Instead of simply incrementing, 'j' is increased by 2 times itself in each run. Binary Search Algorithm is an example of O(log n) complexity. **O(n)** ```swift for i in stride(from: 0, to: n, by: 1) { print(array[i]) } ``` Array Traversal and Linear Search are examples of O(n) complexity. **O(n log n)** ```swift for i in stride(from: 0, to: n, by: 1) { var j = 1 while j < n { j *= 2 // do constant time stuff } } ``` OR ```swift for i in stride(from: 0, to: n, by: 1) { func index(after i: Int) -> Int? { // multiplies `i` by 2 until `i` >= `n` return i < n ? i * 2 : nil } for j in sequence(first: 1, next: index(after:)) { // do constant time stuff } } ``` Merge Sort and Heap Sort are examples of O(n log n) complexity. **O(n^2)** ```swift for i in stride(from: 0, to: n, by: 1) { for j in stride(from: 1, to: n, by: 1) { // do constant time stuff } } ``` Traversing a simple 2-D array and Bubble Sort are examples of O(n^2) complexity. **O(n^3)** ```swift for i in stride(from: 0, to: n, by: 1) { for j in stride(from: 1, to: n, by: 1) { for k in stride(from: 1, to: n, by: 1) { // do constant time stuff } } } ``` **O(2^n)** Algorithms with running time O(2^N) are often recursive algorithms that solve a problem of size N by recursively solving two smaller problems of size N-1. The following example prints all the moves necessary to solve the famous "Towers of Hanoi" problem for N disks. ```swift func solveHanoi(n: Int, from: String, to: String, spare: String) { guard n >= 1 else { return } if n > 1 { solveHanoi(n: n - 1, from: from, to: spare, spare: to) solveHanoi(n: n - 1, from: spare, to: to, spare: from) } } ``` **O(n!)** The most trivial example of function that takes O(n!) time is given below. ```swift func nFactFunc(n: Int) { for i in stride(from: 0, to: n, by: 1) { nFactFunc(n: n - 1) } } ``` Often you don't need math to figure out what the Big-O of an algorithm is but you can simply use your intuition. If your code uses a single loop that looks at all **n** elements of your input, the algorithm is **O(n)**. If the code has two nested loops, it is **O(n^2)**. Three nested loops gives **O(n^3)**, and so on. Note that Big-O notation is an estimate and is only really useful for large values of **n**. For example, the worst-case running time for the [insertion sort](Insertion%20Sort/) algorithm is **O(n^2)**. In theory that is worse than the running time for [merge sort](Merge%20Sort/), which is **O(n log n)**. But for small amounts of data, insertion sort is actually faster, especially if the array is partially sorted already! If you find this confusing, don't let this Big-O stuff bother you too much. It's mostly useful when comparing two algorithms to figure out which one is better. But in the end you still want to test in practice which one really is the best. And if the amount of data is relatively small, then even a slow algorithm will be fast enough for practical use. ================================================ FILE: Binary Search/BinarySearch.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // An unsorted array of numbers let numbers = [11, 59, 3, 2, 53, 17, 31, 7, 19, 67, 47, 13, 37, 61, 29, 43, 5, 41, 23] // Binary search requires that the array is sorted from low to high let sorted = numbers.sorted() // Using recursive solution binarySearch(sorted, key: 2, range: 0 ..< sorted.count) // gives 0 binarySearch(sorted, key: 67, range: 0 ..< sorted.count) // gives 18 binarySearch(sorted, key: 43, range: 0 ..< sorted.count) // gives 13 binarySearch(sorted, key: 42, range: 0 ..< sorted.count) // nil // Using iterative solution binarySearch(sorted, key: 2) // gives 0 binarySearch(sorted, key: 67) // gives 18 binarySearch(sorted, key: 43) // gives 13 binarySearch(sorted, key: 42) // nil ================================================ FILE: Binary Search/BinarySearch.playground/contents.xcplayground ================================================ ================================================ FILE: Binary Search/BinarySearch.swift ================================================ /** Binary Search Recursively splits the array in half until the value is found. If there is more than one occurrence of the search key in the array, then there is no guarantee which one it finds. Note: The array must be sorted! **/ import Foundation // The recursive version of binary search. public func binarySearch(_ a: [T], key: T, range: Range) -> Int? { if range.lowerBound >= range.upperBound { return nil } else { let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 if a[midIndex] > key { return binarySearch(a, key: key, range: range.lowerBound ..< midIndex) } else if a[midIndex] < key { return binarySearch(a, key: key, range: midIndex + 1 ..< range.upperBound) } else { return midIndex } } } /** The iterative version of binary search. Notice how similar these functions are. The difference is that this one uses a while loop, while the other calls itself recursively. **/ public func binarySearch(_ a: [T], key: T) -> Int? { var lowerBound = 0 var upperBound = a.count while lowerBound < upperBound { let midIndex = lowerBound + (upperBound - lowerBound) / 2 if a[midIndex] == key { return midIndex } else if a[midIndex] < key { lowerBound = midIndex + 1 } else { upperBound = midIndex } } return nil } ================================================ FILE: Binary Search/README.markdown ================================================ # Binary Search Goal: Quickly find an element in an array. Let's say you have an array of numbers and you want to determine whether a specific number is in that array, and if so, at which index. In most cases, Swift's `Collection.index(of:)` function is good enough for that: ```swift let numbers = [11, 59, 3, 2, 53, 17, 31, 7, 19, 67, 47, 13, 37, 61, 29, 43, 5, 41, 23] numbers.index(of: 43) // returns 15 ``` The built-in `Collection.index(of:)` function performs a [linear search](../Linear%20Search/). In code that looks something like this: ```swift func linearSearch(_ a: [T], _ key: T) -> Int? { for i in 0 ..< a.count { if a[i] == key { return i } } return nil } ``` And you'd use it like this: ```swift linearSearch(numbers, 43) // returns 15 ``` So what's the problem? `linearSearch()` loops through the entire array from the beginning, until it finds the element you're looking for. In the worst case, the value isn't even in the array and all that work is done for nothing. On average, the linear search algorithm needs to look at half the values in the array. If your array is large enough, this starts to become very slow! ## Divide and conquer The classic way to speed this up is to use a *binary search*. The trick is to keep splitting the array in half until the value is found. For an array of size `n`, the performance is not **O(n)** as with linear search but only **O(log n)**. To put that in perspective, binary search on an array with 1,000,000 elements only takes about 20 steps to find what you're looking for, because `log_2(1,000,000) = 19.9`. And for an array with a billion elements it only takes 30 steps. (Then again, when was the last time you used an array with a billion items?) Sounds great, but there is a downside to using binary search: the array must be sorted. In practice, this usually isn't a problem. Here's how binary search works: - Split the array in half and determine whether the thing you're looking for, known as the *search key*, is in the left half or in the right half. - How do you determine in which half the search key is? This is why you sorted the array first, so you can do a simple `<` or `>` comparison. - If the search key is in the left half, you repeat the process there: split the left half into two even smaller pieces and look in which piece the search key must lie. (Likewise for when it's the right half.) - This repeats until the search key is found. If the array cannot be split up any further, you must regrettably conclude that the search key is not present in the array. Now you know why it's called a "binary" search: in every step it splits the array into two halves. This process of *divide-and-conquer* is what allows it to quickly narrow down where the search key must be. ## The code Here is a recursive implementation of binary search in Swift: ```swift func binarySearch(_ a: [T], key: T, range: Range) -> Int? { if range.lowerBound >= range.upperBound { // If we get here, then the search key is not present in the array. return nil } else { // Calculate where to split the array. let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 // Is the search key in the left half? if a[midIndex] > key { return binarySearch(a, key: key, range: range.lowerBound ..< midIndex) // Is the search key in the right half? } else if a[midIndex] < key { return binarySearch(a, key: key, range: midIndex + 1 ..< range.upperBound) // If we get here, then we've found the search key! } else { return midIndex } } } ``` To try this out, copy the code to a playground and do: ```swift let numbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67] binarySearch(numbers, key: 43, range: 0 ..< numbers.count) // gives 13 ``` Note that the `numbers` array is sorted. The binary search algorithm does not work otherwise! I said that binary search works by splitting the array in half, but we don't actually create two new arrays. Instead, we keep track of these splits using a Swift `Range` object. Initially, this range covers the entire array, `0 ..< numbers.count`. As we split the array, the range becomes smaller and smaller. > **Note:** One thing to be aware of is that `range.upperBound` always points one beyond the last element. In the example, the range is `0..<19` because there are 19 numbers in the array, and so `range.lowerBound = 0` and `range.upperBound = 19`. But in our array the last element is at index 18, not 19, since we start counting from 0. Just keep this in mind when working with ranges: the `upperBound` is always one more than the index of the last element. ## Stepping through the example It might be useful to look at how the algorithm works in detail. The array from the above example consists of 19 numbers and looks like this when sorted: [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] We're trying to determine if the number `43` is in this array. To split the array in half, we need to know the index of the object in the middle. That's determined by this line: ```swift let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 ``` Initially, the range has `lowerBound = 0` and `upperBound = 19`. Filling in these values, we find that `midIndex` is `0 + (19 - 0)/2 = 19/2 = 9`. It's actually `9.5` but because we're using integers, the answer is rounded down. In the next figure, the `*` shows the middle item. As you can see, the number of items on each side is the same, so we're split right down the middle. [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ] * Now binary search will determine which half to use. The relevant section from the code is: ```swift if a[midIndex] > key { // use left half } else if a[midIndex] < key { // use right half } else { return midIndex } ``` In this case, `a[midIndex] = 29`. That's less than the search key, so we can safely conclude that the search key will never be in the left half of the array. After all, the left half only contains numbers smaller than `29`. Hence, the search key must be in the right half somewhere (or not in the array at all). Now we can simply repeat the binary search, but on the array interval from `midIndex + 1` to `range.upperBound`: [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] Since we no longer need to concern ourselves with the left half of the array, I've marked that with `x`'s. From now on we'll only look at the right half, which starts at array index 10. We calculate the index of the new middle element: `midIndex = 10 + (19 - 10)/2 = 14`, and split the array down the middle again. [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43, 47, 53, 59, 61, 67 ] * As you can see, `a[14]` is indeed the middle element of the array's right half. Is the search key greater or smaller than `a[14]`? It's smaller because `43 < 47`. This time we're taking the left half and ignore the larger numbers on the right: [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] The new `midIndex` is here: [ x, x, x, x, x, x, x, x, x, x | 31, 37, 41, 43 | x, x, x, x, x ] * The search key is greater than `37`, so continue with the right side: [ x, x, x, x, x, x, x, x, x, x | x, x | 41, 43 | x, x, x, x, x ] * Again, the search key is greater, so split once more and take the right side: [ x, x, x, x, x, x, x, x, x, x | x, x | x | 43 | x, x, x, x, x ] * And now we're done. The search key equals the array element we're looking at, so we've finally found what we were searching for: number `43` is at array index `13`. w00t! It may have seemed like a lot of work, but in reality it only took four steps to find the search key in the array, which sounds about right because `log_2(19) = 4.23`. With a linear search, it would have taken 14 steps. What would happen if we were to search for `42` instead of `43`? In that case, we can't split up the array any further. The `range.upperBound` becomes smaller than `range.lowerBound`. That tells the algorithm the search key is not in the array and it returns `nil`. > **Note:** Many implementations of binary search calculate `midIndex = (lowerBound + upperBound) / 2`. This contains a subtle bug that only appears with very large arrays, because `lowerBound + upperBound` may overflow the maximum number an integer can hold. This situation is unlikely to happen on a 64-bit CPU, but it definitely can on 32-bit machines. ## Iterative vs recursive Binary search is recursive in nature because you apply the same logic over and over again to smaller and smaller subarrays. However, that does not mean you must implement `binarySearch()` as a recursive function. It's often more efficient to convert a recursive algorithm into an iterative version, using a simple loop instead of lots of recursive function calls. Here is an iterative implementation of binary search in Swift: ```swift func binarySearch(_ a: [T], key: T) -> Int? { var lowerBound = 0 var upperBound = a.count while lowerBound < upperBound { let midIndex = lowerBound + (upperBound - lowerBound) / 2 if a[midIndex] == key { return midIndex } else if a[midIndex] < key { lowerBound = midIndex + 1 } else { upperBound = midIndex } } return nil } ``` As you can see, the code is very similar to the recursive version. The main difference is in the use of the `while` loop. Use it like this: ```swift let numbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67] binarySearch(numbers, key: 43) // gives 13 ``` ## The end Is it a problem that the array must be sorted first? It depends. Keep in mind that sorting takes time -- the combination of binary search plus sorting may be slower than doing a simple linear search. Binary search shines in situations where you sort just once and then do many searches. See also [Wikipedia](https://en.wikipedia.org/wiki/Binary_search_algorithm). *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Binary Search/Tests/BinarySearchTests.swift ================================================ import Foundation import XCTest class BinarySearchTest: XCTestCase { var searchList = [Int]() override func setUp() { super.setUp() for number in 1...500 { searchList.append(number) } } func testEmptyArray() { let array = [Int]() let index = binarySearch(array, key: 123) XCTAssertNil(index) } func testBinarySearch() { for i in 1...100 { var array = [Int]() for number in 1...i { array.append(number) } let randomIndex = Int(arc4random_uniform(UInt32(i))) let testValue = array[randomIndex] let index = binarySearch(array, key: testValue) XCTAssertNotNil(index) XCTAssertEqual(index!, randomIndex) XCTAssertEqual(array[index!], testValue) } } func testLowerBound() { let index = binarySearch(searchList, key: 1) XCTAssertNotNil(index) XCTAssertEqual(index!, 0) XCTAssertEqual(searchList[index!], 1) } func testUpperBound() { let index = binarySearch(searchList, key: 500) XCTAssertNotNil(index) XCTAssertEqual(index!, 499) XCTAssertEqual(searchList[index!], 500) } func testOutOfLowerBound() { let index = binarySearch(searchList, key: 0) XCTAssertNil(index) } func testOutOfUpperBound() { let index = binarySearch(searchList, key: 501) XCTAssertNil(index) } } ================================================ FILE: Binary Search/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Binary Search/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3CE1C77A256003CECC7 /* BinarySearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CD1C77A256003CECC7 /* BinarySearchTests.swift */; }; 7B80C3D01C77A263003CECC7 /* BinarySearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CF1C77A263003CECC7 /* BinarySearch.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3CD1C77A256003CECC7 /* BinarySearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinarySearchTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3CF1C77A263003CECC7 /* BinarySearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearch.swift; path = ../BinarySearch.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3CF1C77A263003CECC7 /* BinarySearch.swift */, 7B80C3CD1C77A256003CECC7 /* BinarySearchTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3D01C77A263003CECC7 /* BinarySearch.swift in Sources */, 7B80C3CE1C77A256003CECC7 /* BinarySearchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Binary Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Binary Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Binary Search Tree/README.markdown ================================================ # Binary Search Tree (BST) > This topic has been tutorialized [here](https://www.raywenderlich.com/139821/swift-algorithm-club-swift-binary-search-tree-data-structure) A binary search tree is a special kind of [binary tree](../Binary%20Tree/) (a tree in which each node has at most two children) that performs insertions and deletions such that the tree is always sorted. For more information about a tree, [read this first](../Tree/). ## "Always sorted" property Here is an example of a valid binary search tree: ![A binary search tree](Images/Tree1.png) Notice how each left child is smaller than its parent node, and each right child is greater than its parent node. This is the key feature of a binary search tree. For example, `2` is smaller than `7`, so it goes on the left; `5` is greater than `2`, so it goes on the right. ## Inserting new nodes When performing an insertion, we first compare the new value to the root node. If the new value is smaller, we take the *left* branch; if greater, we take the *right* branch. We work our way down the tree this way until we find an empty spot where we can insert the new value. Suppose we want to insert the new value `9`: - We start at the root of the tree (the node with the value `7`) and compare it to the new value `9`. - `9 > 7`, so we go down the right branch and repeat the same procedure but this time on node `10`. - Because `9 < 10`, we go down the left branch. - We now arrived at a point where there are no more values to compare with. A new node for `9` is inserted at that location. Here is the tree after inserting the new value `9`: ![After adding 9](Images/Tree2.png) There is only one possible place where the new element can be inserted in the tree. Finding this place is usually quick. It takes **O(h)** time, where **h** is the height of the tree. > **Note:** The *height* of a node is the number of steps it takes to go from that node to its lowest leaf. The height of the entire tree is the distance from the root to the lowest leaf. Many of the operations on a binary search tree are expressed in terms of the tree's height. By following this simple rule -- smaller values on the left, larger values on the right -- we keep the tree sorted, so whenever we query it, we can check if a value is in the tree. ## Searching the tree To find a value in the tree, we perform the same steps as with insertion: - If the value is less than the current node, then take the left branch. - If the value is greater than the current node, take the right branch. - If the value is equal to the current node, we've found it! Like most tree operations, this is performed recursively until either we find what we are looking for or run out of nodes to look at. Here is an example for searching the value `5`: ![Searching the tree](Images/Searching.png) Searching is fast using the structure of the tree. It runs in **O(h)** time. If you have a well-balanced tree with a million nodes, it only takes about 20 steps to find anything in this tree. (The idea is very similar to [binary search](../Binary%20Search) in an array.) ## Traversing the tree Sometimes you need to look at all nodes rather than only one. There are three ways to traverse a binary tree: 1. *In-order* (or *depth-first*): first look at the left child of a node then at the node itself and finally at its right child. 2. *Pre-order*: first look at a node then its left and right children. 3. *Post-order*: first look at the left and right children and process the node itself last. Traversing the tree also happens recursively. If you traverse a binary search tree in-order, it looks at all the nodes as if they were sorted from low to high. For the example tree, it would print `1, 2, 5, 7, 9, 10`: ![Traversing the tree](Images/Traversing.png) ## Deleting nodes Removing nodes is easy. After removing a node, we replace the node with either its biggest child on the left or its smallest child on the right. That way the tree is still sorted after the removal. In the following example, 10 is removed and replaced with either 9 (Figure 2) or 11 (Figure 3). ![Deleting a node with two children](Images/DeleteTwoChildren.png) Note the replacement needs to happen when the node has at least one child. If it has no child, you just disconnect it from its parent: ![Deleting a leaf node](Images/DeleteLeaf.png) ## The code (solution 1) So much for the theory. Let's see how we can implement a binary search tree in Swift. There are different approaches you can take. First, I will show you how to make a class-based version, but we will also look at how to make one using enums. Here is an example for a `BinarySearchTree` class: ```swift public class BinarySearchTree { private(set) public var value: T private(set) public var parent: BinarySearchTree? private(set) public var left: BinarySearchTree? private(set) public var right: BinarySearchTree? public init(value: T) { self.value = value } public var isRoot: Bool { return parent == nil } public var isLeaf: Bool { return left == nil && right == nil } public var isLeftChild: Bool { return parent?.left === self } public var isRightChild: Bool { return parent?.right === self } public var hasLeftChild: Bool { return left != nil } public var hasRightChild: Bool { return right != nil } public var hasAnyChild: Bool { return hasLeftChild || hasRightChild } public var hasBothChildren: Bool { return hasLeftChild && hasRightChild } public var count: Int { return (left?.count ?? 0) + 1 + (right?.count ?? 0) } } ``` This class describes just a single node not the entire tree. It is a generic type, so the node can store any kind of data. It also has references to its `left` and `right` child nodes and a `parent` node. Here is how you can use it: ```swift let tree = BinarySearchTree(value: 7) ``` The `count` property determines how many nodes are in the subtree described by this node. This does not just count the node's immediate children but also their children and their children's children, and so on. If this particular object is the root node, then it counts how many nodes are in the entire tree. Initially, `count = 0`. > **Note:** Because `left`, `right`, and `parent` are optional, we can make good use of Swift's optional chaining (`?`) and nil-coalescing operators (`??`). You could also write this sort of thing with `if let`, but that is less concise. ### Inserting nodes A tree node by itself is useless, so here is how you would add new nodes to the tree: ```swift public func insert(value: T) { if value < self.value { if let left = left { left.insert(value: value) } else { left = BinarySearchTree(value: value) left?.parent = self } } else { if let right = right { right.insert(value: value) } else { right = BinarySearchTree(value: value) right?.parent = self } } } ``` Like so many other tree operations, insertion is easiest to implement with recursion. We compare the new value to the values of the existing nodes and decide whether to add it to the left branch or the right branch. If there is no more left or right child to look at, we create a `BinarySearchTree` object for the new node and connect it to the tree by setting its `parent` property. > **Note:** Because the whole point of a binary search tree is to have smaller nodes on the left and larger ones on the right, you should always insert elements at the root to make sure this remains a valid binary tree! To build the complete tree from the example you can do: ```swift let tree = BinarySearchTree(value: 7) tree.insert(2) tree.insert(5) tree.insert(10) tree.insert(9) tree.insert(1) ``` > **Note:** For reasons that will become clear later, you should insert the numbers in a random order. If you insert them in a sorted order, the tree will not have the right shape. For convenience, let's add an init method that calls `insert()` for all the elements in an array: ```swift public convenience init(array: [T]) { precondition(array.count > 0) self.init(value: array.first!) for v in array.dropFirst() { insert(value: v) } } ``` Now you can simply do this: ```swift let tree = BinarySearchTree(array: [7, 2, 5, 10, 9, 1]) ``` The first value in the array becomes the root of the tree. ### Debug output When working with complicated data structures, it is useful to have human-readable debug output. ```swift extension BinarySearchTree: CustomStringConvertible { public var description: String { var s = "" if let left = left { s += "(\(left.description)) <- " } s += "\(value)" if let right = right { s += " -> (\(right.description))" } return s } } ``` When you do a `print(tree)`, you should get something like this: ((1) <- 2 -> (5)) <- 7 -> ((9) <- 10) The root node is in the middle. With some imagination, you should see that this indeed corresponds to the following tree: ![The tree](Images/Tree2.png) You may be wondering what happens when you insert duplicate items? We always insert those in the right branch. Try it out! ### Searching What do we do now that we have some values in our tree? Search for them, of course! To find items quickly is the main purpose of a binary search tree. :-) Here is the implementation of `search()`: ```swift public func search(value: T) -> BinarySearchTree? { if value < self.value { return left?.search(value) } else if value > self.value { return right?.search(value) } else { return self // found it! } } ``` I hope the logic is clear: this starts at the current node (usually the root) and compares the values. If the search value is less than the node's value, we continue searching in the left branch; if the search value is greater, we dive into the right branch. If there are no more nodes to look at -- when `left` or `right` is nil -- then we return `nil` to indicate the search value is not in the tree. > **Note:** In Swift, that is conveniently done with optional chaining; when you write `left?.search(value)` it automatically returns nil if `left` is nil. There is no need to explicitly check for this with an `if` statement. Searching is a recursive process, but you can also implement it with a simple loop instead: ```swift public func search(_ value: T) -> BinarySearchTree? { var node: BinarySearchTree? = self while let n = node { if value < n.value { node = n.left } else if value > n.value { node = n.right } else { return node } } return nil } ``` Verify that you understand these two implementations are equivalent. Personally, I prefer to use iterative code over recursive code, but your opinion may differ. ;-) Here is how to test searching: ```swift tree.search(5) tree.search(2) tree.search(7) tree.search(6) // nil ``` The first three lines return the corresponding `BinaryTreeNode` object. The last line returns `nil` because there is no node with value `6`. > **Note:** If there are duplicate items in the tree, `search()` returns the "highest" node. That makes sense, because we start searching from the root downwards. ### Traversal Remember there are 3 different ways to look at all nodes in the tree? Here they are: ```swift public func traverseInOrder(process: (T) -> Void) { left?.traverseInOrder(process: process) process(value) right?.traverseInOrder(process: process) } public func traversePreOrder(process: (T) -> Void) { process(value) left?.traversePreOrder(process: process) right?.traversePreOrder(process: process) } public func traversePostOrder(process: (T) -> Void) { left?.traversePostOrder(process: process) right?.traversePostOrder(process: process) process(value) } ``` They all work the same but in different orders. Notice that all the work is done recursively. The Swift's optional chaining makes it clear that the calls to `traverseInOrder()` etc are ignored when there is no left or right child. To print out all the values of the tree sorted from low to high you can write: ```swift tree.traverseInOrder { value in print(value) } ``` This prints the following: 1 2 5 7 9 10 You can also add things like `map()` and `filter()` to the tree. For example, here is an implementation of map: ```swift public func map(formula: (T) -> T) -> [T] { var a = [T]() if let left = left { a += left.map(formula: formula) } a.append(formula(value)) if let right = right { a += right.map(formula: formula) } return a } ``` This calls the `formula` closure on each node in the tree and collects the results in an array. `map()` works by traversing the tree in-order. An extremely simple example of how to use `map()`: ```swift public func toArray() -> [T] { return map { $0 } } ``` This turns the contents of the tree back into a sorted array. Try it out in the playground: ```swift tree.toArray() // [1, 2, 5, 7, 9, 10] ``` As an exercise, see if you can implement filter and reduce. ### Deleting nodes We can make the code more readable by defining some helper functions. ```swift private func reconnectParentTo(node: BinarySearchTree?) { if let parent = parent { if isLeftChild { parent.left = node } else { parent.right = node } } node?.parent = parent } ``` Making changes to the tree involves changing a bunch of `parent` and `left` and `right` pointers. This function helps with this implementation. It takes the parent of the current node -- that is `self` -- and connects it to another node which will be one of the children of `self`. We also need a function that returns the minimum and maximum of a node: ```swift public func minimum() -> BinarySearchTree { var node = self while let next = node.left { node = next } return node } public func maximum() -> BinarySearchTree { var node = self while let next = node.right { node = next } return node } ``` The rest of the code is self-explanatory: ```swift @discardableResult public func remove() -> BinarySearchTree? { let replacement: BinarySearchTree? // Replacement for current node can be either biggest one on the left or // smallest one on the right, whichever is not nil if let right = right { replacement = right.minimum() } else if let left = left { replacement = left.maximum() } else { replacement = nil } replacement?.remove() // Place the replacement on current node's position replacement?.right = right replacement?.left = left right?.parent = replacement left?.parent = replacement reconnectParentTo(node:replacement) // The current node is no longer part of the tree, so clean it up. parent = nil left = nil right = nil return replacement } ``` ### Depth and height Recall that the height of a node is the distance to its lowest leaf. We can calculate that with the following function: ```swift public func height() -> Int { if isLeaf { return 0 } else { return 1 + max(left?.height() ?? 0, right?.height() ?? 0) } } ``` We look at the heights of the left and right branches and take the highest one. Again, this is a recursive procedure. Since this looks at all children of this node, performance is **O(n)**. > **Note:** Swift's null-coalescing operator is used as shorthand to deal with `left` or `right` pointers that are nil. You could write this with `if let`, but this is more concise. Try it out: ```swift tree.height() // 2 ``` You can also calculate the *depth* of a node, which is the distance to the root. Here is the code: ```swift public func depth() -> Int { var node = self var edges = 0 while let parent = node.parent { node = parent edges += 1 } return edges } ``` It steps upwards through the tree, following the `parent` pointers until we reach the root node (whose `parent` is nil). This takes **O(h)** time. Here is an example: ```swift if let node9 = tree.search(9) { node9.depth() // returns 2 } ``` ### Predecessor and successor The binary search tree is always "sorted" but that does not mean that consecutive numbers are actually next to each other in the tree. ![Example](Images/Tree2.png) Note that you cannot find the number that comes before `7` by just looking at its left child node. The left child is `2`, not `5`. Likewise for the number that comes after `7`. The `predecessor()` function returns the node whose value precedes the current value in sorted order: ```swift public func predecessor() -> BinarySearchTree? { if let left = left { return left.maximum() } else { var node = self while let parent = node.parent { if parent.value < value { return parent } node = parent } return nil } } ``` It is easy if we have a left subtree. In that case, the immediate predecessor is the maximum value in that subtree. You can verify in the above picture that `5` is indeed the maximum value in `7`'s left branch. If there is no left subtree, then we have to look at our parent nodes until we find a smaller value. If we want to know what the predecessor is of node `9`, we keep going up until we find the first parent with a smaller value, which is `7`. The code for `successor()` works the same way but mirrored: ```swift public func successor() -> BinarySearchTree? { if let right = right { return right.minimum() } else { var node = self while let parent = node.parent { if parent.value > value { return parent } node = parent } return nil } } ``` Both these methods run in **O(h)** time. > **Note:** There is a variation called a ["threaded" binary tree](../Threaded%20Binary%20Tree) where "unused" left and right pointers are repurposed to make direct links between predecessor and successor nodes. Very clever! ### Is the search tree valid? If you were intent on sabotage you could turn the binary search tree into an invalid tree by calling `insert()` on a node that is not the root. Here is an example: ```swift if let node1 = tree.search(1) { node1.insert(100) } ``` The value of the root node is `7`, so a node with value `100`must be in the tree's right branch. However, you are not inserting at the root but at a leaf node in the tree's left branch. So the new `100` node is in the wrong place in the tree! As a result, doing `tree.search(100)` gives nil. You can check whether a tree is a valid binary search tree with the following method: ```swift public func isBST(minValue: T, maxValue: T) -> Bool { if value < minValue || value > maxValue { return false } let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true return leftBST && rightBST } ``` This verifies the left branch contains values that are less than the current node's value, and that the right branch only contains values that are larger. Call it as follows: ```swift if let node1 = tree.search(1) { tree.isBST(minValue: Int.min, maxValue: Int.max) // true node1.insert(100) // EVIL!!! tree.search(100) // nil tree.isBST(minValue: Int.min, maxValue: Int.max) // false } ``` ## The code (solution 2) We have implemented the binary tree node as a class, but you can also use an enum. The difference is reference semantics versus value semantics. Making a change to the class-based tree will update that same instance in memory, but the enum-based tree is immutable -- any insertions or deletions will give you an entirely new copy of the tree. Which one is best, totally depends on what you want to use it for. Here is how you can make a binary search tree using an enum: ```swift public enum BinarySearchTree { case Empty case Leaf(T) indirect case Node(BinarySearchTree, T, BinarySearchTree) } ``` The enum has three cases: - `Empty` to mark the end of a branch (the class-based version used `nil` references for this). - `Leaf` for a leaf node that has no children. - `Node` for a node that has one or two children. This is marked `indirect` so that it can hold `BinarySearchTree` values. Without `indirect` you can't make recursive enums. > **Note:** The nodes in this binary tree do not have a reference to their parent node. It is not a major impediment, but it will make certain operations more cumbersome to implement. This implementation is recursive, and each case of the enum will be treated differently. For example, this is how you can calculate the number of nodes in the tree and the height of the tree: ```swift public var count: Int { switch self { case .Empty: return 0 case .Leaf: return 1 case let .Node(left, _, right): return left.count + 1 + right.count } } public var height: Int { switch self { case .Empty: return -1 case .Leaf: return 0 case let .Node(left, _, right): return 1 + max(left.height, right.height) } } ``` Inserting new nodes looks like this: ```swift public func insert(newValue: T) -> BinarySearchTree { switch self { case .Empty: return .Leaf(newValue) case .Leaf(let value): if newValue < value { return .Node(.Leaf(newValue), value, .Empty) } else { return .Node(.Empty, value, .Leaf(newValue)) } case .Node(let left, let value, let right): if newValue < value { return .Node(left.insert(newValue), value, right) } else { return .Node(left, value, right.insert(newValue)) } } } ``` Try it out in a playground: ```swift var tree = BinarySearchTree.Leaf(7) tree = tree.insert(2) tree = tree.insert(5) tree = tree.insert(10) tree = tree.insert(9) tree = tree.insert(1) ``` Notice that for each insertion, you get back a new tree object, so you need to assign the result back to the `tree` variable. Here is the all-important search function: ```swift public func search(x: T) -> BinarySearchTree? { switch self { case .Empty: return nil case .Leaf(let y): return (x == y) ? self : nil case let .Node(left, y, right): if x < y { return left.search(x) } else if y < x { return right.search(x) } else { return self } } } ``` Most of these functions have the same structure. Try it out in a playground: ```swift tree.search(10) tree.search(1) tree.search(11) // nil ``` To print the tree for debug purposes, you can use this method: ```swift extension BinarySearchTree: CustomDebugStringConvertible { public var debugDescription: String { switch self { case .Empty: return "." case .Leaf(let value): return "\(value)" case .Node(let left, let value, let right): return "(\(left.debugDescription) <- \(value) -> \(right.debugDescription))" } } } ``` When you do `print(tree)`, it will look like this: ((1 <- 2 -> 5) <- 7 -> (9 <- 10 -> .)) The root node is in the middle, and a dot means there is no child at that position. ## When the tree becomes unbalanced... A binary search tree is *balanced* when its left and right subtrees contain the same number of nodes. In that case, the height of the tree is *log(n)*, where *n* is the number of nodes. That is the ideal situation. If one branch is significantly longer than the other, searching becomes very slow. We end up checking more values than we need. In the worst case, the height of the tree can become *n*. Such a tree acts like a [linked list](../Linked%20List/) than a binary search tree, with performance degrading to **O(n)**. Not good! One way to make the binary search tree balanced is to insert the nodes in a totally random order. On average that should balance out the tree well, but it not guaranteed, nor is it always practical. The other solution is to use a *self-balancing* binary tree. This type of data structure adjusts the tree to keep it balanced after you insert or delete nodes. To see examples, check [AVL tree](../AVL%20Tree) and [red-black tree](../Red-Black%20Tree). ## See also [Binary Search Tree on Wikipedia](https://en.wikipedia.org/wiki/Binary_search_tree) *Written for the Swift Algorithm Club by [Nicolas Ameghino](http://www.github.com/nameghino) and Matthijs Hollemans* ================================================ FILE: Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play let tree = BinarySearchTree(value: 7) tree.insert(value: 2) tree.insert(value: 5) tree.insert(value: 10) tree.insert(value: 9) tree.insert(value: 1) let toDelete = tree.search(value: 1) toDelete?.remove() tree let tree2 = BinarySearchTree(array: [7, 2, 5, 10, 9, 1]) tree.search(value: 5) tree.search(value: 2) tree.search(value: 7) tree.search(value: 6) tree.traverseInOrder { value in print(value) } tree.toArray() tree.minimum() tree.maximum() if let node2 = tree.search(value: 2) { node2.remove() node2 print(tree) } tree.height() tree.predecessor() tree.successor() if let node10 = tree.search(value: 10) { node10.depth() // 1 node10.height() // 1 node10.predecessor() node10.successor() // nil } if let node9 = tree.search(value: 9) { node9.depth() // 2 node9.height() // 0 node9.predecessor() node9.successor() } if let node1 = tree.search(value: 1) { // This makes it an invalid binary search tree because 100 is greater // than the root, 7, and so must be in the right branch not in the left. tree.isBST(minValue: Int.min, maxValue: Int.max) // true node1.insert(value: 100) tree.search(value: 100) // nil tree.isBST(minValue: Int.min, maxValue: Int.max) // false } ================================================ FILE: Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift ================================================ /* A binary search tree. Each node stores a value and two children. The left child contains a smaller value; the right a larger (or equal) value. This tree allows duplicate elements. This tree does not automatically balance itself. To make sure it is balanced, you should insert new values in randomized order, not in sorted order. */ public class BinarySearchTree { fileprivate(set) public var value: T fileprivate(set) public var parent: BinarySearchTree? fileprivate(set) public var left: BinarySearchTree? fileprivate(set) public var right: BinarySearchTree? public init(value: T) { self.value = value } public convenience init(array: [T]) { precondition(array.count > 0) self.init(value: array.first!) for v in array.dropFirst() { insert(value: v) } } public var isRoot: Bool { return parent == nil } public var isLeaf: Bool { return left == nil && right == nil } public var isLeftChild: Bool { return parent?.left === self } public var isRightChild: Bool { return parent?.right === self } public var hasLeftChild: Bool { return left != nil } public var hasRightChild: Bool { return right != nil } public var hasAnyChild: Bool { return hasLeftChild || hasRightChild } public var hasBothChildren: Bool { return hasLeftChild && hasRightChild } /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { return (left?.count ?? 0) + 1 + (right?.count ?? 0) } } // MARK: - Adding items extension BinarySearchTree { /* Inserts a new element into the tree. You should only insert elements at the root, to make to sure this remains a valid binary tree! Performance: runs in O(h) time, where h is the height of the tree. */ public func insert(value: T) { if value < self.value { if let left = left { left.insert(value: value) } else { left = BinarySearchTree(value: value) left?.parent = self } } else { if let right = right { right.insert(value: value) } else { right = BinarySearchTree(value: value) right?.parent = self } } } } // MARK: - Deleting items extension BinarySearchTree { /* Deletes a node from the tree. Returns the node that has replaced this removed one (or nil if this was a leaf node). That is primarily useful for when you delete the root node, in which case the tree gets a new root. Performance: runs in O(h) time, where h is the height of the tree. */ @discardableResult public func remove() -> BinarySearchTree? { let replacement: BinarySearchTree? // Replacement for current node can be either biggest one on the left or // smallest one on the right, whichever is not nil if let right = right { replacement = right.minimum() } else if let left = left { replacement = left.maximum() } else { replacement = nil } replacement?.remove() // Place the replacement on current node's position replacement?.right = right replacement?.left = left right?.parent = replacement left?.parent = replacement reconnectParentTo(node:replacement) // The current node is no longer part of the tree, so clean it up. parent = nil left = nil right = nil return replacement } private func reconnectParentTo(node: BinarySearchTree?) { if let parent = parent { if isLeftChild { parent.left = node } else { parent.right = node } } node?.parent = parent } } // MARK: - Searching extension BinarySearchTree { /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ public func search(value: T) -> BinarySearchTree? { var node: BinarySearchTree? = self while let n = node { if value < n.value { node = n.left } else if value > n.value { node = n.right } else { return node } } return nil } /* // Recursive version of search public func search(value: T) -> BinarySearchTree? { if value < self.value { return left?.search(value) } else if value > self.value { return right?.search(value) } else { return self // found it! } } */ public func contains(value: T) -> Bool { return search(value: value) != nil } /* Returns the leftmost descendent. O(h) time. */ public func minimum() -> BinarySearchTree { var node = self while let next = node.left { node = next } return node } /* Returns the rightmost descendent. O(h) time. */ public func maximum() -> BinarySearchTree { var node = self while let next = node.right { node = next } return node } /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. */ public func depth() -> Int { var node = self var edges = 0 while let parent = node.parent { node = parent edges += 1 } return edges } /* Calculates the height of this node, i.e. the distance to the lowest leaf. Since this looks at all children of this node, performance is O(n). */ public func height() -> Int { if isLeaf { return 0 } else { return 1 + max(left?.height() ?? 0, right?.height() ?? 0) } } /* Finds the node whose value precedes our value in sorted order. */ public func predecessor() -> BinarySearchTree? { if let left = left { return left.maximum() } else { var node = self while let parent = node.parent { if parent.value < value { return parent } node = parent } return nil } } /* Finds the node whose value succeeds our value in sorted order. */ public func successor() -> BinarySearchTree? { if let right = right { return right.minimum() } else { var node = self while let parent = node.parent { if parent.value > value { return parent } node = parent } return nil } } } // MARK: - Traversal extension BinarySearchTree { public func traverseInOrder(process: (T) -> Void) { left?.traverseInOrder(process: process) process(value) right?.traverseInOrder(process: process) } public func traversePreOrder(process: (T) -> Void) { process(value) left?.traversePreOrder(process: process) right?.traversePreOrder(process: process) } public func traversePostOrder(process: (T) -> Void) { left?.traversePostOrder(process: process) right?.traversePostOrder(process: process) process(value) } /* Performs an in-order traversal and collects the results in an array. */ public func map(formula: (T) -> T) -> [T] { var a = [T]() if let left = left { a += left.map(formula: formula) } a.append(formula(value)) if let right = right { a += right.map(formula: formula) } return a } } /* Is this binary tree a valid binary search tree? */ extension BinarySearchTree { public func isBST(minValue: T, maxValue: T) -> Bool { if value < minValue || value > maxValue { return false } let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true return leftBST && rightBST } } // MARK: - Debugging extension BinarySearchTree: CustomStringConvertible { public var description: String { var s = "" if let left = left { s += "(\(left.description)) <- " } s += "\(value)" if let right = right { s += " -> (\(right.description))" } return s } public func toArray() -> [T] { return map { $0 } } } //extension BinarySearchTree: CustomDebugStringConvertible { // public var debugDescription: String { // var s = "" // if let left = left { // s += "(\(left.description)) <- " // } // s += "\(value)" // if let right = right { // s += " -> (\(right.description))" // } // return s // } //} ================================================ FILE: Binary Search Tree/Solution 1/BinarySearchTree.playground/contents.xcplayground ================================================ ================================================ FILE: Binary Search Tree/Solution 1/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Binary Search Tree/Solution 1/BinarySearchTree.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift ================================================ import Foundation import XCTest class BinarySearchTreeTest: XCTestCase { func testRootNode() { let tree = BinarySearchTree(value: 8) XCTAssertEqual(tree.count, 1) XCTAssertEqual(tree.minimum().value, 8) XCTAssertEqual(tree.maximum().value, 8) XCTAssertEqual(tree.height(), 0) XCTAssertEqual(tree.depth(), 0) XCTAssertEqual(tree.toArray(), [8]) } func testCreateFromArray() { let tree = BinarySearchTree(array: [8, 5, 10, 3, 12, 9, 6, 16]) XCTAssertEqual(tree.count, 8) XCTAssertEqual(tree.toArray(), [3, 5, 6, 8, 9, 10, 12, 16]) XCTAssertEqual(tree.search(value: 9)!.value, 9) XCTAssertNil(tree.search(value: 99)) XCTAssertEqual(tree.minimum().value, 3) XCTAssertEqual(tree.maximum().value, 16) XCTAssertEqual(tree.height(), 3) XCTAssertEqual(tree.depth(), 0) let node1 = tree.search(value: 16) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 3) let node2 = tree.search(value: 12) XCTAssertNotNil(node2) XCTAssertEqual(node2!.height(), 1) XCTAssertEqual(node2!.depth(), 2) let node3 = tree.search(value: 10) XCTAssertNotNil(node3) XCTAssertEqual(node3!.height(), 2) XCTAssertEqual(node3!.depth(), 1) } func testInsert() { let tree = BinarySearchTree(value: 8) tree.insert(value: 5) XCTAssertEqual(tree.count, 2) XCTAssertEqual(tree.height(), 1) XCTAssertEqual(tree.depth(), 0) let node1 = tree.search(value: 5) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 1) tree.insert(value: 10) XCTAssertEqual(tree.count, 3) XCTAssertEqual(tree.height(), 1) XCTAssertEqual(tree.depth(), 0) let node2 = tree.search(value: 10) XCTAssertNotNil(node2) XCTAssertEqual(node2!.height(), 0) XCTAssertEqual(node2!.depth(), 1) tree.insert(value: 3) XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.height(), 2) XCTAssertEqual(tree.depth(), 0) let node3 = tree.search(value: 3) XCTAssertNotNil(node3) XCTAssertEqual(node3!.height(), 0) XCTAssertEqual(node3!.depth(), 2) XCTAssertEqual(node1!.height(), 1) XCTAssertEqual(node1!.depth(), 1) XCTAssertEqual(tree.minimum().value, 3) XCTAssertEqual(tree.maximum().value, 10) XCTAssertEqual(tree.toArray(), [3, 5, 8, 10]) } func testInsertDuplicates() { let tree = BinarySearchTree(array: [8, 5, 10]) tree.insert(value: 8) tree.insert(value: 5) tree.insert(value: 10) XCTAssertEqual(tree.count, 6) XCTAssertEqual(tree.toArray(), [5, 5, 8, 8, 10, 10]) } func testTraversing() { let tree = BinarySearchTree(array: [8, 5, 10, 3, 12, 9, 6, 16]) var inOrder = [Int]() tree.traverseInOrder { inOrder.append($0) } XCTAssertEqual(inOrder, [3, 5, 6, 8, 9, 10, 12, 16]) var preOrder = [Int]() tree.traversePreOrder { preOrder.append($0) } XCTAssertEqual(preOrder, [8, 5, 3, 6, 10, 9, 12, 16]) var postOrder = [Int]() tree.traversePostOrder { postOrder.append($0) } XCTAssertEqual(postOrder, [3, 6, 5, 9, 16, 12, 10, 8]) } func testInsertSorted() { let tree = BinarySearchTree(array: [8, 5, 10, 3, 12, 9, 6, 16].sorted(by: <)) XCTAssertEqual(tree.count, 8) XCTAssertEqual(tree.toArray(), [3, 5, 6, 8, 9, 10, 12, 16]) XCTAssertEqual(tree.minimum().value, 3) XCTAssertEqual(tree.maximum().value, 16) XCTAssertEqual(tree.height(), 7) XCTAssertEqual(tree.depth(), 0) let node1 = tree.search(value: 16) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 7) } func testRemoveLeaf() { let tree = BinarySearchTree(array: [8, 5, 10, 4]) let node10 = tree.search(value: 10)! XCTAssertNil(node10.left) XCTAssertNil(node10.right) XCTAssertTrue(tree.right === node10) let node5 = tree.search(value: 5)! XCTAssertTrue(tree.left === node5) let node4 = tree.search(value: 4)! XCTAssertTrue(node5.left === node4) XCTAssertNil(node5.right) let replacement1 = node4.remove() XCTAssertNil(node5.left) XCTAssertNil(replacement1) let replacement2 = node5.remove() XCTAssertNil(tree.left) XCTAssertNil(replacement2) let replacement3 = node10.remove() XCTAssertNil(tree.right) XCTAssertNil(replacement3) XCTAssertEqual(tree.count, 1) XCTAssertEqual(tree.toArray(), [8]) } func testRemoveOneChildLeft() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9]) let node4 = tree.search(value: 4)! let node5 = tree.search(value: 5)! XCTAssertTrue(node5.left === node4) XCTAssertTrue(node5 === node4.parent) node5.remove() XCTAssertTrue(tree.left === node4) XCTAssertTrue(tree === node4.parent) XCTAssertNil(node4.left) XCTAssertNil(node4.right) XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.toArray(), [4, 8, 9, 10]) let node9 = tree.search(value: 9)! let node10 = tree.search(value: 10)! XCTAssertTrue(node10.left === node9) XCTAssertTrue(node10 === node9.parent) node10.remove() XCTAssertTrue(tree.right === node9) XCTAssertTrue(tree === node9.parent) XCTAssertNil(node9.left) XCTAssertNil(node9.right) XCTAssertEqual(tree.count, 3) XCTAssertEqual(tree.toArray(), [4, 8, 9]) } func testRemoveOneChildRight() { let tree = BinarySearchTree(array: [8, 5, 10, 6, 11]) let node6 = tree.search(value: 6)! let node5 = tree.search(value: 5)! XCTAssertTrue(node5.right === node6) XCTAssertTrue(node5 === node6.parent) node5.remove() XCTAssertTrue(tree.left === node6) XCTAssertTrue(tree === node6.parent) XCTAssertNil(node6.left) XCTAssertNil(node6.right) XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.toArray(), [6, 8, 10, 11]) let node11 = tree.search(value: 11)! let node10 = tree.search(value: 10)! XCTAssertTrue(node10.right === node11) XCTAssertTrue(node10 === node11.parent) node10.remove() XCTAssertTrue(tree.right === node11) XCTAssertTrue(tree === node11.parent) XCTAssertNil(node11.left) XCTAssertNil(node11.right) XCTAssertEqual(tree.count, 3) XCTAssertEqual(tree.toArray(), [6, 8, 11]) } func testRemoveTwoChildrenSimple() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 6, 9, 11]) let node4 = tree.search(value: 4)! let node5 = tree.search(value: 5)! let node6 = tree.search(value: 6)! XCTAssertTrue(node5.left === node4) XCTAssertTrue(node5.right === node6) XCTAssertTrue(node5 === node4.parent) XCTAssertTrue(node5 === node6.parent) let replacement1 = node5.remove() XCTAssertTrue(replacement1 === node6) XCTAssertTrue(tree.left === node6) XCTAssertTrue(tree === node6.parent) XCTAssertTrue(node6.left === node4) XCTAssertTrue(node6 === node4.parent) XCTAssertNil(node5.left) XCTAssertNil(node5.right) XCTAssertNil(node5.parent) XCTAssertNil(node4.left) XCTAssertNil(node4.right) XCTAssertNotNil(node4.parent) XCTAssertEqual(tree.count, 6) XCTAssertEqual(tree.toArray(), [4, 6, 8, 9, 10, 11]) let node9 = tree.search(value: 9)! let node10 = tree.search(value: 10)! let node11 = tree.search(value: 11)! XCTAssertTrue(node10.left === node9) XCTAssertTrue(node10.right === node11) XCTAssertTrue(node10 === node9.parent) XCTAssertTrue(node10 === node11.parent) let replacement2 = node10.remove() XCTAssertTrue(replacement2 === node11) XCTAssertTrue(tree.right === node11) XCTAssertTrue(tree === node11.parent) XCTAssertTrue(node11.left === node9) XCTAssertTrue(node11 === node9.parent) XCTAssertNil(node10.left) XCTAssertNil(node10.right) XCTAssertNil(node10.parent) XCTAssertNil(node9.left) XCTAssertNil(node9.right) XCTAssertNotNil(node9.parent) XCTAssertEqual(tree.count, 5) XCTAssertEqual(tree.toArray(), [4, 6, 8, 9, 11]) } func testRemoveTwoChildrenComplex() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9, 20, 11, 15, 13]) let node9 = tree.search(value: 9)! let node10 = tree.search(value: 10)! let node11 = tree.search(value: 11)! let node13 = tree.search(value: 13)! let node15 = tree.search(value: 15)! let node20 = tree.search(value: 20)! XCTAssertTrue(node10.left === node9) XCTAssertTrue(node10 === node9.parent) XCTAssertTrue(node10.right === node20) XCTAssertTrue(node10 === node20.parent) XCTAssertTrue(node20.left === node11) XCTAssertTrue(node20 === node11.parent) XCTAssertTrue(node11.right === node15) XCTAssertTrue(node11 === node15.parent) let replacement = node10.remove() XCTAssertTrue(replacement === node11) XCTAssertTrue(tree.right === node11) XCTAssertTrue(tree === node11.parent) XCTAssertTrue(node11.left === node9) XCTAssertTrue(node11 === node9.parent) XCTAssertTrue(node11.right === node20) XCTAssertTrue(node11 === node20.parent) XCTAssertTrue(node20.left === node13) XCTAssertTrue(node20 === node13.parent) XCTAssertNil(node20.right) XCTAssertNil(node10.left) XCTAssertNil(node10.right) XCTAssertNil(node10.parent) XCTAssertEqual(tree.count, 8) XCTAssertEqual(tree.toArray(), [4, 5, 8, 9, 11, 13, 15, 20]) } func testRemoveRoot() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9, 20, 11, 15, 13]) let node9 = tree.search(value: 9)! let newRoot = tree.remove() XCTAssertTrue(newRoot === node9) XCTAssertEqual(newRoot!.value, 9) XCTAssertEqual(newRoot!.count, 8) XCTAssertEqual(newRoot!.toArray(), [4, 5, 9, 10, 11, 13, 15, 20]) // The old root is a subtree of a single element. XCTAssertEqual(tree.value, 8) XCTAssertEqual(tree.count, 1) XCTAssertEqual(tree.toArray(), [8]) } func testPredecessor() { let tree = BinarySearchTree(array: [3, 1, 2, 5, 4]) let node = tree.search(value: 5) XCTAssertEqual(node!.value, 5) XCTAssertEqual(node!.predecessor()!.value, 4) XCTAssertEqual(node!.predecessor()!.predecessor()!.value, 3) XCTAssertEqual(node!.predecessor()!.predecessor()!.predecessor()!.value, 2) XCTAssertEqual(node!.predecessor()!.predecessor()!.predecessor()!.predecessor()!.value, 1) XCTAssertNil(node!.predecessor()!.predecessor()!.predecessor()!.predecessor()!.predecessor()) } func testSuccessor() { let tree = BinarySearchTree(array: [3, 1, 2, 5, 4]) let node = tree.search(value: 1) XCTAssertEqual(node!.value, 1) XCTAssertEqual(node!.successor()!.value, 2) XCTAssertEqual(node!.successor()!.successor()!.value, 3) XCTAssertEqual(node!.successor()!.successor()!.successor()!.value, 4) XCTAssertEqual(node!.successor()!.successor()!.successor()!.successor()!.value, 5) XCTAssertNil(node!.successor()!.successor()!.successor()!.successor()!.successor()) } } ================================================ FILE: Binary Search Tree/Solution 1/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3DA1C77A323003CECC7 /* BinarySearchTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */; }; 9E5A58B91E304C3100DAB3BB /* BinarySearchTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BinarySearchTreeTests.swift; sourceTree = SOURCE_ROOT; }; 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchTree.swift; path = ../BinarySearchTree.playground/Sources/BinarySearchTree.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */, 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3DA1C77A323003CECC7 /* BinarySearchTreeTests.swift in Sources */, 9E5A58B91E304C3100DAB3BB /* BinarySearchTree.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // Each time you insert something, you get back a completely new tree. var tree = BinarySearchTree.leaf(7) tree = tree.insert(newValue: 2) tree = tree.insert(newValue: 5) tree = tree.insert(newValue: 10) tree = tree.insert(newValue: 9) tree = tree.insert(newValue: 1) print(tree) tree.search(x: 10) tree.search(x: 1) tree.search(x: 11) ================================================ FILE: Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift ================================================ /* Binary search tree using value types The tree is immutable. Any insertions or deletions will create a new tree. */ public enum BinarySearchTree { case empty case leaf(T) indirect case node(BinarySearchTree, T, BinarySearchTree) /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { switch self { case .empty: return 0 case .leaf: return 1 case let .node(left, _, right): return left.count + 1 + right.count } } /* Distance of this node to its lowest leaf. Performance: O(n). */ public var height: Int { switch self { case .empty: return 0 case .leaf: return 1 case let .node(left, _, right): return 1 + max(left.height, right.height) } } /* Inserts a new element into the tree. Performance: runs in O(h) time, where h is the height of the tree. */ public func insert(newValue: T) -> BinarySearchTree { switch self { case .empty: return .leaf(newValue) case .leaf(let value): if newValue < value { return .node(.leaf(newValue), value, .empty) } else { return .node(.empty, value, .leaf(newValue)) } case .node(let left, let value, let right): if newValue < value { return .node(left.insert(newValue: newValue), value, right) } else { return .node(left, value, right.insert(newValue: newValue)) } } } /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ public func search(x: T) -> BinarySearchTree? { switch self { case .empty: return nil case .leaf(let y): return (x == y) ? self : nil case let .node(left, y, right): if x < y { return left.search(x: x) } else if y < x { return right.search(x: x) } else { return self } } } public func contains(x: T) -> Bool { return search(x: x) != nil } /* Returns the leftmost descendent. O(h) time. */ public func minimum() -> BinarySearchTree { var node = self var prev = node while case let .node(next, _, _) = node { prev = node node = next } if case .leaf = node { return node } return prev } /* Returns the rightmost descendent. O(h) time. */ public func maximum() -> BinarySearchTree { var node = self var prev = node while case let .node(_, _, next) = node { prev = node node = next } if case .leaf = node { return node } return prev } } extension BinarySearchTree: CustomDebugStringConvertible { public var debugDescription: String { switch self { case .empty: return "." case .leaf(let value): return "\(value)" case .node(let left, let value, let right): return "(\(left.debugDescription) <- \(value) -> \(right.debugDescription))" } } } ================================================ FILE: Binary Search Tree/Solution 2/BinarySearchTree.playground/contents.xcplayground ================================================ ================================================ FILE: Binary Search Tree/Solution 2/BinarySearchTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Binary Search Tree/Solution 2/BinarySearchTree.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Binary Search Tree/Solution 2/BinarySearchTree.swift ================================================ /* Binary search tree using value types The tree is immutable. Any insertions or deletions will create a new tree. */ public enum BinarySearchTree { case empty case leaf(T) indirect case node(BinarySearchTree, T, BinarySearchTree) /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { switch self { case .empty: return 0 case .leaf: return 1 case let .node(left, _, right): return left.count + 1 + right.count } } /* Distance of this node to its lowest leaf. Performance: O(n). */ public var height: Int { switch self { case .empty: return -1 case .leaf: return 0 case let .node(left, _, right): return 1 + max(left.height, right.height) } } /* Inserts a new element into the tree. Performance: runs in O(h) time, where h is the height of the tree. */ public func insert(newValue: T) -> BinarySearchTree { switch self { case .empty: return .leaf(newValue) case .leaf(let value): if newValue < value { return .node(.leaf(newValue), value, .empty) } else { return .node(.empty, value, .leaf(newValue)) } case .node(let left, let value, let right): if newValue < value { return .node(left.insert(newValue), value, right) } else { return .node(left, value, right.insert(newValue)) } } } /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ public func search(x: T) -> BinarySearchTree? { switch self { case .empty: return nil case .leaf(let y): return (x == y) ? self : nil case let .node(left, y, right): if x < y { return left.search(x) } else if y < x { return right.search(x) } else { return self } } } public func contains(x: T) -> Bool { return search(x) != nil } /* Returns the leftmost descendent. O(h) time. */ public func minimum() -> BinarySearchTree { var node = self var prev = node while case let .node(next, _, _) = node { prev = node node = next } if case .leaf = node { return node } return prev } /* Returns the rightmost descendent. O(h) time. */ public func maximum() -> BinarySearchTree { var node = self var prev = node while case let .node(_, _, next) = node { prev = node node = next } if case .leaf = node { return node } return prev } } extension BinarySearchTree: CustomDebugStringConvertible { public var debugDescription: String { switch self { case .empty: return "." case .leaf(let value): return "\(value)" case .node(let left, let value, let right): return "(\(left.debugDescription) <- \(value) -> \(right.debugDescription))" } } } ================================================ FILE: Binary Tree/BinaryTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play public indirect enum BinaryTree { case node(BinaryTree, T, BinaryTree) case empty public var count: Int { switch self { case let .node(left, _, right): return left.count + 1 + right.count case .empty: return 0 } } } extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } } } // leaf nodes let node5 = BinaryTree.node(.empty, "5", .empty) let nodeA = BinaryTree.node(.empty, "a", .empty) let node10 = BinaryTree.node(.empty, "10", .empty) let node4 = BinaryTree.node(.empty, "4", .empty) let node3 = BinaryTree.node(.empty, "3", .empty) let nodeB = BinaryTree.node(.empty, "b", .empty) // intermediate nodes on the left let aMinus10 = BinaryTree.node(nodeA, "-", node10) let timesLeft = BinaryTree.node(node5, "*", aMinus10) // intermediate nodes on the right let minus4 = BinaryTree.node(.empty, "-", node4) let divide3andB = BinaryTree.node(node3, "/", nodeB) let timesRight = BinaryTree.node(minus4, "*", divide3andB) // root node let tree = BinaryTree.node(timesLeft, "+", timesRight) print(tree) tree.count // 12 extension BinaryTree { public func traverseInOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { left.traverseInOrder(process: process) process(value) right.traverseInOrder(process: process) } } public func traversePreOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process: process) right.traversePreOrder(process: process) } } public func traversePostOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { left.traversePostOrder(process: process) right.traversePostOrder(process: process) process(value) } } } //tree.traverseInOrder { s in print(s) } //tree.traversePreOrder { s in print(s) } tree.traversePostOrder { s in print(s) } ================================================ FILE: Binary Tree/BinaryTree.playground/contents.xcplayground ================================================ ================================================ FILE: Binary Tree/BinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Binary Tree/BinaryTree.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Binary Tree/BinaryTree.swift ================================================ /* A general-purpose binary tree. Nodes don't have a reference to their parent. */ public indirect enum BinaryTree { case node(BinaryTree, T, BinaryTree) case empty public var count: Int { switch self { case let .node(left, _, right): return left.count + 1 + right.count case .empty: return 0 } } } extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } } } extension BinaryTree { public func traverseInOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { left.traverseInOrder(process: process) process(value) right.traverseInOrder(process: process) } } public func traversePreOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process: process) right.traversePreOrder(process: process) } } public func traversePostOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { left.traversePostOrder(process: process) right.traversePostOrder(process: process) process(value) } } } extension BinaryTree { func invert() -> BinaryTree { if case let .node(left, value, right) = self { return .node(right.invert(), value, left.invert()) } else { return .empty } } } ================================================ FILE: Binary Tree/README.markdown ================================================ # Binary Tree A binary tree is a [tree](../Tree/) where each node has 0, 1, or 2 children. This is a binary tree: ![A binary tree](Images/BinaryTree.png) The child nodes are usually called the *left* child and the *right* child. If a node doesn't have any children, it's called a *leaf* node. The *root* is the node at the very top of the tree (programmers like their trees upside down). Often nodes will have a link back to their parent but this is not strictly necessary. Binary trees are often used as [binary search trees](../Binary%20Search%20Tree/). In that case, the nodes must be in a specific order (smaller values on the left, larger values on the right). But this is not a requirement for all binary trees. For example, here is a binary tree that represents a sequence of arithmetical operations, `(5 * (a - 10)) + (-4 * (3 / b))`: ![A binary tree](Images/Operations.png) ## The code Here's how you could implement a general-purpose binary tree in Swift: ```swift public indirect enum BinaryTree { case node(BinaryTree, T, BinaryTree) case empty } ``` As an example of how to use this, let's build that tree of arithmetic operations: ```swift // leaf nodes let node5 = BinaryTree.node(.empty, "5", .empty) let nodeA = BinaryTree.node(.empty, "a", .empty) let node10 = BinaryTree.node(.empty, "10", .empty) let node4 = BinaryTree.node(.empty, "4", .empty) let node3 = BinaryTree.node(.empty, "3", .empty) let nodeB = BinaryTree.node(.empty, "b", .empty) // intermediate nodes on the left let Aminus10 = BinaryTree.node(nodeA, "-", node10) let timesLeft = BinaryTree.node(node5, "*", Aminus10) // intermediate nodes on the right let minus4 = BinaryTree.node(.empty, "-", node4) let divide3andB = BinaryTree.node(node3, "/", nodeB) let timesRight = BinaryTree.node(minus4, "*", divide3andB) // root node let tree = BinaryTree.node(timesLeft, "+", timesRight) ``` You need to build up the tree in reverse, starting with the leaf nodes and working your way up to the top. It will be useful to add a `description` method so you can print the tree: ```swift extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } } } ``` If you `print(tree)` you should see something like this: value: +, left = [value: *, left = [value: 5, left = [], right = []], right = [value: -, left = [value: a, left = [], right = []], right = [value: 10, left = [], right = []]]], right = [value: *, left = [value: -, left = [], right = [value: 4, left = [], right = []]], right = [value: /, left = [value: 3, left = [], right = []], right = [value: b, left = [], right = []]]] With a bit of imagination, you can see the tree structure. ;-) It helps if you indent it: value: +, left = [value: *, left = [value: 5, left = [], right = []], right = [value: -, left = [value: a, left = [], right = []], right = [value: 10, left = [], right = []]]], right = [value: *, left = [value: -, left = [], right = [value: 4, left = [], right = []]], right = [value: /, left = [value: 3, left = [], right = []], right = [value: b, left = [], right = []]]] Another useful method is counting the number of nodes in the tree: ```swift public var count: Int { switch self { case let .node(left, _, right): return left.count + 1 + right.count case .empty: return 0 } } ``` On the tree from the example, `tree.count` should be 12. Something you often need to do with trees is traverse them, i.e. look at all the nodes in some order. There are three ways to traverse a binary tree: 1. *In-order* (or *depth-first*): first look at the left child of a node, then at the node itself, and finally at its right child. 2. *Pre-order*: first look at a node, then at its left and right children. 3. *Post-order*: first look at the left and right children and process the node itself last. Here is how you'd implement that: ```swift public func traverseInOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { left.traverseInOrder(process: process) process(value) right.traverseInOrder(process: process) } } public func traversePreOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process: process) right.traversePreOrder(process: process) } } public func traversePostOrder(process: (T) -> Void) { if case let .node(left, value, right) = self { left.traversePostOrder(process: process) right.traversePostOrder(process: process) process(value) } } ``` As is common when working with tree structures, these functions call themselves recursively. For example, if you traverse the tree of arithmetic operations in post-order, you'll see the values in this order: 5 a 10 - * 4 - 3 b / * + The leaves appear first. The root node appears last. You can use a stack machine to evaluate these expressions, something like the following pseudocode: ```swift tree.traversePostOrder { s in switch s { case this is a numeric literal, such as 5: push it onto the stack case this is a variable name, such as a: look up the value of a and push it onto the stack case this is an operator, such as *: pop the two top-most items off the stack, multiply them, and push the result back onto the stack } the result is in the top-most item on the stack } ``` *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Bit Set/BitSet.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // Create a bit set that stores 140 bits var bits = BitSet(size: 140) // Initially, it looks like all zeros: // 0000000000000000000000000000000000000000000000000000000000000000 // 0000000000000000000000000000000000000000000000000000000000000000 // 0000000000000000000000000000000000000000000000000000000000000000 print(bits) bits[2] = true bits[99] = true bits[128] = true bits.cardinality // 3 // 0010000000000000000000000000000000000000000000000000000000000000 // 0000000000000000000000000000000000010000000000000000000000000000 // 1000000000000000000000000000000000000000000000000000000000000000 print(bits) bits.setAll() bits.cardinality // 140 // 1111111111111111111111111111111111111111111111111111111111111111 // 1111111111111111111111111111111111111111111111111111111111111111 // 1111111111110000000000000000000000000000000000000000000000000000 print(bits) print("") // Bitwise operations var a = BitSet(size: 4) var b = BitSet(size: 8) a.setAll() a.cardinality // 4 a[1] = false a[2] = false a[3] = false b[2] = true b[6] = true b[7] = true print(a) // 1000000000000000000000000000000000000000000000000000000000000000 print(b) // 0010001100000000000000000000000000000000000000000000000000000000 let c = a | b c.size // 8 print(c) // 1010001100000000000000000000000000000000000000000000000000000000 a.cardinality // 1 b.cardinality // 3 c.cardinality // 4 print("") print(~a) // 0111000000000000000000000000000000000000000000000000000000000000 print(~b) // 1101110000000000000000000000000000000000000000000000000000000000 print(~c) // 0101110000000000000000000000000000000000000000000000000000000000 (~a).cardinality // 3 (~b).cardinality // 5 (~c).cardinality // 4 var z = BitSet(size: 66) z.all0() // true z.all1() // false z[45] = true z.any1() // true z.all0() // false z[45] = false z.any1() // false z.all0() // true z[65] = true z.any1() // true z.setAll() z.all1() // true z[65] = false z.all1() // false //var bigBits = BitSet(size: 10000) //print(bigBits) var smallBitSet = BitSet(size: 16) smallBitSet[5] = true smallBitSet[10] = true print(smallBitSet >> 3) print(smallBitSet << 6) // one bit shifts off the end var bigBitSet = BitSet( size: 120 ) bigBitSet[1] = true bigBitSet[3] = true bigBitSet[7] = true bigBitSet[32] = true bigBitSet[55] = true bigBitSet[64] = true bigBitSet[80] = true print(bigBitSet) print(bigBitSet << 32) print(bigBitSet << 64) print(bigBitSet >> 32) print(bigBitSet >> 64) ================================================ FILE: Bit Set/BitSet.playground/Sources/BitSet.swift ================================================ /* A fixed-size sequence of n bits. Bits have indices 0 to n-1. */ public struct BitSet { /* How many bits this object can hold. */ private(set) public var size: Int /* We store the bits in a list of unsigned 64-bit integers. The first entry, `words[0]`, is the least significant word. */ fileprivate let N = 64 public typealias Word = UInt64 fileprivate(set) public var words: [Word] private let allOnes = ~Word() /* Creates a bit set that can hold `size` bits. All bits are initially 0. */ public init(size: Int) { precondition(size > 0) self.size = size // Round up the count to the next multiple of 64. let n = (size + (N-1)) / N words = [Word](repeating: 0, count: n) } /* Converts a bit index into an array index and a mask inside the word. */ private func indexOf(_ i: Int) -> (Int, Word) { precondition(i >= 0) precondition(i < size) let o = i / N let m = Word(i - o*N) return (o, 1 << m) } /* Returns a mask that has 1s for all bits that are in the last word. */ private func lastWordMask() -> Word { let diff = words.count*N - size if diff > 0 { // Set the highest bit that's still valid. let mask = 1 << Word(63 - diff) // Subtract 1 to turn it into a mask, and add the high bit back in. return (Word)(mask | (mask - 1)) } else { return allOnes } } /* If the size is not a multiple of N, then we have to clear out the bits that we're not using, or bitwise operations between two differently sized BitSets will go wrong. */ fileprivate mutating func clearUnusedBits() { words[words.count - 1] &= lastWordMask() } /* So you can write bitset[99] = ... */ public subscript(i: Int) -> Bool { get { return isSet(i) } set { if newValue { set(i) } else { clear(i) } } } /* Sets the bit at the specified index to 1. */ public mutating func set(_ i: Int) { let (j, m) = indexOf(i) words[j] |= m } /* Sets all the bits to 1. */ public mutating func setAll() { for i in 0.. Bool { let (j, m) = indexOf(i) words[j] ^= m return (words[j] & m) != 0 } /* Determines whether the bit at the specific index is 1 (true) or 0 (false). */ public func isSet(_ i: Int) -> Bool { let (j, m) = indexOf(i) return (words[j] & m) != 0 } /* Returns the number of bits that are 1. Time complexity is O(s) where s is the number of 1-bits. */ public var cardinality: Int { var count = 0 for var x in words { while x != 0 { let y = x & ~(x - 1) // find lowest 1-bit x = x ^ y // and erase it count += 1 } } return count } /* Checks if all the bits are set. */ public func all1() -> Bool { for i in 0.. Bool { for x in words { if x != 0 { return true } } return false } /* Checks if none of the bits are set. */ public func all0() -> Bool { for x in words { if x != 0 { return false } } return true } } // MARK: - Equality extension BitSet: Equatable { } public func == (lhs: BitSet, rhs: BitSet) -> Bool { return lhs.words == rhs.words } // MARK: - Hashing extension BitSet: Hashable { /* Based on the hashing code from Java's BitSet. */ public var hashValue: Int { var h = Word(1234) for i in stride(from: words.count, to: 0, by: -1) { h ^= words[i - 1] &* Word(i) } return Int((h >> 32) ^ h) } } // MARK: - Bitwise operations extension BitSet { public static var allZeros: BitSet { return BitSet(size: 64) } } private func copyLargest(_ lhs: BitSet, _ rhs: BitSet) -> BitSet { return (lhs.words.count > rhs.words.count) ? lhs : rhs } /* Note: In all of these bitwise operations, lhs and rhs are allowed to have a different number of bits. The new BitSet always has the larger size. The extra bits that get added to the smaller BitSet are considered to be 0. That will strip off the higher bits from the larger BitSet when doing &. */ public func & (lhs: BitSet, rhs: BitSet) -> BitSet { let m = max(lhs.size, rhs.size) var out = BitSet(size: m) let n = min(lhs.words.count, rhs.words.count) for i in 0.. BitSet { var out = copyLargest(lhs, rhs) let n = min(lhs.words.count, rhs.words.count) for i in 0.. BitSet { var out = copyLargest(lhs, rhs) let n = min(lhs.words.count, rhs.words.count) for i in 0.. BitSet { var out = BitSet(size: rhs.size) for i in 0.. BitSet { var out = lhs let offset = numBitsLeft / lhs.N let shift = numBitsLeft % lhs.N for i in 0..= 0) { out.words[i] = lhs.words[i - offset] << shift } if (i - offset - 1 >= 0) { out.words[i] |= lhs.words[i - offset - 1] >> (lhs.N - shift) } } out.clearUnusedBits() return out } public func >> (lhs: BitSet, numBitsRight: Int) -> BitSet { var out = lhs let offset = numBitsRight / lhs.N let shift = numBitsRight % lhs.N for i in 0..> shift } if (i + offset + 1 < lhs.words.count) { out.words[i] |= lhs.words[i + offset + 1] << (lhs.N - shift) } } out.clearUnusedBits() return out } // MARK: - Debugging extension UInt64 { /* Writes the bits in little-endian order, LSB first. */ public func bitsToString() -> String { var s = "" var n = self for _ in 1...64 { s += ((n & 1 == 1) ? "1" : "0") n >>= 1 } return s } } extension BitSet: CustomStringConvertible { public var description: String { var s = "" for x in words { s += x.bitsToString() + " " } return s } } ================================================ FILE: Bit Set/BitSet.playground/contents.xcplayground ================================================ ================================================ FILE: Bit Set/BitSet.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Bit Set/BitSet.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Bit Set/README.markdown ================================================ # Bit Set A fixed-size sequence of *n* bits. Also known as bit array or bit vector. To store whether something is true or false you use a `Bool`. Every programmer knows that... But what if you need to remember whether 10,000 things are true or not? You could make an array of 10,000 booleans but you can also go hardcore and use 10,000 bits instead. That's a lot more compact because 10,000 bits fit in less than 160 `Int`s on a 64-bit CPU. Since manipulating individual bits is a little tricky, you can use `BitSet` to hide the dirty work. ## The code A bit set is simply a wrapper around an array. The array doesn't store individual bits but larger integers called the "words". The main job of `BitSet` is to map the bits to the right word. ```swift public struct BitSet { private(set) public var size: Int private let N = 64 public typealias Word = UInt64 fileprivate(set) public var words: [Word] public init(size: Int) { precondition(size > 0) self.size = size // Round up the count to the next multiple of 64. let n = (size + (N-1)) / N words = [Word](repeating: 0, count: n) } ``` `N` is the bit size of the words. It is 64 because we store the bits in a list of unsigned 64-bit integers. (It's fairly easy to change `BitSet` to use 32-bit words instead.) If you write, ```swift var bits = BitSet(size: 140) ``` then the `BitSet` allocates an array of three words. Each word has 64 bits and therefore three words can hold 192 bits. We only use 140 of those bits so we're wasting a bit of space (but of course we can never use less than a whole word). > **Note:** The first entry in the `words` array is the least-significant word, so these words are stored in little endian order in the array. ## Looking up the bits Most of the operations on `BitSet` take the index of the bit as a parameter, so it's useful to have a way to find which word contains that bit. ```swift private func indexOf(_ i: Int) -> (Int, Word) { precondition(i >= 0) precondition(i < size) let o = i / N let m = Word(i - o*N) return (o, 1 << m) } ``` The `indexOf()` function returns the array index of the word, as well as a "mask" that shows exactly where the bit sits inside that word. For example, `indexOf(2)` returns the tuple `(0, 4)` because bit 2 is in the first word (index 0). The mask is 4. In binary the mask looks like the following: 0010000000000000000000000000000000000000000000000000000000000000 That 1 points at the second bit in the word. > **Note:** Remember that everything is shown in little-endian order, including the bits themselves. Bit 0 is on the left, bit 63 on the right. Another example: `indexOf(127)` returns the tuple `(1, 9223372036854775808)`. It is the last bit of the second word. The mask is: 0000000000000000000000000000000000000000000000000000000000000001 Note that the mask is always 64 bits because we look at the data one word at a time. ## Setting and getting bits Now that we know where to find a bit, setting it to 1 is easy: ```swift public mutating func set(_ i: Int) { let (j, m) = indexOf(i) words[j] |= m } ``` This looks up the word index and the mask, then performs a bitwise OR between that word and the mask. If the bit was 0 it becomes 1. If it was already set, then it remains set. Clearing the bit -- i.e. changing it to 0 -- is just as easy: ```swift public mutating func clear(_ i: Int) { let (j, m) = indexOf(i) words[j] &= ~m } ``` Instead of a bitwise OR we now do a bitwise AND with the inverse of the mask. So if the mask was `00100000...0`, then the inverse is `11011111...1`. All the bits are 1, except for the bit we want to set to 0. Due to the way `&` works, this leaves all other bits alone and only changes that single bit to 0. To see if a bit is set we also use the bitwise AND but without inverting: ```swift public func isSet(_ i: Int) -> Bool { let (j, m) = indexOf(i) return (words[j] & m) != 0 } ``` We can add a subscript function to make this all very natural to express: ```swift public subscript(i: Int) -> Bool { get { return isSet(i) } set { if newValue { set(i) } else { clear(i) } } } ``` Now you can write things like: ```swift var bits = BitSet(size: 140) bits[2] = true bits[99] = true bits[128] = true print(bits) ``` This will print the three words that the 140-bit `BitSet` uses to store everything: ```swift 0010000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000010000000000000000000000000000 1000000000000000000000000000000000000000000000000000000000000000 ``` Something else that's fun to do with bits is flipping them. This changes 0 into 1 and 1 into 0. Here's `flip()`: ```swift public mutating func flip(_ i: Int) -> Bool { let (j, m) = indexOf(i) words[j] ^= m return (words[j] & m) != 0 } ``` This uses the remaining bitwise operator, exclusive-OR, to do the flipping. The function also returns the new value of the bit. ## Ignoring the unused bits A lot of the `BitSet` functions are quite easy to implement. For example, `clearAll()`, which resets all the bits to 0: ```swift public mutating func clearAll() { for i in 0.. Word { let diff = words.count*N - size // 1 if diff > 0 { let mask = 1 << Word(63 - diff) // 2 return mask | (mask - 1) // 3 } else { return ~Word() } } private mutating func clearUnusedBits() { words[words.count - 1] &= lastWordMask() // 4 } ``` Here's what it does, step-by-step: 1) `diff` is the number of "leftover" bits. In the above example that is 52 because `3*64 - 140 = 52`. 2) Create a mask that is all 0's, except the highest bit that's still valid is a 1. In our example, that would be: 0000000000010000000000000000000000000000000000000000000000000000 3) Subtract 1 to turn it into: 1111111111100000000000000000000000000000000000000000000000000000 and add the high bit back in to get: 1111111111110000000000000000000000000000000000000000000000000000 There are now 12 one-bits in this word because `140 - 2*64 = 12`. 4) Finally, turn all the higher bits off. Any leftover bits in the last word are now all 0. An example of where this is important is when you combine two `BitSet`s of different sizes. For the sake of illustration, let's take the bitwise OR between two 8-bit values: 10001111 size=4 00100011 size=8 The first one only uses the first 4 bits; the second one uses 8 bits. The first one should really be `10000000` but let's pretend we forgot to clear out those 1's at the end. Then a bitwise OR between the two results in: 10001111 00100011 -------- OR 10101111 That is wrong since two of those 1-bits aren't supposed to be here. The correct way to do it is: 10000000 unused bits set to 0 first! 00100011 -------- OR 10100011 Here's how the `|` operator is implemented: ```swift public func |(lhs: BitSet, rhs: BitSet) -> BitSet { var out = copyLargest(lhs, rhs) let n = min(lhs.words.count, rhs.words.count) for i in 0..> (lhs: BitSet, numBitsRight: Int) -> BitSet { var out = lhs let offset = numBitsRight / lhs.N let shift = numBitsRight % lhs.N for i in 0..> shift } if (i + offset + 1 < lhs.words.count) { out.words[i] |= lhs.words[i + offset + 1] << (lhs.N - shift) } } out.clearUnusedBits() return out } ``` Let's start with this line: ```swift for i in 0..> 10 I've grouped each part of the number by word to make it easier to see what happens. The for-loop goes from least significant word to most significant. So for index zero we're want to know what bits will make up our least significant word. Let's calculate our offset and shift values: offset = 10 / 8 = 1 (remember this is integer division) shift = 10 % 8 = 2 So we consult the word at offset 1 to get some of our bits: 11000000 >> 2 = 00110000 And we get the rest of them from the word one further away: 01000010 << (8 - 2) = 10000000 And we bitwise OR these together to get our least significant term 00110000 10000000 -------- OR 10110000 We repeat this for the 2nd least significant term and obtain: 00010000 The last term can't get any bits because they are past the end of our number so those are all zeros. Our result is: 00000000 00010000 10110000 ## See also [Bit Twiddling Hacks](http://graphics.stanford.edu/~seander/bithacks.html) *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Bloom Filter/BloomFilter.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play public class BloomFilter { fileprivate var array: [Bool] private var hashFunctions: [(T) -> Int] public init(size: Int = 1024, hashFunctions: [(T) -> Int]) { self.array = [Bool](repeating: false, count: size) self.hashFunctions = hashFunctions } private func computeHashes(_ value: T) -> [Int] { return hashFunctions.map { hashFunc in abs(hashFunc(value) % array.count) } } public func insert(_ element: T) { for hashValue in computeHashes(element) { array[hashValue] = true } } public func insert(_ values: [T]) { for value in values { insert(value) } } public func query(_ value: T) -> Bool { let hashValues = computeHashes(value) // Map hashes to indices in the Bloom Filter let results = hashValues.map { hashValue in array[hashValue] } // All values must be 'true' for the query to return true // This does NOT imply that the value is in the Bloom filter, // only that it may be. If the query returns false, however, // you can be certain that the value was not added. let exists = results.reduce(true, { $0 && $1 }) return exists } public func isEmpty() -> Bool { // As soon as the reduction hits a 'true' value, the && condition will fail. return array.reduce(true) { prev, next in prev && !next } } } /* Two hash functions, adapted from http://www.cse.yorku.ca/~oz/hash.html */ func djb2(x: String) -> Int { var hash = 5381 for char in x { hash = ((hash << 5) &+ hash) &+ char.hashValue } return Int(hash) } func sdbm(x: String) -> Int { var hash = 0 for char in x { hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash } return Int(hash) } /* A simple test */ let bloom = BloomFilter(size: 17, hashFunctions: [djb2, sdbm]) bloom.insert("Hello world!") print(bloom.array) bloom.query("Hello world!") // true bloom.query("Hello WORLD") // false bloom.insert("Bloom Filterz") print(bloom.array) bloom.query("Bloom Filterz") // true bloom.query("Hello WORLD") // false or true: It may return true due to a false positive, but it's not guaranteed. ================================================ FILE: Bloom Filter/BloomFilter.playground/contents.xcplayground ================================================ ================================================ FILE: Bloom Filter/BloomFilter.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Bloom Filter/BloomFilter.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Bloom Filter/BloomFilter.swift ================================================ public class BloomFilter { private var array: [Bool] private var hashFunctions: [(T) -> Int] public init(size: Int = 1024, hashFunctions: [(T) -> Int]) { self.array = [Bool](repeating: false, count: size) self.hashFunctions = hashFunctions } private func computeHashes(_ value: T) -> [Int] { return hashFunctions.map { hashFunc in abs(hashFunc(value) % array.count) } } public func insert(_ element: T) { for hashValue in computeHashes(element) { array[hashValue] = true } } public func insert(_ values: [T]) { for value in values { insert(value) } } public func query(_ value: T) -> Bool { let hashValues = computeHashes(value) // Map hashes to indices in the Bloom Filter let results = hashValues.map { hashValue in array[hashValue] } // All values must be 'true' for the query to return true // This does NOT imply that the value is in the Bloom filter, // only that it may be. If the query returns false, however, // you can be certain that the value was not added. let exists = results.reduce(true, { $0 && $1 }) return exists } public func isEmpty() -> Bool { // As soon as the reduction hits a 'true' value, the && condition will fail. return array.reduce(true) { prev, next in prev && !next } } } ================================================ FILE: Bloom Filter/README.markdown ================================================ # Bloom Filter ## Introduction A Bloom Filter is a space-efficient data structure that tells you whether or not an element is present in a set. This is a probabilistic data structure: a query to a Bloom filter either returns `false`, meaning the element is definitely not in the set, or `true`, meaning that the element *might* be in the set. There is a small probability of false positives, where the element isn't actually in the set even though the query returned `true`. But there will never any false negatives: you're guaranteed that if the query returns `false`, then the element really isn't in the set. So a Bloom Filter tells you, "definitely not" or "probably yes". At first, this may not seem too useful. However, it's important in applications like cache filtering and data synchronization. An advantage of the Bloom Filter over a hash table is that the former maintains constant memory usage and constant-time insert and search. For sets with a large number of elements, the performance difference between a hash table and a Bloom Filter is significant, and it is a viable option if you do not need the guarantee of no false positives. > **Note:** Unlike a hash table, the Bloom Filter does not store the actual objects. It just remembers what objects you’ve seen (with a degree of uncertainty) and which ones you haven’t. ## Inserting objects into the set A Bloom Filter is essentially a fixed-length [bit vector](../Bit%20Set/), an array of bits. When we insert objects, we set some of these bits to `1`, and when we query for objects we check if certain bits are `0` or `1`. Both operations use hash functions. To insert an element in the filter, the element is hashed with several different hash functions. Each hash function returns a value that we map to an index in the array. We then set the bits at these indices to `1` or true. For example, let's say this is our array of bits. We have 17 bits and initially they are all `0` or false: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] Now we want to insert the string `"Hello world!"` into the Bloom Filter. We apply two hash functions to this string. The first one gives the value 1999532104120917762. We map this hash value to an index into our array by taking the modulo of the array length: `1999532104120917762 % 17 = 4`. This means we set the bit at index 4 to `1` or true: [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] Then we hash the original string again but this time with a different hash function. It gives the hash value 9211818684948223801. Modulo 17 that is 12, and we set the bit at index 12 to `1` as well: [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ] These two 1-bits are enough to tell the Bloom Filter that it now contains the string `"Hello world!"`. Of course, it doesn't contain the actual string, so you can't ask the Bloom Filter, "give me a list of all the objects you contain". All it has is a bunch of ones and zeros. ## Querying the set Querying, similarly to inserting, is accomplished by first hashing the expected value, which gives several array indices, and then checking to see if all of the bits at those indices are `1`. If even one of the bits is not `1`, the element could not have been inserted and the query returns `false`. If all the bits are `1`, the query returns `true`. For example, if we query for the string `"Hello WORLD"`, then the first hash function returns 5383892684077141175, which modulo 17 is 12. That bit is `1`. But the second hash function gives 5625257205398334446, which maps to array index 9. That bit is `0`. This means the string `"Hello WORLD"` is not in the filter and the query returns `false`. The fact that the first hash function mapped to a `1` bit is a coincidence (it has nothing to do with the fact that both strings start with `"Hello "`). Too many such coincidences can lead to "collisions". If there are collisions, the query may erroneously return `true` even though the element was not inserted -- bringing about the issue with false positives mentioned earlier. Let's say we insert some other element, `"Bloom Filterz"`, which sets bits 7 and 9. Now the array looks like this: [ 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0 ] If you query for `"Hello WORLD"` again, the filter sees that bit 12 is true and bit 9 is now true as well. It reports that `"Hello WORLD"` is indeed present in the set, even though it isn't... because we never inserted that particular string. It's a false positive. This example shows why a Bloom Filter will never say, "definitely yes", only "probably yes". You can fix such issues by using an array with more bits and using additional hash functions. Of course, the more hash functions you use the slower the Bloom Filter will be. So you have to strike a balance. Deletion is not possible with a Bloom Filter, since any one bit might belong to multiple elements. Once you add an element, it's in there for good. Performance of a Bloom Filter is **O(k)** where **k** is the number of hashing functions. ## The code The code is quite straightforward. The internal bit array is set to a fixed length on initialization, which cannot be mutated once it is initialized. ```swift public init(size: Int = 1024, hashFunctions: [(T) -> Int]) { self.array = [Bool](repeating: false, count: size) self.hashFunctions = hashFunctions } ``` Several hash functions should be specified at initialization. Which hash functions you use will depend on the datatypes of the elements you'll be adding to the set. You can see some examples in the playground and the tests -- the `djb2` and `sdbm` hash functions for strings. Insertion just flips the required bits to `true`: ```swift public func insert(_ element: T) { for hashValue in computeHashes(element) { array[hashValue] = true } } ``` This uses the `computeHashes()` function, which loops through the specified `hashFunctions` and returns an array of indices: ```swift private func computeHashes(_ value: T) -> [Int] { return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } } ``` And querying checks to make sure the bits at the hashed values are `true`: ```swift public func query(_ value: T) -> Bool { let hashValues = computeHashes(value) let results = hashValues.map() { hashValue in array[hashValue] } let exists = results.reduce(true, { $0 && $1 }) return exists } ``` If you're coming from another imperative language, you might notice the unusual syntax in the `exists` assignment. Swift makes use of functional paradigms when it makes code more consise and readable, and in this case `reduce` is a much more consise way to check if all the required bits are `true` than a `for` loop. ## Another approach In the previous section, you learnt about how using multiple different hash functions can help reduce the chance of collisions in the bloom filter. However, good hash functions are difficult to design. A simple alternative to multiple hash functions is to use a set of random numbers. As an example, let's say a bloom filter wants to hash each element 15 times during insertion. Instead of using 15 different hash functions, you can rely on just one hash function. The hash value can then be combined with 15 different values to form the indices for flipping. This bloom filter would initialize a set of 15 random numbers ahead of time and use these values during each insertion. ``` hash("Hello world!") >> hash(987654321) // would flip bit 8 hash("Hello world!") >> hash(123456789) // would flip bit 2 ``` Since Swift 4.2, `Hasher` is now included in the Standard library, which is designed to reduce multiple hashes to a single hash in an efficient manner. This makes combining the hashes trivial. ``` private func computeHashes(_ value: T) -> [Int] { return randomSeeds.map() { seed in let hasher = Hasher() hasher.combine(seed) hasher.combine(value) let hashValue = hasher.finalize() return abs(hashValue % array.count) } } ``` If you want to learn more about this approach, you can read about the [Hasher documentation](https://developer.apple.com/documentation/swift/hasher) or Soroush Khanlou's [Swift 4.2 Bloom filter](http://khanlou.com/2018/09/bloom-filters/) implementation. *Written for Swift Algorithm Club by Jamil Dhanani. Edited by Matthijs Hollemans. Updated by Bruno Scheele.* ================================================ FILE: Bloom Filter/Tests/BloomFilterTests.swift ================================================ import XCTest /* Two hash functions, adapted from http://www.cse.yorku.ca/~oz/hash.html */ func djb2(_ x: String) -> Int { var hash = 5381 for char in x { hash = ((hash << 5) &+ hash) &+ char.hashValue } return Int(hash) } func sdbm(_ x: String) -> Int { var hash = 0 for char in x { hash = char.hashValue &+ (hash << 6) &+ (hash << 16) &- hash } return Int(hash) } class BloomFilterTests: XCTestCase { func testSwift4(){ // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testSingleHashFunction() { let bloom = BloomFilter(hashFunctions: [djb2]) bloom.insert("Hello world!") let result_good = bloom.query("Hello world!") let result_bad = bloom.query("Hello world") XCTAssertTrue(result_good) XCTAssertFalse(result_bad) } func testEmptyFilter() { let bloom = BloomFilter(hashFunctions: [djb2]) let empty = bloom.isEmpty() XCTAssertTrue(empty) } func testMultipleHashFunctions() { let bloom = BloomFilter(hashFunctions: [djb2, sdbm]) bloom.insert("Hello world!") let result_good = bloom.query("Hello world!") let result_bad = bloom.query("Hello world") XCTAssertTrue(result_good) XCTAssertFalse(result_bad) } func testFalsePositive() { let bloom = BloomFilter(size: 5, hashFunctions: [djb2, sdbm]) bloom.insert(["hello", "elloh", "llohe", "lohel", "ohell"]) print("Inserted") let query = bloom.query("This wasn't inserted!") // This is true even though we did not insert the value in the Bloom filter; // the Bloom filter is capable of producing false positives but NOT // false negatives. XCTAssertTrue(query) } } ================================================ FILE: Bloom Filter/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Bloom Filter/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3D01C77A263003CECC7 /* BloomFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CF1C77A263003CECC7 /* BloomFilter.swift */; }; 7B95D1E41C861DAA00760793 /* BloomFilterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B95D1E31C861DAA00760793 /* BloomFilterTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3CF1C77A263003CECC7 /* BloomFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BloomFilter.swift; path = ../BloomFilter.swift; sourceTree = SOURCE_ROOT; }; 7B95D1E31C861DAA00760793 /* BloomFilterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BloomFilterTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3CF1C77A263003CECC7 /* BloomFilter.swift */, 7B95D1E31C861DAA00760793 /* BloomFilterTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3D01C77A263003CECC7 /* BloomFilter.swift in Sources */, 7B95D1E41C861DAA00760793 /* BloomFilterTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Bloom Filter/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Bloom Filter/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Bloom Filter/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Bounded Priority Queue/BoundedPriorityQueue.playground/Contents.swift ================================================ struct Message: Comparable, CustomStringConvertible { let name: String let priority: Int var description: String { return "\(name):\(priority)" } } func == (m1: Message, m2: Message) -> Bool { return m1.priority == m2.priority } func < (m1: Message, m2: Message) -> Bool { return m1.priority < m2.priority } let queue = BoundedPriorityQueue(maxElements: 5) queue.count queue.enqueue(Message(name: "hello", priority: 100)) queue.count queue.peek() print(queue) queue.enqueue(Message(name: "there", priority: 99)) queue.count queue.peek() print(queue) queue.enqueue(Message(name: "world", priority: 150)) queue.count queue.peek() print(queue) queue.enqueue(Message(name: "swift", priority: 110)) queue.count queue.peek() print(queue) queue.enqueue(Message(name: "is", priority: 30)) queue.count queue.peek() print(queue) // At this point, the queue is: // // Try to insert an item with a really low priority. This should not get added. queue.enqueue(Message(name: "very", priority: -1)) queue.count // 5 queue.peek() print(queue) // still same as before // Try to insert an item with medium priority. This gets added and the lowest // priority item is removed. queue.enqueue(Message(name: "cool", priority: 120)) queue.count queue.peek() print(queue) // Try to insert an item with very high priority. This gets added and the // lowest priority item is removed. queue.enqueue(Message(name: "!!!", priority: 500)) queue.count queue.peek() print(queue) // Test dequeuing queue.dequeue() queue.count queue.peek() print(queue) queue.dequeue() queue.count queue.peek() print(queue) queue.dequeue() queue.count queue.peek() print(queue) queue.dequeue() queue.count queue.peek() print(queue) queue.dequeue() queue.count queue.peek() print(queue) queue.dequeue() queue.count queue.peek() print(queue) ================================================ FILE: Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift ================================================ public class LinkedListNode { var value: T var next: LinkedListNode? var previous: LinkedListNode? public init(value: T) { self.value = value } } public class BoundedPriorityQueue { fileprivate typealias Node = LinkedListNode private(set) public var count = 0 fileprivate var head: Node? private var tail: Node? private var maxElements: Int public init(maxElements: Int) { self.maxElements = maxElements } public var isEmpty: Bool { return count == 0 } public func peek() -> T? { return head?.value } public func enqueue(_ value: T) { if let node = insert(value, after: findInsertionPoint(value)) { // If the newly inserted node is the last one in the list, then update // the tail pointer. if node.next == nil { tail = node } // If the queue is full, then remove an element from the back. count += 1 if count > maxElements { removeLeastImportantElement() } } } private func insert(_ value: T, after: Node?) -> Node? { if let previous = after { // If the queue is full and we have to insert at the end of the list, // then there's no reason to insert the new value. if count == maxElements && previous.next == nil { print("Queue is full and priority of new object is too small") return nil } // Put the new node in between previous and previous.next (if exists). let node = Node(value: value) node.next = previous.next previous.next?.previous = node previous.next = node node.previous = previous return node } else if let first = head { // Have to insert at the head, so shift the existing head up once place. head = Node(value: value) head!.next = first first.previous = head return head } else { // This is the very first item in the queue. head = Node(value: value) return head } } /* Find the node after which to insert the new value. If this returns nil, the new value should be inserted at the head of the list. */ private func findInsertionPoint(_ value: T) -> Node? { var node = head var prev: Node? = nil while let current = node, value < current.value { prev = node node = current.next } return prev } private func removeLeastImportantElement() { if let last = tail { tail = last.previous tail?.next = nil count -= 1 } // Note: Instead of using a tail pointer, we could just scan from the new // node until the end. Then nodes also don't need a previous pointer. But // this is much slower on large lists. } public func dequeue() -> T? { if let first = head { count -= 1 if count == 0 { head = nil tail = nil } else { head = first.next head!.previous = nil } return first.value } else { return nil } } } extension LinkedListNode: CustomStringConvertible { public var description: String { return "\(value)" } } extension BoundedPriorityQueue: CustomStringConvertible { public var description: String { var s = "<" var node = head while let current = node { s += "\(current), " node = current.next } return s + ">" } } ================================================ FILE: Bounded Priority Queue/BoundedPriorityQueue.playground/contents.xcplayground ================================================ ================================================ FILE: Bounded Priority Queue/BoundedPriorityQueue.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Bounded Priority Queue/BoundedPriorityQueue.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Bounded Priority Queue/BoundedPriorityQueue.swift ================================================ open class LinkedListNode { var value: T var next: LinkedListNode? var previous: LinkedListNode? public init(value: T) { self.value = value } } open class BoundedPriorityQueue { fileprivate typealias Node = LinkedListNode fileprivate(set) open var count = 0 fileprivate var head: Node? fileprivate var tail: Node? fileprivate var maxElements: Int public init(maxElements: Int) { self.maxElements = maxElements } open var isEmpty: Bool { return count == 0 } open func peek() -> T? { return head?.value } open func enqueue(_ value: T) { if let node = insert(value, after: findInsertionPoint(value)) { // If the newly inserted node is the last one in the list, then update // the tail pointer. if node.next == nil { tail = node } // If the queue is full, then remove an element from the back. count += 1 if count > maxElements { removeLeastImportantElement() } } } fileprivate func insert(_ value: T, after: Node?) -> Node? { if let previous = after { // If the queue is full and we have to insert at the end of the list, // then there's no reason to insert the new value. if count == maxElements && previous.next == nil { print("Queue is full and priority of new object is too small") return nil } // Put the new node in between previous and previous.next (if exists). let node = Node(value: value) node.next = previous.next previous.next?.previous = node previous.next = node node.previous = previous return node } else if let first = head { // Have to insert at the head, so shift the existing head up once place. head = Node(value: value) head!.next = first first.previous = head return head } else { // This is the very first item in the queue. head = Node(value: value) return head } } /* Find the node after which to insert the new value. If this returns nil, the new value should be inserted at the head of the list. */ fileprivate func findInsertionPoint(_ value: T) -> Node? { var node = head var prev: Node? = nil while let current = node, value < current.value { prev = node node = current.next } return prev } fileprivate func removeLeastImportantElement() { if let last = tail { tail = last.previous tail?.next = nil count -= 1 } // Note: Instead of using a tail pointer, we could just scan from the new // node until the end. Then nodes also don't need a previous pointer. But // this is much slower on large lists. } open func dequeue() -> T? { if let first = head { count -= 1 if count == 0 { head = nil tail = nil } else { head = first.next head!.previous = nil } return first.value } else { return nil } } } extension LinkedListNode: CustomStringConvertible { public var description: String { return "\(value)" } } extension BoundedPriorityQueue: CustomStringConvertible { public var description: String { var s = "<" var node = head while let current = node { s += "\(current), " node = current.next } return s + ">" } } ================================================ FILE: Bounded Priority Queue/README.markdown ================================================ # Bounded Priority queue A bounded priority queue is similar to a regular [priority queue](../Priority%20Queue/), except that there is a fixed upper bound on the number of elements that can be stored. When a new element is added to the queue while the queue is at capacity, the element with the highest priority value is ejected from the queue. ## Example Suppose we have a bounded-priority-queue with maximum size 5 that has the following values and priorities: ``` Value: [ A, B, C, D, E ] Priority: [ 4.6, 3.2, 1.33, 0.25, 0.1 ] ``` Here, we consider the object with the highest priority value to be the most important (so this is a *max-priority* queue). The larger the priority value, the more we care about the object. So `A` is more important than `B`, `B` is more important than `C`, and so on. Now we want to insert the element `F` with priority `0.4` into this bounded priority queue. Because the queue has maximum size 5, this will insert the element `F` but then evict the lowest-priority element (`E`), yielding the updated queue: ``` Value: [ A, B, C, F, D ] Priority: [ 4.6, 3.2, 1.33, 0.4, 0.25 ] ``` `F` is inserted between `C` and `D` because of its priority value. It's less important than `C` but more important than `D`. Suppose that we wish to insert the element `G` with priority 0.1 into this BPQ. Because `G`'s priority value is less than the minimum-priority element in the queue, upon inserting `G` it will immediately be evicted. In other words, inserting an element into a BPQ with priority less than the minimum-priority element of the BPQ has no effect. ## Implementation While a [heap](../Heap/) may be a really simple implementation for a priority queue, a sorted [linked list](../Linked%20List/) allows for **O(k)** insertion and **O(1)** deletion, where **k** is the bounding number of elements. Here's how you could implement it in Swift: ```swift public class BoundedPriorityQueue { private typealias Node = LinkedListNode private(set) public var count = 0 fileprivate var head: Node? private var tail: Node? private var maxElements: Int public init(maxElements: Int) { self.maxElements = maxElements } public var isEmpty: Bool { return count == 0 } public func peek() -> T? { return head?.value } ``` The `BoundedPriorityQueue` class contains a doubly linked list of `LinkedListNode` objects. Nothing special here yet. The fun stuff happens in the `enqueue()` method: ```swift public func enqueue(_ value: T) { if let node = insert(value, after: findInsertionPoint(value)) { // If the newly inserted node is the last one in the list, then update // the tail pointer. if node.next == nil { tail = node } // If the queue is full, then remove an element from the back. count += 1 if count > maxElements { removeLeastImportantElement() } } } private func insert(_ value: T, after: Node?) -> Node? { if let previous = after { // If the queue is full and we have to insert at the end of the list, // then there's no reason to insert the new value. if count == maxElements && previous.next == nil { print("Queue is full and priority of new object is too small") return nil } // Put the new node in between previous and previous.next (if exists). let node = Node(value: value) node.next = previous.next previous.next?.previous = node previous.next = node node.previous = previous return node } else if let first = head { // Have to insert at the head, so shift the existing head up once place. head = Node(value: value) head!.next = first first.previous = head return head } else { // This is the very first item in the queue. head = Node(value: value) return head } } /* Find the node after which to insert the new value. If this returns nil, the new value should be inserted at the head of the list. */ private func findInsertionPoint(_ value: T) -> Node? { var node = head var prev: Node? = nil while let current = node where value < current.value { prev = node node = current.next } return prev } private func removeLeastImportantElement() { if let last = tail { tail = last.previous tail?.next = nil count -= 1 } // Note: Instead of using a tail pointer, we could just scan from the new // node until the end. Then nodes also don't need a previous pointer. But // this is much slower on large lists. } ``` We first check if the queue already has the maximum number of elements. If so, and the new priority value is less than the `tail` element's priority value, then there is no room for this new element and we return without inserting it. If the new value is acceptable, then we search through the list to find the proper insertion location and update the `next` and `previous` pointers. Lastly, if the queue has now reached the maximum number of elements, then we `dequeue()` the one with the largest priority value. By keeping the most important element at the front of the list, it makes dequeueing very easy: ```swift public func dequeue() -> T? { if let first = head { count -= 1 if count == 0 { head = nil tail = nil } else { head = first.next head!.previous = nil } return first.value } else { return nil } } ``` This simply removes the `head` element from the list and returns it. *Written for Swift Algorithm Club by John Gill and Matthijs Hollemans* ================================================ FILE: Bounded Priority Queue/Tests/BoundedPriorityQueueTests.swift ================================================ // // BoundedPriorityQueueTests.swift // // Created by John Gill on 2/28/16. // import Foundation import XCTest private struct Message: Comparable { let name: String let priority: Int } private func == (m1: Message, m2: Message) -> Bool { return m1.priority == m2.priority } private func < (m1: Message, m2: Message) -> Bool { return m1.priority < m2.priority } private func > (m1: Message, m2: Message) -> Bool { return m1.priority > m2.priority } class BoundedPriorityQueueTest: XCTestCase { func testEmpty() { let queue = BoundedPriorityQueue(maxElements: 5) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.dequeue()) } func testOneElement() { let queue = BoundedPriorityQueue(maxElements: 5) queue.enqueue(Message(name: "hello", priority: 100)) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) let result = queue.dequeue() XCTAssertEqual(result!.priority, 100) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) } func testMaxElements() { let queue = BoundedPriorityQueue(maxElements: 5) XCTAssertTrue(queue.isEmpty) queue.enqueue(Message(name: "john", priority: 100)) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.peek()?.priority, 100) queue.enqueue(Message(name: "james", priority: 200)) XCTAssertEqual(queue.count, 2) XCTAssertEqual(queue.peek()?.priority, 200) queue.enqueue(Message(name: "mark", priority: 300)) XCTAssertEqual(queue.count, 3) XCTAssertEqual(queue.peek()?.priority, 300) queue.enqueue(Message(name: "ken", priority: 400)) XCTAssertEqual(queue.count, 4) XCTAssertEqual(queue.peek()?.priority, 400) queue.enqueue(Message(name: "thomas", priority: 500)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 500) queue.enqueue(Message(name: "melanie", priority: 550)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 550) queue.enqueue(Message(name: "lily", priority: 450)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 550) queue.enqueue(Message(name: "fred", priority: 350)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 550) queue.enqueue(Message(name: "rachel", priority: 50)) XCTAssertEqual(queue.count, 5) XCTAssertEqual(queue.peek()?.priority, 550) var result = queue.dequeue() XCTAssertEqual(result!.priority, 550) XCTAssertEqual(queue.count, 4) result = queue.dequeue() XCTAssertEqual(result!.priority, 500) XCTAssertEqual(queue.count, 3) result = queue.dequeue() XCTAssertEqual(result!.priority, 450) XCTAssertEqual(queue.count, 2) queue.enqueue(Message(name: "ryan", priority: 150)) XCTAssertEqual(queue.count, 3) XCTAssertEqual(queue.peek()?.priority, 400) result = queue.dequeue() XCTAssertEqual(result!.priority, 400) XCTAssertEqual(queue.count, 2) result = queue.dequeue() XCTAssertEqual(result!.priority, 350) XCTAssertEqual(queue.count, 1) result = queue.dequeue() XCTAssertEqual(result!.priority, 150) XCTAssertEqual(queue.count, 0) result = queue.dequeue() XCTAssertNil(result) XCTAssertEqual(queue.count, 0) XCTAssertTrue(queue.isEmpty) } } ================================================ FILE: Bounded Priority Queue/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ B810B5B11C83E3B200450324 /* BoundedPriorityQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B810B5B01C83E3B200450324 /* BoundedPriorityQueueTests.swift */; }; B8F635A81C83E4270060805E /* BoundedPriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8F635A71C83E4270060805E /* BoundedPriorityQueue.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ B80004B31C83E342001FE2D7 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B80004B81C83E342001FE2D7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; B810B5B01C83E3B200450324 /* BoundedPriorityQueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoundedPriorityQueueTests.swift; sourceTree = SOURCE_ROOT; }; B8F635A71C83E4270060805E /* BoundedPriorityQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoundedPriorityQueue.swift; path = ../BoundedPriorityQueue.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ B80004B01C83E342001FE2D7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ B80004A81C83E324001FE2D7 = { isa = PBXGroup; children = ( B80004B51C83E342001FE2D7 /* Tests */, B80004B41C83E342001FE2D7 /* Products */, ); sourceTree = ""; }; B80004B41C83E342001FE2D7 /* Products */ = { isa = PBXGroup; children = ( B80004B31C83E342001FE2D7 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; B80004B51C83E342001FE2D7 /* Tests */ = { isa = PBXGroup; children = ( B8F635A71C83E4270060805E /* BoundedPriorityQueue.swift */, B810B5B01C83E3B200450324 /* BoundedPriorityQueueTests.swift */, B80004B81C83E342001FE2D7 /* Info.plist */, ); path = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ B80004B21C83E342001FE2D7 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = B80004B91C83E342001FE2D7 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( B80004AF1C83E342001FE2D7 /* Sources */, B80004B11C83E342001FE2D7 /* Resources */, B80004B01C83E342001FE2D7 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = B80004B31C83E342001FE2D7 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ B80004A91C83E324001FE2D7 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0820; TargetAttributes = { B80004B21C83E342001FE2D7 = { CreatedOnToolsVersion = 7.2.1; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = B80004AC1C83E324001FE2D7 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = B80004A81C83E324001FE2D7; productRefGroup = B80004B41C83E342001FE2D7 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( B80004B21C83E342001FE2D7 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ B80004B11C83E342001FE2D7 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ B80004AF1C83E342001FE2D7 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( B810B5B11C83E3B200450324 /* BoundedPriorityQueueTests.swift in Sources */, B8F635A81C83E4270060805E /* BoundedPriorityQueue.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ B80004AD1C83E324001FE2D7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; B80004AE1C83E324001FE2D7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; B80004BA1C83E342001FE2D7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.alvahouse322.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; }; name = Debug; }; B80004BB1C83E342001FE2D7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = com.alvahouse322.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ B80004AC1C83E324001FE2D7 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( B80004AD1C83E324001FE2D7 /* Debug */, B80004AE1C83E324001FE2D7 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; B80004B91C83E342001FE2D7 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( B80004BA1C83E342001FE2D7 /* Debug */, B80004BB1C83E342001FE2D7 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = B80004A91C83E324001FE2D7 /* Project object */; } ================================================ FILE: Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Bounded Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Boyer-Moore-Horspool/BoyerMooreHorspool.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play /* Boyer-Moore string search This code is based on the article "Faster String Searches" by Costas Menico from Dr Dobb's magazine, July 1989. http://www.drdobbs.com/database/faster-string-searches/184408171 */ extension String { func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.count guard patternLength > 0, patternLength <= self.count else { return nil } // Make the skip table. This table determines how far we skip ahead // when a character from the pattern is found. var skipTable = [Character: Int]() for (i, c) in pattern.enumerated() { skipTable[c] = patternLength - i - 1 } // This points at the last character in the pattern. let p = pattern.index(before: pattern.endIndex) let lastChar = pattern[p] // The pattern is scanned right-to-left, so skip ahead in the string by // the length of the pattern. (Minus 1 because startIndex already points // at the first character in the source string.) var i = index(startIndex, offsetBy: patternLength - 1) // This is a helper function that steps backwards through both strings // until we find a character that doesn’t match, or until we’ve reached // the beginning of the pattern. func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { j = index(before: j) q = index(before: q) if self[j] != pattern[q] { return nil } } return j } // The main loop. Keep going until the end of the string is reached. while i < endIndex { let c = self[i] // Does the current character match the last character from the pattern? if c == lastChar { // There is a possible match. Do a brute-force search backwards. if let k = backwards() { return k } if !usingHorspoolImprovement { // If no match, we can only safely skip one character ahead. i = index(after: i) } else { // Ensure to jump at least one character (this is needed because the first // character is in the skipTable, and `skipTable[lastChar] = 0`) let jumpOffset = max(skipTable[c] ?? patternLength, 1) i = index(i, offsetBy: jumpOffset, limitedBy: endIndex) ?? endIndex } } else { // The characters are not equal, so skip ahead. The amount to skip is // determined by the skip table. If the character is not present in the // pattern, we can skip ahead by the full pattern length. However, if // the character *is* present in the pattern, there may be a match up // ahead and we can't skip as far. i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex } } return nil } } // A few simple tests let str = "Hello, World" str.index(of: "World") // 7 let animals = "🐶🐔🐷🐮🐱" animals.index(of: "🐮") // 6 let lorem = "Lorem ipsum dolor sit amet" lorem.index(of: "sit", usingHorspoolImprovement: true) // 18 ================================================ FILE: Boyer-Moore-Horspool/BoyerMooreHorspool.playground/contents.xcplayground ================================================ ================================================ FILE: Boyer-Moore-Horspool/BoyerMooreHorspool.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Boyer-Moore-Horspool/BoyerMooreHorspool.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Boyer-Moore-Horspool/BoyerMooreHorspool.playground/timeline.xctimeline ================================================ ================================================ FILE: Boyer-Moore-Horspool/BoyerMooreHorspool.swift ================================================ /* Boyer-Moore string search This code is based on the article "Faster String Searches" by Costas Menico from Dr Dobb's magazine, July 1989. http://www.drdobbs.com/database/faster-string-searches/184408171 */ extension String { func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.count guard patternLength > 0, patternLength <= self.count else { return nil } // Make the skip table. This table determines how far we skip ahead // when a character from the pattern is found. var skipTable = [Character: Int]() for (i, c) in pattern.enumerated() { skipTable[c] = patternLength - i - 1 } // This points at the last character in the pattern. let p = pattern.index(before: pattern.endIndex) let lastChar = pattern[p] // The pattern is scanned right-to-left, so skip ahead in the string by // the length of the pattern. (Minus 1 because startIndex already points // at the first character in the source string.) var i = index(startIndex, offsetBy: patternLength - 1) // This is a helper function that steps backwards through both strings // until we find a character that doesn’t match, or until we’ve reached // the beginning of the pattern. func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { j = index(before: j) q = index(before: q) if self[j] != pattern[q] { return nil } } return j } // The main loop. Keep going until the end of the string is reached. while i < endIndex { let c = self[i] // Does the current character match the last character from the pattern? if c == lastChar { // There is a possible match. Do a brute-force search backwards. if let k = backwards() { return k } if !usingHorspoolImprovement { // If no match, we can only safely skip one character ahead. i = index(after: i) } else { // Ensure to jump at least one character (this is needed because the first // character is in the skipTable, and `skipTable[lastChar] = 0`) let jumpOffset = max(skipTable[c] ?? patternLength, 1) i = index(i, offsetBy: jumpOffset, limitedBy: endIndex) ?? endIndex } } else { // The characters are not equal, so skip ahead. The amount to skip is // determined by the skip table. If the character is not present in the // pattern, we can skip ahead by the full pattern length. However, if // the character *is* present in the pattern, there may be a match up // ahead and we can't skip as far. i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex } } return nil } } ================================================ FILE: Boyer-Moore-Horspool/README.markdown ================================================ # Boyer-Moore String Search > This topic has been tutorialized [here](https://www.raywenderlich.com/163964/swift-algorithm-club-booyer-moore-string-search-algorithm) Goal: Write a string search algorithm in pure Swift without importing Foundation or using `NSString`'s `rangeOfString()` method. In other words, we want to implement an `indexOf(pattern: String)` extension on `String` that returns the `String.Index` of the first occurrence of the search pattern, or `nil` if the pattern could not be found inside the string. For example: ```swift // Input: let s = "Hello, World" s.indexOf(pattern: "World") // Output: 7 // Input: let animals = "🐶🐔🐷🐮🐱" animals.indexOf(pattern: "🐮") // Output: 6 ``` > **Note:** The index of the cow is 6, not 3 as you might expect, because the string uses more storage per character for emoji. The actual value of the `String.Index` is not so important, just that it points at the right character in the string. The [brute-force approach](../Brute-Force%20String%20Search/) works OK, but it's not very efficient, especially on large chunks of text. As it turns out, you don't need to look at _every_ character from the source string -- you can often skip ahead multiple characters. The skip-ahead algorithm is called [Boyer-Moore](https://en.wikipedia.org/wiki/Boyer–Moore_string_search_algorithm) and it has been around for a long time. It is considered the benchmark for all string search algorithms. Here's how you could write it in Swift: ```swift extension String { func index(of pattern: String) -> Index? { // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.count guard patternLength > 0, patternLength <= count else { return nil } // Make the skip table. This table determines how far we skip ahead // when a character from the pattern is found. var skipTable = [Character: Int]() for (i, c) in pattern.enumerated() { skipTable[c] = patternLength - i - 1 } // This points at the last character in the pattern. let p = pattern.index(before: pattern.endIndex) let lastChar = pattern[p] // The pattern is scanned right-to-left, so skip ahead in the string by // the length of the pattern. (Minus 1 because startIndex already points // at the first character in the source string.) var i = index(startIndex, offsetBy: patternLength - 1) // This is a helper function that steps backwards through both strings // until we find a character that doesn’t match, or until we’ve reached // the beginning of the pattern. func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { j = index(before: j) q = index(before: q) if self[j] != pattern[q] { return nil } } return j } // The main loop. Keep going until the end of the string is reached. while i < endIndex { let c = self[i] // Does the current character match the last character from the pattern? if c == lastChar { // There is a possible match. Do a brute-force search backwards. if let k = backwards() { return k } // If no match, we can only safely skip one character ahead. i = index(after: i) } else { // The characters are not equal, so skip ahead. The amount to skip is // determined by the skip table. If the character is not present in the // pattern, we can skip ahead by the full pattern length. However, if // the character *is* present in the pattern, there may be a match up // ahead and we can't skip as far. i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex } } return nil } } ``` The algorithm works as follows. You line up the search pattern with the source string and see what character from the string matches the _last_ character of the search pattern: ``` source string: Hello, World search pattern: World ^ ``` There are three possibilities: 1. The two characters are equal. You've found a possible match. 2. The characters are not equal, but the source character does appear in the search pattern elsewhere. 3. The source character does not appear in the search pattern at all. In the example, the characters `o` and `d` do not match, but `o` does appear in the search pattern. That means we can skip ahead several positions: ``` source string: Hello, World search pattern: World ^ ``` Note how the two `o` characters line up now. Again you compare the last character of the search pattern with the search text: `W` vs `d`. These are not equal but the `W` does appear in the pattern. So skip ahead again to line up those two `W` characters: ``` source string: Hello, World search pattern: World ^ ``` This time the two characters are equal and there is a possible match. To verify the match you do a brute-force search, but backwards, from the end of the search pattern to the beginning. And that's all there is to it. The amount to skip ahead at any given time is determined by the "skip table", which is a dictionary of all the characters in the search pattern and the amount to skip by. The skip table in the example looks like: ``` W: 4 o: 3 r: 2 l: 1 d: 0 ``` The closer a character is to the end of the pattern, the smaller the skip amount. If a character appears more than once in the pattern, the one nearest to the end of the pattern determines the skip value for that character. > **Note:** If the search pattern consists of only a few characters, it's faster to do a brute-force search. There's a trade-off between the time it takes to build the skip table and doing brute-force for short patterns. Credits: This code is based on the article ["Faster String Searches" by Costas Menico](http://www.drdobbs.com/database/faster-string-searches/184408171) from Dr Dobb's magazine, July 1989 -- Yes, 1989! Sometimes it's useful to keep those old magazines around. See also: [a detailed analysis](http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/bmen.htm) of the algorithm. ## Boyer-Moore-Horspool algorithm A variation on the above algorithm is the [Boyer-Moore-Horspool algorithm](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore%E2%80%93Horspool_algorithm). Like the regular Boyer-Moore algorithm, it uses the `skipTable` to skip ahead a number of characters. The difference is in how we check partial matches. In the above version, if a partial match is found but it's not a complete match, we skip ahead by just one character. In this revised version, we also use the skip table in that situation. Here's an implementation of the Boyer-Moore-Horspool algorithm: ```swift extension String { func index(of pattern: String) -> Index? { // Cache the length of the search pattern because we're going to // use it a few times and it's expensive to calculate. let patternLength = pattern.count guard patternLength > 0, patternLength <= characters.count else { return nil } // Make the skip table. This table determines how far we skip ahead // when a character from the pattern is found. var skipTable = [Character: Int]() for (i, c) in pattern.enumerated() { skipTable[c] = patternLength - i - 1 } // This points at the last character in the pattern. let p = pattern.index(before: pattern.endIndex) let lastChar = pattern[p] // The pattern is scanned right-to-left, so skip ahead in the string by // the length of the pattern. (Minus 1 because startIndex already points // at the first character in the source string.) var i = index(startIndex, offsetBy: patternLength - 1) // This is a helper function that steps backwards through both strings // until we find a character that doesn’t match, or until we’ve reached // the beginning of the pattern. func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { j = index(before: j) q = index(before: q) if self[j] != pattern[q] { return nil } } return j } // The main loop. Keep going until the end of the string is reached. while i < endIndex { let c = self[i] // Does the current character match the last character from the pattern? if c == lastChar { // There is a possible match. Do a brute-force search backwards. if let k = backwards() { return k } // Ensure to jump at least one character (this is needed because the first // character is in the skipTable, and `skipTable[lastChar] = 0`) let jumpOffset = max(skipTable[c] ?? patternLength, 1) i = index(i, offsetBy: jumpOffset, limitedBy: endIndex) ?? endIndex } else { // The characters are not equal, so skip ahead. The amount to skip is // determined by the skip table. If the character is not present in the // pattern, we can skip ahead by the full pattern length. However, if // the character *is* present in the pattern, there may be a match up // ahead and we can't skip as far. i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex } } return nil } } ``` In practice, the Horspool version of the algorithm tends to perform a little better than the original. However, it depends on the tradeoffs you're willing to make. Credits: This code is based on the paper: [R. N. Horspool (1980). "Practical fast searching in strings". Software - Practice & Experience 10 (6): 501–506.](http://www.cin.br/~paguso/courses/if767/bib/Horspool_1980.pdf) _Written for Swift Algorithm Club by Matthijs Hollemans, updated by Andreas Neusüß_, [Matías Mazzei](https://github.com/mmazzei). ================================================ FILE: Boyer-Moore-Horspool/Tests/BoyerMooreHorspoolTests.swift ================================================ // // BoyerMooreHorspoolTests.swift // Tests // // Created by Matias Mazzei on 12/24/16. // Copyright © 2016 Swift Algorithm Club. All rights reserved. // class BoyerMooreHorspoolTests: BoyerMooreTest { override func setUp() { super.setUp() useHorspoolImprovement = false } } ================================================ FILE: Boyer-Moore-Horspool/Tests/BoyerMooreTests.swift ================================================ // // BoyerMooreHorspoolTests.swift // Tests // // Created by Matias Mazzei on 12/24/16. // Copyright © 2016 Swift Algorithm Club. All rights reserved. // import Foundation import XCTest class BoyerMooreTest: XCTestCase { var useHorspoolImprovement = false override func setUp() { super.setUp() } func assert(pattern: String, doesNotExistsIn string: String) { let index = string.index(of: pattern, usingHorspoolImprovement: useHorspoolImprovement) XCTAssertNil(index) } func assert(pattern: String, existsIn string: String) { let index = string.index(of: pattern, usingHorspoolImprovement: useHorspoolImprovement) XCTAssertNotNil(index) let startIndex = index! let endIndex = string.index(index!, offsetBy: pattern.count) let match = String(string[startIndex.. CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Boyer-Moore-Horspool/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */; }; 8ED7591C1F9A064A00440D89 /* BoyerMooreHorspool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ED7591B1F9A064A00440D89 /* BoyerMooreHorspool.swift */; }; 9AED56801E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoyerMooreTests.swift; sourceTree = SOURCE_ROOT; }; 8ED7591B1F9A064A00440D89 /* BoyerMooreHorspool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoyerMooreHorspool.swift; path = ../BoyerMooreHorspool.swift; sourceTree = ""; }; 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoyerMooreHorspoolTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 8ED7591B1F9A064A00440D89 /* BoyerMooreHorspool.swift */, 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 9AED56811E0EEA5B00958DCC /* ShellScript */, 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = ""; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 9AED56811E0EEA5B00958DCC /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8ED7591C1F9A064A00440D89 /* BoyerMooreHorspool.swift in Sources */, 9AED56801E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift in Sources */, 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Boyer-Moore-Horspool/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Boyer-Moore-Horspool/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Boyer-Moore-Horspool/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: Boyer-Moore-Horspool/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift ================================================ func breadthFirstSearch(_ graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) var nodesExplored = [source.label] source.visited = true while let node = queue.dequeue() { for edge in node.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true nodesExplored.append(neighborNode.label) } } } return nodesExplored } let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") let nodeC = graph.addNode("c") let nodeD = graph.addNode("d") let nodeE = graph.addNode("e") let nodeF = graph.addNode("f") let nodeG = graph.addNode("g") let nodeH = graph.addNode("h") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeD) graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = breadthFirstSearch(graph, source: nodeA) print(nodesExplored) ================================================ FILE: Breadth-First Search/BreadthFirstSearch.playground/Sources/Edge.swift ================================================ public class Edge: Equatable { public var neighbor: Node public init(_ neighbor: Node) { self.neighbor = neighbor } } public func == (_ lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } ================================================ FILE: Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift ================================================ public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { self.nodes = [] } @discardableResult public func addNode(_ label: String) -> Node { let node = Node(label) nodes.append(node) return node } public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor) source.neighbors.append(edge) } public var description: String { var description = "" for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { let duplicated = Graph() for node in nodes { duplicated.addNode(node.label) } for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(node.label) let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } return duplicated } } public func == (_ lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } ================================================ FILE: Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift ================================================ public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String public var distance: Int? public var visited: Bool public init(_ label: String) { self.label = label neighbors = [] visited = false } public var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } public var hasDistance: Bool { return distance != nil } public func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } public func == (_ lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } ================================================ FILE: Breadth-First Search/BreadthFirstSearch.playground/Sources/Queue.swift ================================================ public struct Queue { private var array: [T] public init() { array = [] } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public func peek() -> T? { return array.first } } ================================================ FILE: Breadth-First Search/BreadthFirstSearch.playground/contents.xcplayground ================================================ ================================================ FILE: Breadth-First Search/BreadthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Breadth-First Search/BreadthFirstSearch.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Breadth-First Search/BreadthFirstSearch.swift ================================================ func breadthFirstSearch(_ graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) var nodesExplored = [source.label] source.visited = true while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true nodesExplored.append(neighborNode.label) } } } return nodesExplored } ================================================ FILE: Breadth-First Search/README.markdown ================================================ # Breadth-First Search > This topic has been tutorialized [here](https://www.raywenderlich.com/155801/swift-algorithm-club-swift-breadth-first-search) Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at a source node and explores the immediate neighbor nodes first, before moving to the next level neighbors. Breadth-first search can be used on both directed and undirected graphs. ## Animated example Here's how breadth-first search works on a graph: ![Animated example of a breadth-first search](Images/AnimatedExample.gif) When we visit a node, we color it black. We also put its neighbor nodes into a [queue](../Queue/). In the animation the nodes that are enqueued but not visited yet are shown in gray. Let's follow the animated example. We start with the source node `A` and add it to a queue. In the animation this is shown as node `A` becoming gray. ```swift queue.enqueue(A) ``` The queue is now `[ A ]`. The idea is that, as long as there are nodes in the queue, we visit the node that's at the front of the queue, and enqueue its immediate neighbor nodes if they have not been visited yet. To start traversing the graph, we pull the first node off the queue, `A`, and color it black. Then we enqueue its two neighbor nodes `B` and `C`. This colors them gray. ```swift queue.dequeue() // A queue.enqueue(B) queue.enqueue(C) ``` The queue is now `[ B, C ]`. We dequeue `B`, and enqueue `B`'s neighbor nodes `D` and `E`. ```swift queue.dequeue() // B queue.enqueue(D) queue.enqueue(E) ``` The queue is now `[ C, D, E ]`. Dequeue `C`, and enqueue `C`'s neighbor nodes `F` and `G`. ```swift queue.dequeue() // C queue.enqueue(F) queue.enqueue(G) ``` The queue is now `[ D, E, F, G ]`. Dequeue `D`, which has no neighbor nodes. ```swift queue.dequeue() // D ``` The queue is now `[ E, F, G ]`. Dequeue `E` and enqueue its single neighbor node `H`. Note that `B` is also a neighbor for `E` but we've already visited `B`, so we're not adding it to the queue again. ```swift queue.dequeue() // E queue.enqueue(H) ``` The queue is now `[ F, G, H ]`. Dequeue `F`, which has no unvisited neighbor nodes. ```swift queue.dequeue() // F ``` The queue is now `[ G, H ]`. Dequeue `G`, which has no unvisited neighbor nodes. ```swift queue.dequeue() // G ``` The queue is now `[ H ]`. Dequeue `H`, which has no unvisited neighbor nodes. ```swift queue.dequeue() // H ``` The queue is now empty, meaning that all nodes have been explored. The order in which the nodes were explored is `A`, `B`, `C`, `D`, `E`, `F`, `G`, `H`. We can show this as a tree: ![The BFS tree](Images/TraversalTree.png) The parent of a node is the one that "discovered" that node. The root of the tree is the node you started the breadth-first search from. For an unweighted graph, this tree defines a shortest path from the starting node to every other node in the tree. So breadth-first search is one way to find the shortest path between two nodes in a graph. ## The code Simple implementation of breadth-first search using a queue: ```swift func breadthFirstSearch(_ graph: Graph, source: Node) -> [String] { var queue = Queue() queue.enqueue(source) var nodesExplored = [source.label] source.visited = true while let node = queue.dequeue() { for edge in node.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { queue.enqueue(neighborNode) neighborNode.visited = true nodesExplored.append(neighborNode.label) } } } return nodesExplored } ``` While there are nodes in the queue, we visit the first one and then enqueue its immediate neighbors if they haven't been visited yet. Put this code in a playground and test it like so: ```swift let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") let nodeC = graph.addNode("c") let nodeD = graph.addNode("d") let nodeE = graph.addNode("e") let nodeF = graph.addNode("f") let nodeG = graph.addNode("g") let nodeH = graph.addNode("h") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeD) graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = breadthFirstSearch(graph, source: nodeA) print(nodesExplored) ``` This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]` ## What is BFS good for? Breadth-first search can be used to solve many problems. A small selection: * Computing the [shortest path](../Shortest%20Path%20(Unweighted)/) between a source node and each of the other nodes (only for unweighted graphs). * Calculating the [minimum spanning tree](../Minimum%20Spanning%20Tree%20(Unweighted)/) on an unweighted graph. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* ================================================ FILE: Breadth-First Search/Tests/BreadthFirstSearchTests.swift ================================================ import XCTest class BreadthFirstSearchTests: XCTestCase { func testExploringTree() { let tree = Graph() let nodeA = tree.addNode("a") let nodeB = tree.addNode("b") let nodeC = tree.addNode("c") let nodeD = tree.addNode("d") let nodeE = tree.addNode("e") let nodeF = tree.addNode("f") let nodeG = tree.addNode("g") let nodeH = tree.addNode("h") tree.addEdge(nodeA, neighbor: nodeB) tree.addEdge(nodeA, neighbor: nodeC) tree.addEdge(nodeB, neighbor: nodeD) tree.addEdge(nodeB, neighbor: nodeE) tree.addEdge(nodeC, neighbor: nodeF) tree.addEdge(nodeC, neighbor: nodeG) tree.addEdge(nodeE, neighbor: nodeH) let nodesExplored = breadthFirstSearch(tree, source: nodeA) XCTAssertEqual(nodesExplored, ["a", "b", "c", "d", "e", "f", "g", "h"]) } func testExploringGraph() { let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") let nodeC = graph.addNode("c") let nodeD = graph.addNode("d") let nodeE = graph.addNode("e") let nodeF = graph.addNode("f") let nodeG = graph.addNode("g") let nodeH = graph.addNode("h") let nodeI = graph.addNode("i") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeH) graph.addEdge(nodeB, neighbor: nodeA) graph.addEdge(nodeB, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeH) graph.addEdge(nodeC, neighbor: nodeB) graph.addEdge(nodeC, neighbor: nodeD) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeI) graph.addEdge(nodeD, neighbor: nodeC) graph.addEdge(nodeD, neighbor: nodeE) graph.addEdge(nodeD, neighbor: nodeF) graph.addEdge(nodeE, neighbor: nodeD) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeC) graph.addEdge(nodeF, neighbor: nodeD) graph.addEdge(nodeF, neighbor: nodeE) graph.addEdge(nodeF, neighbor: nodeG) graph.addEdge(nodeG, neighbor: nodeF) graph.addEdge(nodeG, neighbor: nodeH) graph.addEdge(nodeG, neighbor: nodeI) graph.addEdge(nodeH, neighbor: nodeA) graph.addEdge(nodeH, neighbor: nodeB) graph.addEdge(nodeH, neighbor: nodeG) graph.addEdge(nodeH, neighbor: nodeI) graph.addEdge(nodeI, neighbor: nodeC) graph.addEdge(nodeI, neighbor: nodeG) graph.addEdge(nodeI, neighbor: nodeH) let nodesExplored = breadthFirstSearch(graph, source: nodeA) XCTAssertEqual(nodesExplored, ["a", "b", "h", "c", "g", "i", "d", "f", "e"]) } func testExploringGraphWithASingleNode() { let graph = Graph() let node = graph.addNode("a") let nodesExplored = breadthFirstSearch(graph, source: node) XCTAssertEqual(nodesExplored, ["a"]) } } ================================================ FILE: Breadth-First Search/Tests/Graph.swift ================================================ // MARK: - Edge public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor } } public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } // MARK: - Node public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String public var distance: Int? public var visited: Bool public init(label: String) { self.label = label neighbors = [] visited = false } public var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } public var hasDistance: Bool { return distance != nil } public func remove(edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { self.nodes = [] } public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } public var description: String { var description = "" for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { let duplicated = Graph() for node in nodes { _ = duplicated.addNode(node.label) } for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(node.label) let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } return duplicated } } public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } ================================================ FILE: Breadth-First Search/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Breadth-First Search/Tests/Queue.swift ================================================ public struct Queue { private var array: [T] public init() { array = [] } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public func peek() -> T? { return array.first } } ================================================ FILE: Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */; }; 83F9C96C1C8443E800B3A87F /* BreadthFirstSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */; }; 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9701C84449D00B3A87F /* Queue.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BreadthFirstSearch.swift; path = ../BreadthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BreadthFirstSearchTests.swift; sourceTree = SOURCE_ROOT; }; 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = SOURCE_ROOT; }; 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 83F9C9651C84437C00B3A87F /* BreadthFirstSearch.swift */, 83F9C96B1C8443E800B3A87F /* BreadthFirstSearchTests.swift */, 83F9C96E1C84449D00B3A87F /* Graph.swift */, 83F9C9701C84449D00B3A87F /* Queue.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, 83F9C9681C84437C00B3A87F /* BreadthFirstSearch.swift in Sources */, 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */, 83F9C96C1C8443E800B3A87F /* BreadthFirstSearchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Breadth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Breadth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif extension String { func indexOf(_ pattern: String) -> String.Index? { for i in self.characters.indices { var j = i var found = true for p in pattern.characters.indices { if j == self.characters.endIndex || self[j] != pattern[p] { found = false break } else { j = self.characters.index(after: j) } } if found { return i } } return nil } } // A few simple tests let s = "Hello, World" s.indexOf("World") // 7 let animals = "🐶🐔🐷🐮🐱" animals.indexOf("🐮") // 6 ================================================ FILE: Brute-Force String Search/BruteForceStringSearch.playground/contents.xcplayground ================================================ ================================================ FILE: Brute-Force String Search/BruteForceStringSearch.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Brute-Force String Search/BruteForceStringSearch.swift ================================================ /* Brute-force string search */ extension String { func indexOf(_ pattern: String) -> String.Index? { for i in self.characters.indices { var j = i var found = true for p in pattern.characters.indices { if j == self.characters.endIndex || self[j] != pattern[p] { found = false break } else { j = self.characters.index(after: j) } } if found { return i } } return nil } } ================================================ FILE: Brute-Force String Search/README.markdown ================================================ # Brute-Force String Search How would you go about writing a string search algorithm in pure Swift if you were not allowed to import Foundation and could not use `NSString`'s `rangeOfString()` method? The goal is to implement an `indexOf(pattern: String)` extension on `String` that returns the `String.Index` of the first occurrence of the search pattern, or `nil` if the pattern could not be found inside the string. For example: ```swift // Input: let s = "Hello, World" s.indexOf("World") // Output: 7 // Input: let animals = "🐶🐔🐷🐮🐱" animals.indexOf("🐮") // Output: 6 ``` > **Note:** The index of the cow is 6, not 3 as you might expect, because the string uses more storage per character for emoji. The actual value of the `String.Index` is not so important, just that it points at the right character in the string. Here is a brute-force solution: ```swift extension String { func indexOf(_ pattern: String) -> String.Index? { for i in self.characters.indices { var j = i var found = true for p in pattern.characters.indices{ if j == self.characters.endIndex || self[j] != pattern[p] { found = false break } else { j = self.characters.index(after: j) } } if found { return i } } return nil } } ``` This looks at each character in the source string in turn. If the character equals the first character of the search pattern, then the inner loop checks whether the rest of the pattern matches. If no match is found, the outer loop continues where it left off. This repeats until a complete match is found or the end of the source string is reached. The brute-force approach works OK, but it's not very efficient (or pretty). It should work fine on small strings, though. For a smarter algorithm that works better with large chunks of text, check out [Boyer-Moore](../Boyer-Moore-Horspool) string search. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Bubble Sort/MyPlayground.playground/Contents.swift ================================================ import Foundation var array = [4,2,1,3] print("before:",array) print("after:", bubbleSort(array)) print("after:", bubbleSort(array, <)) print("after:", bubbleSort(array, >)) ================================================ FILE: Bubble Sort/MyPlayground.playground/Sources/BubbleSort.swift ================================================ // // BubbleSort.swift // // Created by Julio Brazil on 1/10/18. // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included in all copies or substantial // portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE // OR OTHER DEALINGS IN THE SOFTWARE. // import Foundation /// Performs the bubble sort algorithm in the array /// /// - Parameter elements: a array of elements that implement the Comparable protocol /// - Returns: an array with the same elements but in order public func bubbleSort (_ elements: [T]) -> [T] where T: Comparable { return bubbleSort(elements, <) } public func bubbleSort (_ elements: [T], _ comparison: (T,T) -> Bool) -> [T] { var array = elements for i in 0.. ================================================ FILE: Bubble Sort/MyPlayground.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Bubble Sort/MyPlayground.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Bubble Sort/README.markdown ================================================ # Bubble Sort Bubble sort is a sorting algorithm that is implemented by starting in the beginning of the array and swapping the first two elements only if the first element is greater than the second element. This comparison is then moved onto the next pair and so on and so forth. This is done until the array is completely sorted. The smaller items slowly “bubble” up to the beginning of the array. Sometimes this algorithm is refered as Sinking sort, due to the larger, or heavier elements sinking to the end of the array. ##### Runtime: - Average: O(N^2) - Worst: O(N^2) ##### Memory: - O(1) ### Implementation: The implementation will not be shown as the average and worst runtimes show that this is a very inefficient algorithm. However, having a grasp of the concept will help you understand the basics of simple sorting algorithms. Bubble sort is a very simple sorting algorithm, it consists in comparing pairs of adjacent elements in the array, if the first element is larger, swap them, otherwise, you do nothing and go for the next comparison. This is accomplished by looking through the array `n` times, `n` being the amount of elements in the array. ![animated gif of the bubble sort algorithm](https://s3.amazonaws.com/codecademy-content/programs/tdd-js/articles/BubbleSort.gif) This GIF shows a inverted implementation than #### Example Let us take the array `[5, 1, 4, 2, 8]`, and sort the array from lowest number to greatest number using bubble sort. In each step, elements written in bold are being compared. Three passes will be required. ##### First Pass [ **5 1** 4 2 8 ] -> [ **1 5** 4 2 8 ], Here, algorithm compares the first two elements, and swaps since 5 > 1. [ 1 **5 4** 2 8 ] -> [ 1 **4 5** 2 8 ], Swap since 5 > 4 [ 1 4 **5 2** 8 ] -> [ 1 4 **2 5** 8 ], Swap since 5 > 2 [ 1 4 2 **5 8** ] -> [ 1 4 2 **5 8** ], Now, since these elements are already in order (8 > 5), algorithm does not swap them. ##### Second Pass [ **1 4** 2 5 8 ] -> [ **1 4** 2 5 8 ] [ 1 **4 2** 5 8 ] -> [ 1 **2 4** 5 8 ], Swap since 4 > 2 [ 1 2 **4 5** 8 ] -> [ 1 2 **4 5** 8 ] [ 1 2 4 **5 8** ] -> [ 1 2 4 **5 8** ] Now, the array is already sorted, but the algorithm does not know if it is completed. The algorithm needs one whole pass without any swap to know it is sorted. ##### Third Pass [ **1 2** 4 5 8 ] -> [ **1 2** 4 5 8 ] [ 1 **2 4** 5 8 ] -> [ 1 **2 4** 5 8 ] [ 1 2 **4 5** 8 ] -> [ 1 2 **4 5** 8 ] [ 1 2 4 **5 8** ] -> [ 1 2 4 **5 8** ] This is the same for the forth and fifth passes. #### Code ```swift for i in 0.. [ **1 5** 4 2 8 ], Swaps since 5 > 1 [ 1 **5 4** 2 8 ] -> [ 1 **4 5** 2 8 ], Swap since 5 > 4 [ 1 4 **5 2** 8 ] -> [ 1 4 **2 5** 8 ], Swap since 5 > 2 [ 1 4 2 **5 8** ] -> [ 1 4 2 **5 8** ], Now, since these elements are already in order (8 > 5), algorithm does not swap them. *by the end of the first pass, the last element is guaranteed to be the largest* ##### Second Pass [ **1 4** 2 5 8 ] -> [ **1 4** 2 5 8 ] [ 1 **4 2** 5 8 ] -> [ 1 **2 4** 5 8 ], Swap since 4 > 2 [ 1 2 **4 5** 8 ] -> [ 1 2 **4 5** 8 ], As the first loop has occured once, the inner loop stops here, not comparing 5 with 8 ##### Third Pass [ **1 2** 4 5 8 ] -> [ **1 2** 4 5 8 ] [ 1 **2 4** 5 8 ] -> [ 1 **2 4** 5 8 ] again, stoping one comparison short ##### Fourth Pass [ **1 2** 4 5 8 ] -> [ **1 2** 4 5 8 ] There is no Fifth pass #### Conclusion Even with the proposed optimizations, this is still a terribly inefficient sorting algorithm. A good alternative is [Merge Sort](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Merge%20Sort), that not only is better performing, has a similar degree of dificulty to implement. *Updated for the Swift Algorithm Club by Julio Brazil* ##### Supporting Links [Code Pumpkin](https://codepumpkin.com/bubble-sort/) [Wikipedia](https://en.wikipedia.org/wiki/Bubble_sort) [GeeksforGeeks](https://www.geeksforgeeks.org/bubble-sort/) ================================================ FILE: Bucket Sort/BucketSort.playground/Contents.swift ================================================ // // BucketSort.playground // // Created by Barbara Rodeker on 4/4/16. // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included in all copies or substantial // portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE // OR OTHER DEALINGS IN THE SOFTWARE. // // ////////////////////////////////////// // MARK: Extensions ////////////////////////////////////// extension Int: IntConvertible, Sortable { public func toInt() -> Int { return self } } ////////////////////////////////////// // MARK: Playing code ////////////////////////////////////// let input = [1, 2, 4, 6, 10, 5] var buckets = [Bucket(capacity: 15), Bucket(capacity: 15), Bucket(capacity: 15)] let sortedElements = bucketSort(input, distributor: RangeDistributor(), sorter: InsertionSorter(), buckets: buckets) print(sortedElements) ================================================ FILE: Bucket Sort/BucketSort.playground/Sources/BucketSort.swift ================================================ // // BucketSort.swift // // Created by Barbara Rodeker on 4/4/16. // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included in all copies or substantial // portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE // OR OTHER DEALINGS IN THE SOFTWARE. // // ////////////////////////////////////// // MARK: Main algorithm ////////////////////////////////////// /** Performs bucket sort algorithm on the given input elements. [Bucket Sort Algorithm Reference](https://en.wikipedia.org/wiki/Bucket_sort) - Parameter elements: Array of Sortable elements - Parameter distributor: Performs the distribution of each element of a bucket - Parameter sorter: Performs the sorting inside each bucket, after all the elements are distributed - Parameter buckets: An array of buckets - Returns: A new array with sorted elements */ public func bucketSort(_ elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket]) -> [T] { precondition(allPositiveNumbers(elements)) precondition(enoughSpaceInBuckets(buckets, elements: elements)) var bucketsCopy = buckets for elem in elements { distributor.distribute(elem, buckets: &bucketsCopy) } var results = [T]() for bucket in bucketsCopy { results += bucket.sort(sorter) } return results } private func allPositiveNumbers(_ array: [T]) -> Bool { return array.filter { $0.toInt() >= 0 }.count > 0 } private func enoughSpaceInBuckets(_ buckets: [Bucket], elements: [T]) -> Bool { let maximumValue = elements.max()?.toInt() let totalCapacity = buckets.count * (buckets.first?.capacity)! guard let max = maximumValue else { return false } return totalCapacity >= max } ////////////////////////////////////// // MARK: Distributor ////////////////////////////////////// public protocol Distributor { func distribute(_ element: T, buckets: inout [Bucket]) } /* * An example of a simple distribution function that send every elements to * the bucket representing the range in which it fits.An * * If the range of values to sort is 0..<49 i.e, there could be 5 buckets of capacity = 10 * So every element will be classified by the ranges: * * - 0 ..< 10 * - 10 ..< 20 * - 20 ..< 30 * - 30 ..< 40 * - 40 ..< 50 * * By following the formula: element / capacity = #ofBucket */ public struct RangeDistributor: Distributor { public init() {} public func distribute(_ element: T, buckets: inout [Bucket]) { let value = element.toInt() let bucketCapacity = buckets.first!.capacity let bucketIndex = value / bucketCapacity buckets[bucketIndex].add(element) } } ////////////////////////////////////// // MARK: Sortable ////////////////////////////////////// public protocol IntConvertible { func toInt() -> Int } public protocol Sortable: IntConvertible, Comparable { } ////////////////////////////////////// // MARK: Sorter ////////////////////////////////////// public protocol Sorter { func sort(_ items: [T]) -> [T] } public struct InsertionSorter: Sorter { public init() {} public func sort(_ items: [T]) -> [T] { var results = items for i in 0 ..< results.count { var j = i while j > 0 && results[j-1] > results[j] { let auxiliar = results[j-1] results[j-1] = results[j] results[j] = auxiliar j -= 1 } } return results } } ////////////////////////////////////// // MARK: Bucket ////////////////////////////////////// public struct Bucket { var elements: [T] let capacity: Int public init(capacity: Int) { self.capacity = capacity elements = [T]() } public mutating func add(_ item: T) { if elements.count < capacity { elements.append(item) } } public func sort(_ algorithm: Sorter) -> [T] { return algorithm.sort(elements) } } ================================================ FILE: Bucket Sort/BucketSort.playground/contents.xcplayground ================================================ ================================================ FILE: Bucket Sort/BucketSort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Bucket Sort/BucketSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Bucket Sort/BucketSort.swift ================================================ // // BucketSort.swift // // Created by Barbara Rodeker on 4/4/16. // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included in all copies or substantial // portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN // AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE // OR OTHER DEALINGS IN THE SOFTWARE. // // ////////////////////////////////////// // MARK: Main algorithm ////////////////////////////////////// /** Performs bucket sort algorithm on the given input elements. [Bucket Sort Algorithm Reference](https://en.wikipedia.org/wiki/Bucket_sort) - Parameter elements: Array of Sortable elements - Parameter distributor: Performs the distribution of each element of a bucket - Parameter sorter: Performs the sorting inside each bucket, after all the elements are distributed - Parameter buckets: An array of buckets - Returns: A new array with sorted elements */ public func bucketSort(_ elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket]) -> [T] { precondition(allPositiveNumbers(elements)) precondition(enoughSpaceInBuckets(buckets, elements: elements)) var bucketsCopy = buckets for elem in elements { distributor.distribute(elem, buckets: &bucketsCopy) } var results = [T]() for bucket in bucketsCopy { results += bucket.sort(sorter) } return results } private func allPositiveNumbers(_ array: [T]) -> Bool { return array.filter { $0.toInt() >= 0 }.count > 0 } private func enoughSpaceInBuckets(_ buckets: [Bucket], elements: [T]) -> Bool { let maximumValue = elements.max()?.toInt() let totalCapacity = buckets.count * (buckets.first?.capacity)! guard let max = maximumValue else { return false } return totalCapacity >= max } ////////////////////////////////////// // MARK: Distributor ////////////////////////////////////// public protocol Distributor { func distribute(_ element: T, buckets: inout [Bucket]) } /* * An example of a simple distribution function that send every elements to * the bucket representing the range in which it fits.An * * If the range of values to sort is 0..<49 i.e, there could be 5 buckets of capacity = 10 * So every element will be classified by the ranges: * * - 0 ..< 10 * - 10 ..< 20 * - 20 ..< 30 * - 30 ..< 40 * - 40 ..< 50 * * By following the formula: element / capacity = #ofBucket */ public struct RangeDistributor: Distributor { public init() {} public func distribute(_ element: T, buckets: inout [Bucket]) { let value = element.toInt() let bucketCapacity = buckets.first!.capacity let bucketIndex = value / bucketCapacity buckets[bucketIndex].add(element) } } ////////////////////////////////////// // MARK: Sortable ////////////////////////////////////// public protocol IntConvertible { func toInt() -> Int } public protocol Sortable: IntConvertible, Comparable { } ////////////////////////////////////// // MARK: Sorter ////////////////////////////////////// public protocol Sorter { func sort(_ items: [T]) -> [T] } public struct InsertionSorter: Sorter { public init() {} public func sort(_ items: [T]) -> [T] { var results = items for i in 0 ..< results.count { var j = i while j > 0 && results[j-1] > results[j] { let auxiliar = results[j-1] results[j-1] = results[j] results[j] = auxiliar j -= 1 } } return results } } ////////////////////////////////////// // MARK: Bucket ////////////////////////////////////// public struct Bucket { var elements: [T] let capacity: Int public init(capacity: Int) { self.capacity = capacity elements = [T]() } public mutating func add(_ item: T) { if elements.count < capacity { elements.append(item) } } public func sort(_ algorithm: Sorter) -> [T] { return algorithm.sort(elements) } } ================================================ FILE: Bucket Sort/README.markdown ================================================ # Bucket Sort Bucket Sort, also known as Bin Sort, is a distributed sorting algorithm, which sort elements from an array by performing these steps: 1) Distribute the elements into buckets or bins. 2) Sort each bucket individually. 3) Merge the buckets in order to produce a sorted array as the result. See the algorithm in action [here](https://www.cs.usfca.edu/~galles/visualization/BucketSort.html) and [here](http://www.algostructure.com/sorting/bucketsort.php). The performance for execution time is: | Case | Performance | |:-------------: |:---------------:| | Worst | O(n^2) | | Best | Omega(n + k) | | Average | Theta(n + k) | Where **n** = the number of elements and **k** is the number of buckets. In the *best case*, the algorithm distributes the elements uniformly between buckets, a few elements are placed on each bucket and sorting the buckets is **O(1)**. Rearranging the elements is one more run through the initial list. In the *worst case*, the elements are sent all to the same bucket, making the process take **O(n^2)**. ## Pseudocode A [pseudocode](https://en.wikipedia.org/wiki/Bucket_sort#Pseudocode) of the algorithm can be as follows: function bucketSort(array, n) is buckets ← new array of n empty lists for i = 0 to (length(array)-1) do insert array[i] into buckets[msbits(array[i], k)] for i = 0 to n - 1 do nextSort(buckets[i]); return the concatenation of buckets[0], ...., buckets[n-1] ## Graphically explained 1) Distribute elements in buckets: ![distribution step](https://upload.wikimedia.org/wikipedia/commons/6/61/Bucket_sort_1.png) 2) Sorting inside every bucket and merging: ![sorting each bucket and merge](https://upload.wikimedia.org/wikipedia/commons/3/39/Bucket_sort_2.png) ## An example ### Input Suppose we have the following list of elements: `[2, 56, 4, 77, 26, 98, 55]`. Let's use 10 buckets. To determine the capacity of each bucket we need to know the *maximum element value*, in this case `98`. So the buckets are: * `bucket 1`: from 0 to 9 * `bucket 2`: from 10 to 19 * `bucket 3`: from 20 to 29 * and so on. ### Distribution Now we need to choose a distribution function. `bucketNumber = (elementValue / totalNumberOfBuckets) + 1` Such that by applying that function we distribute all the elements in the buckets. In our example it is like the following: 1. Apply the distribution function to `2`. `bucketNumber = (2 / 10) + 1 = 1` 2. Apply the distribution function to `56`. `bucketNumber = (56 / 10) + 1 = 6` 3. Apply the distribution function to `4`. `bucketNumber = (4 / 10) + 1 = 1` 4. Apply the distribution function to `77`. `bucketNumber = (77 / 10) + 1 = 8` 5. Apply the distribution function to `26`. `bucketNumber = (26 / 10) + 1 = 3` 6. Apply the distribution function to `98`. `bucketNumber = (98 / 10) + 1 = 10` 7. Apply the distribution function to `55`. `bucketNumber = (55 / 10) + 1 = 6` Our buckets will be filled now: **1** : `[2, 4]` **2** : `[]` **3** : `[26]` **4** : `[]` **5** : `[]` **6** : `[55, 56]` **7** : `[]` **8** : `[77]` **9** : `[]` **10** : `[98]` We can choose to insert the elements in every bucket in order, or sort every bucket after distributing all the elements. ### Put the elements back in the list Finally we go through all the buckets and put the elements back in the list: `[2, 4, 26, 55, 56, 77, 98]` ## Swift implementation Here is a diagram that shows the functions, data structures and protocols for our bucker sort implementation: ![classes](Docs/BucketSort.png) #### Main function `bucketSort()` is a generic function that can apply the algorithm to any element of type `T`, as long as `T` is `Sortable`. ```swift public func bucketSort(elements: [T], distributor: Distributor, sorter: Sorter, buckets: [Bucket]) -> [T] { precondition(allPositiveNumbers(elements)) precondition(enoughSpaceInBuckets(buckets, elements: elements)) var bucketsCopy = buckets for elem in elements { distributor.distribute(elem, buckets: &bucketsCopy) } var results = [T]() for bucket in bucketsCopy { results += bucket.sort(sorter) } return results } ``` #### Bucket ```swift public struct Bucket { var elements: [T] let capacity: Int public init(capacity: Int) { self.capacity = capacity elements = [T]() } public mutating func add(item: T) { if (elements.count < capacity) { elements.append(item) } } public func sort(algorithm: Sorter) -> [T] { return algorithm.sort(elements) } } ``` #### Sortable ```swift public protocol Sortable: IntConvertible, Comparable { } ``` #### IntConvertible The algorithm is designed to sort integers, so all the elements to be sorted should be mapped to an integer value. ```swift public protocol IntConvertible { func toInt() -> Int } ``` #### Sorter ```swift public protocol Sorter { func sort(items: [T]) -> [T] } ``` #### Distributor ```swift public protocol Distributor { func distribute(element: T, inout buckets: [Bucket]) } ``` ### Custom Sorter and Distributor The current implementation make use of the following implementations for *Sorter* and *Distributor*. *Sorter* ```swift public struct InsertionSorter: Sorter { public func sort(items: [T]) -> [T] { var results = items for i in 0 ..< results.count { var j = i while ( j > 0 && results[j-1] > results[j]) { let auxiliar = results[j-1] results[j-1] = results[j] results[j] = auxiliar j -= 1 } } return results } } ``` *Distributor* ```swift /* * An example of a simple distribution function that send every elements to * the bucket representing the range in which it fits. * * If the range of values to sort is 0..<49 i.e, there could be 5 buckets of capacity = 10 * So every element will be classified by the ranges: * * - 0 ..< 10 * - 10 ..< 20 * - 20 ..< 30 * - 30 ..< 40 * - 40 ..< 50 * * By following the formula: element / capacity = #ofBucket */ public struct RangeDistributor: Distributor { public func distribute(element: T, inout buckets: [Bucket]) { let value = element.toInt() let bucketCapacity = buckets.first!.capacity let bucketIndex = value / bucketCapacity buckets[bucketIndex].add(element) } } ``` ### Make your own version By reusing this code and implementing your own *Sorter* and *Distributor* you can experiment with different versions. ## Other variations of Bucket Sort The following are some of the variation to the general [Bucket Sort](https://en.wikipedia.org/wiki/Bucket_sort) implemented here: - [Proxmap Sort](https://en.wikipedia.org/wiki/Bucket_sort#ProxmapSort) - [Histogram Sort](https://en.wikipedia.org/wiki/Bucket_sort#Histogram_sort) - [Postman Sort](https://en.wikipedia.org/wiki/Bucket_sort#Postman.27s_sort) - [Shuffle Sort](https://en.wikipedia.org/wiki/Bucket_sort#Shuffle_sort) *Written for Swift Algorithm Club by Barbara Rodeker. Images from Wikipedia. Updated by Bruno Scheele.* ================================================ FILE: Bucket Sort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Bucket Sort/Tests/Tests.swift ================================================ // // TestTests.swift // TestTests // // Created by Barbara Rodeker on 4/5/16. // Copyright © 2016 Barbara M. Rodeker. All rights reserved. // import XCTest class TestTests: XCTestCase { var smallArray: [Int]? let total = 400 let maximum = 1000 var largeArray: [Int]? var sparsedArray: [Int]? override func setUp() { super.setUp() smallArray = [8, 3, 33, 0, 12, 8, 2, 18] largeArray = [Int]() for _ in 0.. [Int] { let value = (elements.max()?.toInt())! + 1 let capacityRequired = Int( ceil( Double(value) / Double(totalBuckets) ) ) var buckets = [Bucket]() for _ in 0..(capacity: capacityRequired)) } let results = bucketSort(smallArray!, distributor: RangeDistributor(), sorter: InsertionSorter(), buckets: buckets) return results } func isSorted(_ array: [Int]) -> Bool { var index = 0 var sorted = true while index < (array.count - 1) && sorted { if array[index] > array[index+1] { sorted = false } index += 1 } return sorted } } ////////////////////////////////////// // MARK: Extensions ////////////////////////////////////// extension Int: IntConvertible, Sortable { public func toInt() -> Int { return self } } ================================================ FILE: Bucket Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 76E90BEB1CBFB317009E04FE /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E90BEA1CBFB317009E04FE /* Tests.swift */; }; 76E90BED1CBFB322009E04FE /* BucketSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76E90BEC1CBFB322009E04FE /* BucketSort.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 76E90BEA1CBFB317009E04FE /* Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = SOURCE_ROOT; }; 76E90BEC1CBFB322009E04FE /* BucketSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BucketSort.swift; path = ../BucketSort.swift; sourceTree = SOURCE_ROOT; }; 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 76E90BEA1CBFB317009E04FE /* Tests.swift */, 76E90BEC1CBFB322009E04FE /* BucketSort.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0900; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 76E90BEB1CBFB317009E04FE /* Tests.swift in Sources */, 76E90BED1CBFB322009E04FE /* BucketSort.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Bucket Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Bucket Sort/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Bucket Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Closest Pair/ClosestPair.playground/Contents.swift ================================================ //Created by Ahmed Nader (github: AhmedNader42) on 4/4/18. func ClosestPairOf(points: [Point]) -> (minimum:Double, firstPoint:Point, secondPoint:Point) { var innerPoints = mergeSort(points, sortAccording : true) let result = ClosestPair(&innerPoints, innerPoints.count) return (result.minValue, result.firstPoint, result.secondPoint) } func ClosestPair(_ p : inout [Point],_ n : Int) -> (minValue: Double,firstPoint: Point,secondPoint: Point) { // Brute force if only 3 points (To end recursion) if n <= 3 { var i=0, j = i+1 var minDist = Double.infinity var newFirst:Point? = nil var newSecond:Point? = nil while i min { break } if dist(strip[i], strip[x]) < temp { temp = dist(strip[i], strip[x]) tempFirst = strip[i] tempSecond = strip[x] } x+=1 } i+=1 } if temp < min { min = temp; first = tempFirst second = tempSecond } return (min, first, second) } // MergeSort the array (Taken from Swift Algorithms Club with // minor addition) // sortAccodrding : true -> x, false -> y. func mergeSort(_ array: [Point], sortAccording : Bool) -> [Point] { guard array.count > 1 else { return array } let middleIndex = array.count / 2 let leftArray = mergeSort(Array(array[0.. [Point] { var compare : (Point, Point) -> Bool // Choose to compare with X or Y. if sortAccording { compare = { p1,p2 in return p1.x < p2.x } } else { compare = { p1, p2 in return p1.y < p2.y } } var leftIndex = 0 var rightIndex = 0 var orderedPile = [Point]() if orderedPile.capacity < leftPile.count + rightPile.count { orderedPile.reserveCapacity(leftPile.count + rightPile.count) } while true { guard leftIndex < leftPile.endIndex else { orderedPile.append(contentsOf: rightPile[rightIndex.. Double { let equation:Double = (((a.x-b.x)*(a.x-b.x))) + (((a.y-b.y)*(a.y-b.y))) return equation.squareRoot() } var a = Point(0,2) var b = Point(6,67) var c = Point(43,71) var d = Point(1000,1000) var e = Point(39,107) var f = Point(2000,2000) var g = Point(3000,3000) var h = Point(4000,4000) var points = [a,b,c,d,e,f,g,h] let endResult = ClosestPairOf(points: points) print("Minimum Distance : \(endResult.minimum), The two points : (\(endResult.firstPoint.x ),\(endResult.firstPoint.y)), (\(endResult.secondPoint.x),\(endResult.secondPoint.y))") ================================================ FILE: Closest Pair/ClosestPair.playground/contents.xcplayground ================================================ ================================================ FILE: Closest Pair/ClosestPair.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Closest Pair/ClosestPair.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Closest Pair/README.markdown ================================================ # ClosestPair Closest Pair is an algorithm that finds the closest pair of a given array of points By utilizing the Divide and Conquer methodology of solving problems so that it reaches the correct solution with O(nlogn) complexity. ![Given points and we're required to find the two red ones](Images/1200px-Closest_pair_of_points.png) As we see in the above image there are an array of points and we need to find the closest two, But how do we do that without having to compare each two points which results in a whopping O(n^2) complexity? Here is the main algorithm (Steps) we'll follow. - Sort the array according to their position on the X-axis so that they are sorted in the array as they are naturally in math. ```swift var innerPoints = mergeSort(points, sortAccording : true) ``` - Divide the points into two arrays Left, Right and keep dividing until you reach to only having 3 points in your array. - The base case is you have less than 3 points compare those against each other (Brute force) then return the minimum distance you found and the two points. - Now we get the first observation in the below image, There could be 2 points both very close to each other and indeed those two are the closest pair but since our algorithm so far divides from the middle ```swift let line:Double = (p[mid].x + p[mid+1].x)/2 ``` and just recursively calls itself until it reaches the base case we don't detect those points. ![ Points lying near the division line](Images/Case.png) - To solve this we start by sorting the array on the Y-axis to get the points in their natural order and then we start getting the difference between the X position of the point and the line we drew to divide and if it is less than the min we got so far from the recursion we add it to the strip ```swift var strip = [Point]() var i=0, j = 0 while i min { break } if dist(strip[i], strip[x]) < temp { temp = dist(strip[i], strip[x]) tempFirst = strip[i] tempSecond = strip[x] } x+=1 } i+=1 } ``` - Of course not every time you end up with the same shape but this is the worst case and it's rare to happen so in reality you end up with far less points valid for comparison and this is why the algorithm gets performance in addition to the sorting tricks we did. - Compare the points in the strip and if you find a smaller distance replace the current one with it. So this is the rundown of how the algorithm works and you could see the fun little math tricks used to optimize this and we end up with O(nlogn) complexity mainly because of the sorting. ## See also See the playground to play around with the implementation of the algorithm [Wikipedia](https://en.wikipedia.org/wiki/Closest_pair_of_points_problem) *Written for Swift Algorithm Club by [Ahmed Nader](https://github.com/ahmednader42)* ================================================ FILE: Comb Sort/Comb Sort.playground/Contents.swift ================================================ // Comb Sort Function // Created by Stephen Rutstein // 7-16-2016 import Foundation // Test Comb Sort with small array of ten values let array = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] combSort(array) // Test Comb Sort with large array of 1000 random values var bigArray = [Int](repeating: 0, count: 1000) var i = 0 while i < 1000 { bigArray[i] = Int(arc4random_uniform(1000) + 1) i += 1 } combSort(bigArray) ================================================ FILE: Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift ================================================ // Comb Sort.swift // Comb Sort // // Created by Stephen.Rutstein on 7/16/16. // Copyright © 2016 Stephen.Rutstein. All rights reserved. // import Foundation public func combSort(_ input: [T]) -> [T] { var copy: [T] = input var gap = copy.count let shrink = 1.3 while gap > 1 { gap = (Int)(Double(gap) / shrink) if gap < 1 { gap = 1 } var index = 0 while !(index + gap >= copy.count) { if copy[index] > copy[index + gap] { copy.swapAt(index, index + gap) } index += 1 } } return copy } fileprivate func swap(a: inout T, b: inout T) { let temp = a a = b b = temp } ================================================ FILE: Comb Sort/Comb Sort.playground/contents.xcplayground ================================================ ================================================ FILE: Comb Sort/Comb Sort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Comb Sort/Comb Sort.swift ================================================ // Comb Sort.swift // Comb Sort // // Created by Stephen.Rutstein on 7/16/16. // Copyright © 2016 Stephen.Rutstein. All rights reserved. // import Foundation public func combSort(_ input: [T]) -> [T] { var copy: [T] = input var gap = copy.count let shrink = 1.3 while gap > 1 { gap = (Int)(Double(gap) / shrink) if gap < 1 { gap = 1 } var index = 0 while !(index + gap >= copy.count) { if copy[index] > copy[index + gap] { copy.swapAt(index, index + gap) } index += 1 } } return copy } fileprivate func swap(a: inout T, b: inout T) { let temp = a a = b b = temp } ================================================ FILE: Comb Sort/README.markdown ================================================ # Comb Sort A common issue for Bubble Sort is when small values are located near the end of an array. This problem severely slows down Bubble Sort, as it must move the small value -- or _turtle_ -- through nearly the entire array. Bubble Sort works by checking the current index of an array against the next index, and when those two values are unsorted, they are swapped into place. As a result, the values bubble into their rightful place within the array. Comb Sort improves upon Bubble Sort by dealing with these turtles near the end of the array. The value of the current index of the array is compared against one a set distance away. This removes a worst-case scenario of Bubble Sort, and greatly improves on the time complexity of Bubble Sort. ## Example A step-by-step example of how Comb Sort works, and differs from Bubble Sort, can be seen [here](http://www.exforsys.com/tutorials/c-algorithms/comb-sort.html). Here is a visual to see Comb Sort in effect: ![](https://upload.wikimedia.org/wikipedia/commons/4/46/Comb_sort_demo.gif) ## Algorithm Similar to Bubble Sort, two values within an array are compared. When the lower index value is larger than the higher index value, and thus out of place within the array, they are swapped. Unlike Bubble Sort, the value being compared against is a set distance away. This value -- the _gap_ -- is slowly decreased through iterations. ## The Code Here is a Swift implementation of Comb Sort: ```swift func combSort (input: [Int]) -> [Int] { var copy: [Int] = input var gap = copy.count let shrink = 1.3 while gap > 1 { gap = (Int)(Double(gap) / shrink) if gap < 1 { gap = 1 } var index = 0 while !(index + gap >= copy.count) { if copy[index] > copy[index + gap] { swap(©[index], ©[index + gap]) } index += 1 } } return copy } ``` This code can be tested in a playground by calling this method with a paramaterized array to sort: ```swift combSort(example_array_of_values) ``` This will sort the values of the array into ascending order -- increasing in value. ## Performance Comb Sort was created to improve upon the worst case time complexity of Bubble Sort. With Comb Sort, the worst case scenario for performance is polynomial -- O(n^2). At best though, Comb Sort performs at O(n logn) time complexity -- loglinear. This creates a drastic improvement over Bubble Sort's performance. Similar to Bubble Sort, the space complexity for Comb Sort is constant -- O(1). This is extremely space efficient as it sorts the array in place. ## Additional Resources [Comb Sort Wikipedia](https://en.wikipedia.org/wiki/Comb_sort) *Written for the _Swift Algorithm Club_ by [Stephen Rutstein](https://github.com/srutstein21)* ================================================ FILE: Comb Sort/Tests/CombSortTests.swift ================================================ // // CombSortTests.swift // Tests // // Created by theng on 2017-01-09. // Copyright © 2017 Swift Algorithm Club. All rights reserved. // import XCTest class CombSortTests: XCTestCase { var sequence: [Int]! let expectedSequence: [Int] = [-12, -10, -1, 2, 9, 32, 55, 67, 89, 101] override func setUp() { super.setUp() sequence = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] } override func tearDown() { super.tearDown() } func testCombSort() { let sortedSequence = combSort(sequence) XCTAssertEqual(sortedSequence, expectedSequence) } } ================================================ FILE: Comb Sort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Comb Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 056E927E1E24852900B30F52 /* CombSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056E927D1E24852900B30F52 /* CombSortTests.swift */; }; 056E92841E248A4000B30F52 /* Comb Sort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056E92831E248A4000B30F52 /* Comb Sort.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 056E92751E2483D300B30F52 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 056E92791E2483D300B30F52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 056E927D1E24852900B30F52 /* CombSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombSortTests.swift; sourceTree = ""; }; 056E92831E248A4000B30F52 /* Comb Sort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Comb Sort.swift"; path = "../Comb Sort.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 056E92721E2483D300B30F52 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 056E92581E24836C00B30F52 = { isa = PBXGroup; children = ( 056E92761E2483D300B30F52 /* Tests */, 056E92621E24836C00B30F52 /* Products */, ); sourceTree = ""; }; 056E92621E24836C00B30F52 /* Products */ = { isa = PBXGroup; children = ( 056E92751E2483D300B30F52 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 056E92761E2483D300B30F52 /* Tests */ = { isa = PBXGroup; children = ( 056E92831E248A4000B30F52 /* Comb Sort.swift */, 056E92791E2483D300B30F52 /* Info.plist */, 056E927D1E24852900B30F52 /* CombSortTests.swift */, ); name = Tests; sourceTree = SOURCE_ROOT; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 056E92741E2483D300B30F52 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 056E927A1E2483D300B30F52 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 056E92711E2483D300B30F52 /* Sources */, 056E92721E2483D300B30F52 /* Frameworks */, 056E92731E2483D300B30F52 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = 056E92751E2483D300B30F52 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 056E92591E24836C00B30F52 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0820; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 056E92741E2483D300B30F52 = { CreatedOnToolsVersion = 8.2; LastSwiftMigration = 0820; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 056E925C1E24836C00B30F52 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 056E92581E24836C00B30F52; productRefGroup = 056E92621E24836C00B30F52 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 056E92741E2483D300B30F52 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 056E92731E2483D300B30F52 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 056E92711E2483D300B30F52 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 056E927E1E24852900B30F52 /* CombSortTests.swift in Sources */, 056E92841E248A4000B30F52 /* Comb Sort.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 056E926C1E24836C00B30F52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; }; name = Debug; }; 056E926D1E24836C00B30F52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.2; }; name = Release; }; 056E927B1E2483D300B30F52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "Swift-Algorithm-Club.Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; }; name = Debug; }; 056E927C1E2483D300B30F52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "Swift-Algorithm-Club.Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 056E925C1E24836C00B30F52 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 056E926C1E24836C00B30F52 /* Debug */, 056E926D1E24836C00B30F52 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 056E927A1E2483D300B30F52 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 056E927B1E2483D300B30F52 /* Debug */, 056E927C1E2483D300B30F52 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 056E92591E24836C00B30F52 /* Project object */; } ================================================ FILE: Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Combinatorics/Combinatorics.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif /* Calculates n! */ func factorial(_ n: Int) -> Int { var n = n var result = 1 while n > 1 { result *= n n -= 1 } return result } factorial(5) factorial(20) /* Calculates P(n, k), the number of permutations of n distinct symbols in groups of size k. */ func permutations(_ n: Int, _ k: Int) -> Int { var n = n var answer = n for _ in 1..(_ a: [T], _ n: Int) { if n == 0 { print(a) // display the current permutation } else { var a = a permuteWirth(a, n - 1) for i in 0.. Int { return permutations(n, k) / factorial(k) } combinations(3, choose: 2) combinations(28, choose: 5) print("\nCombinations:") for i in 1...20 { print("\(20)-choose-\(i) = \(combinations(20, choose: i))") } /* Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose k things out of n possibilities. */ func quickBinomialCoefficient(_ n: Int, choose k: Int) -> Int { var result = 1 for i in 0.. { let columns: Int let rows: Int private var array: [T] init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows array = Array(repeating: initialValue, count: rows*columns) } subscript(column: Int, row: Int) -> T { get { return array[row*columns + column] } set { array[row*columns + column] = newValue } } } /* Calculates C(n, k), or "n-choose-k", i.e. the number of ways to choose k things out of n possibilities. Thanks to the dynamic programming, this algorithm from Skiena allows for the calculation of much larger numbers, at the cost of temporary storage space for the cached values. */ func binomialCoefficient(_ n: Int, choose k: Int) -> Int { var bc = Array(repeating: Array(repeating: 0, count: n + 1), count: n + 1) for i in 0...n { bc[i][0] = 1 bc[i][i] = 1 } if n > 0 { for i in 1...n { for j in 1.. ================================================ FILE: Combinatorics/Combinatorics.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Combinatorics/README.markdown ================================================ # Permutations A *permutation* is a certain arrangement of the objects from a collection. For example, if we have the first five letters from the alphabet, then this is a permutation: a, b, c, d, e This is another permutation: b, e, d, a, c For a collection of `n` objects, there are `n!` possible permutations, where `!` is the "factorial" function. So for our collection of five letters, the total number of permutations you can make is: 5! = 5 * 4 * 3 * 2 * 1 = 120 A collection of six items has `6! = 720` permutations. For ten items, it is `10! = 3,628,800`. That adds up quick! Where does this `n!` come from? The logic is as follows: we have a collection of five letters that we want to put in some order. To do this, you need to pick up these letters one-by-one. Initially, you have the choice of five letters: `a, b, c, d, e`. That gives 5 possibilities. After picking the first letter, you only have four letters left to choose from. That gives `5 * 4 = 20` possibilities: a+b b+a c+a d+a e+a a+c b+c c+b d+b e+b a+d b+d c+d d+c e+c a+e b+e c+e d+e e+d After picking the second letter, there are only three letters left to choose from. And so on... When you get to the last letter, you don't have any choice because there is only one letter left. That's why the total number of possibilities is `5 * 4 * 3 * 2 * 1`. To calculate the factorial in Swift: ```swift func factorial(_ n: Int) -> Int { var n = n var result = 1 while n > 1 { result *= n n -= 1 } return result } ``` Try it out in a playground: ```swift factorial(5) // returns 120 ``` Note that `factorial(20)` is the largest number you can calculate with this function, or you'll get integer overflow. Let's say that from that collection of five letters you want to choose only 3 elements. How many possible ways can you do this? Well, that works the same way as before, except that you stop after the third letter. So now the number of possibilities is `5 * 4 * 3 = 60`. The formula for this is: n! P(n, k) = -------- (n - k)! where `n` is the size of your collection and `k` is the size of the group that you're selecting. In our example, `P(5, 3) = 5! / (5 - 3)! = 120 / 2 = 60`. You could implement this in terms of the `factorial()` function from earlier, but there's a problem. Remember that `factorial(20)` is the largest possible number it can handle, so you could never calculate `P(21, 3)`, for example. Here is an algorithm that can deal with larger numbers: ```swift func permutations(_ n: Int, _ k: Int) -> Int { var n = n var answer = n for _ in 1..(_ a: [T], _ n: Int) { if n == 0 { print(a) // display the current permutation } else { var a = a permuteWirth(a, n - 1) for i in 0.. Int { return permutations(n, k) / factorial(k) } ``` Use it like this: ```swift combinations(28, choose: 5) // prints 98280 ``` Because this uses the `permutations()` and `factorial()` functions under the hood, you're still limited by how large these numbers can get. For example, `combinations(30, 15)` is "only" `155,117,520` but because the intermediate results don't fit into a 64-bit integer, you can't calculate it with the given function. There's a faster approach to calculate `C(n, k)` in **O(k)** time and **O(1)** extra space. The idea behind it is that the formula for `C(n, k)` is: n! n * (n - 1) * ... * 1 C(n, k) = ------------- = ------------------------------------------ (n - k)! * k! (n - k) * (n - k - 1) * ... * 1 * k! After the reduction of fractions, we get the following formula: n * (n - 1) * ... * (n - k + 1) (n - 0) * (n - 1) * ... * (n - k + 1) C(n, k) = --------------------------------------- = ----------------------------------------- k! (0 + 1) * (1 + 1) * ... * (k - 1 + 1) We can implement this formula as follows: ```swift func quickBinomialCoefficient(_ n: Int, choose k: Int) -> Int { var result = 1 for i in 0.. Int { var bc = Array(repeating: Array(repeating: 0, count: n + 1), count: n + 1) for i in 0...n { bc[i][0] = 1 bc[i][i] = 1 } if n > 0 { for i in 1...n { for j in 1.. Bool { let screenBounds = UIScreen.main.bounds window = UIWindow(frame: screenBounds) let viewController = UIViewController() viewController.view = View(frame: (window?.frame)!) viewController.view.backgroundColor = .white window?.rootViewController = viewController window?.makeKeyAndVisible() return true } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } } ================================================ FILE: Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" }, { "idiom" : "ios-marketing", "size" : "1024x1024", "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: Convex Hull/Convex Hull/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UIRequiresFullScreen UIStatusBarHidden UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Convex Hull/Convex Hull/View.swift ================================================ // // View.swift // Convex Hull // // Created by Jaap Wijnen on 19/02/2017. // Copyright © 2017 Workmoose. All rights reserved. // import UIKit class View: UIView { let MAX_POINTS = 100 var points = [CGPoint]() var convexHull = [CGPoint]() override init(frame: CGRect) { super.init(frame: frame) generateRandomPoints() quickHull(points: points) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func generateRandomPoints() { for _ in 0.. Bool in return a.x < b.x } } func quickHull(points: [CGPoint]) { var pts = points // Assume points has at least 2 points // Assume list is ordered on x // left most point let p1 = pts.removeFirst() // right most point let p2 = pts.removeLast() // p1 and p2 are outer most points and thus are part of the hull convexHull.append(p1) convexHull.append(p2) // points to the right of oriented line from p1 to p2 var s1 = [CGPoint]() // points to the right of oriented line from p2 to p1 var s2 = [CGPoint]() // p1 to p2 line let lineVec1 = CGPoint(x: p2.x - p1.x, y: p2.y - p1.y) for p in pts { // per point check if point is to right or left of p1 to p2 line let pVec1 = CGPoint(x: p.x - p1.x, y: p.y - p1.y) let sign1 = lineVec1.x * pVec1.y - pVec1.x * lineVec1.y // cross product to check on which side of the line point p is. if sign1 > 0 { // right of p1 p2 line (in a normal xy coordinate system this would be < 0 but due to the weird iPhone screen coordinates this is > 0 s1.append(p) } else { // right of p2 p1 line s2.append(p) } } // find new hull points findHull(s1, p1, p2) findHull(s2, p2, p1) } func findHull(_ points: [CGPoint], _ p1: CGPoint, _ p2: CGPoint) { // if set of points is empty there are no points to the right of this line so this line is part of the hull. if points.isEmpty { return } var pts = points var maxDist: CGFloat = -1 var maxPoint: CGPoint = pts.first! for p in pts { // for every point check the distance from our line let dist = distance(from: p, to: (p1, p2)) if dist > maxDist { // if distance is larger than current maxDist remember new point p maxDist = dist maxPoint = p } } convexHull.insert(maxPoint, at: convexHull.index(of: p1)! + 1) // insert point with max distance from line in the convexHull after p1 pts.remove(at: pts.index(of: maxPoint)!) // remove maxPoint from points array as we are going to split this array in points left and right of the line // points to the right of oriented line from p1 to maxPoint var s1 = [CGPoint]() // points to the right of oriented line from maxPoint to p2 var s2 = [CGPoint]() // p1 to maxPoint line let lineVec1 = CGPoint(x: maxPoint.x - p1.x, y: maxPoint.y - p1.y) // maxPoint to p2 line let lineVec2 = CGPoint(x: p2.x - maxPoint.x, y: p2.y - maxPoint.y) for p in pts { let pVec1 = CGPoint(x: p.x - p1.x, y: p.y - p1.y) // vector from p1 to p let sign1 = lineVec1.x * pVec1.y - pVec1.x * lineVec1.y // sign to check is p is to the right or left of lineVec1 let pVec2 = CGPoint(x: p.x - maxPoint.x, y: p.y - maxPoint.y) // vector from p2 to p let sign2 = lineVec2.x * pVec2.y - pVec2.x * lineVec2.y // sign to check is p is to the right or left of lineVec2 if sign1 > 0 { // right of p1 maxPoint line s1.append(p) } else if sign2 > 0 { // right of maxPoint p2 line s2.append(p) } } // find new hull points findHull(s1, p1, maxPoint) findHull(s2, maxPoint, p2) } func distance(from p: CGPoint, to line: (CGPoint, CGPoint)) -> CGFloat { // If line.0 and line.1 are the same point, they don't define a line (and, besides, // would cause division by zero in the distance formula). Return the distance between // line.0 and point p instead. if line.0 == line.1 { return sqrt(pow(p.x - line.0.x, 2) + pow(p.y - line.0.y, 2)) } // from Deza, Michel Marie; Deza, Elena (2013), Encyclopedia of Distances (2nd ed.), Springer, p. 86, ISBN 9783642309588 return abs((line.1.y - line.0.y) * p.x - (line.1.x - line.0.x) * p.y + line.1.x * line.0.y - line.1.y * line.0.x) / sqrt(pow(line.1.y - line.0.y, 2) + pow(line.1.x - line.0.x, 2)) } override func draw(_ rect: CGRect) { let context = UIGraphicsGetCurrentContext() // Draw hull let lineWidth: CGFloat = 2.0 context!.setFillColor(UIColor.black.cgColor) context!.setLineWidth(lineWidth) context!.setStrokeColor(UIColor.red.cgColor) context!.setFillColor(UIColor.black.cgColor) let firstPoint = convexHull.first! context!.move(to: firstPoint) for p in convexHull.dropFirst() { context!.addLine(to: p) } context!.addLine(to: firstPoint) context!.strokePath() // Draw points for p in points { let radius: CGFloat = 5 let circleRect = CGRect(x: p.x - radius, y: p.y - radius, width: 2 * radius, height: 2 * radius) context!.fillEllipse(in: circleRect) } } } ================================================ FILE: Convex Hull/Convex Hull.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 1CB614301F89456C00A14493 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CB6142F1F89456C00A14493 /* Tests.swift */; }; 1CB614371F8945B300A14493 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6D68CB1E599CF100161780 /* View.swift */; }; 8E6D68BA1E59989400161780 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6D68B91E59989400161780 /* AppDelegate.swift */; }; 8E6D68C11E59989400161780 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8E6D68C01E59989400161780 /* Assets.xcassets */; }; 8E6D68C41E59989400161780 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8E6D68C21E59989400161780 /* LaunchScreen.storyboard */; }; 8E6D68CC1E599CF100161780 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E6D68CB1E599CF100161780 /* View.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 1CB614321F89456C00A14493 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 8E6D68AE1E59989400161780 /* Project object */; proxyType = 1; remoteGlobalIDString = 8E6D68B51E59989400161780; remoteInfo = "Convex Hull"; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 1CB6142D1F89456C00A14493 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 1CB6142F1F89456C00A14493 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 1CB614311F89456C00A14493 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8E6D68B61E59989400161780 /* Convex Hull.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Convex Hull.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 8E6D68B91E59989400161780 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 8E6D68C01E59989400161780 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 8E6D68C31E59989400161780 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 8E6D68C51E59989400161780 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 8E6D68CB1E599CF100161780 /* View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 1CB6142A1F89456C00A14493 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 8E6D68B31E59989400161780 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 1CB6142E1F89456C00A14493 /* Tests */ = { isa = PBXGroup; children = ( 1CB6142F1F89456C00A14493 /* Tests.swift */, 1CB614311F89456C00A14493 /* Info.plist */, ); path = Tests; sourceTree = ""; }; 8E6D68AD1E59989400161780 = { isa = PBXGroup; children = ( 8E6D68B81E59989400161780 /* Convex Hull */, 1CB6142E1F89456C00A14493 /* Tests */, 8E6D68B71E59989400161780 /* Products */, ); sourceTree = ""; }; 8E6D68B71E59989400161780 /* Products */ = { isa = PBXGroup; children = ( 8E6D68B61E59989400161780 /* Convex Hull.app */, 1CB6142D1F89456C00A14493 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 8E6D68B81E59989400161780 /* Convex Hull */ = { isa = PBXGroup; children = ( 8E6D68B91E59989400161780 /* AppDelegate.swift */, 8E6D68CB1E599CF100161780 /* View.swift */, 8E6D68C01E59989400161780 /* Assets.xcassets */, 8E6D68C21E59989400161780 /* LaunchScreen.storyboard */, 8E6D68C51E59989400161780 /* Info.plist */, ); path = "Convex Hull"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 1CB6142C1F89456C00A14493 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 1CB614341F89456C00A14493 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 1CB614291F89456C00A14493 /* Sources */, 1CB6142A1F89456C00A14493 /* Frameworks */, 1CB6142B1F89456C00A14493 /* Resources */, ); buildRules = ( ); dependencies = ( 1CB614331F89456C00A14493 /* PBXTargetDependency */, ); name = Tests; productName = Tests; productReference = 1CB6142D1F89456C00A14493 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 8E6D68B51E59989400161780 /* Convex Hull */ = { isa = PBXNativeTarget; buildConfigurationList = 8E6D68C81E59989400161780 /* Build configuration list for PBXNativeTarget "Convex Hull" */; buildPhases = ( 8E6D68B21E59989400161780 /* Sources */, 8E6D68B31E59989400161780 /* Frameworks */, 8E6D68B41E59989400161780 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Convex Hull"; productName = "Convex Hull"; productReference = 8E6D68B61E59989400161780 /* Convex Hull.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 8E6D68AE1E59989400161780 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0900; LastUpgradeCheck = 1000; ORGANIZATIONNAME = Workmoose; TargetAttributes = { 1CB6142C1F89456C00A14493 = { CreatedOnToolsVersion = 9.0; ProvisioningStyle = Automatic; TestTargetID = 8E6D68B51E59989400161780; }; 8E6D68B51E59989400161780 = { CreatedOnToolsVersion = 8.2.1; DevelopmentTeam = 4SQG5NJNPF; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 8E6D68B11E59989400161780 /* Build configuration list for PBXProject "Convex Hull" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 8E6D68AD1E59989400161780; productRefGroup = 8E6D68B71E59989400161780 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 8E6D68B51E59989400161780 /* Convex Hull */, 1CB6142C1F89456C00A14493 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 1CB6142B1F89456C00A14493 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 8E6D68B41E59989400161780 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 8E6D68C41E59989400161780 /* LaunchScreen.storyboard in Resources */, 8E6D68C11E59989400161780 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 1CB614291F89456C00A14493 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 1CB614371F8945B300A14493 /* View.swift in Sources */, 1CB614301F89456C00A14493 /* Tests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 8E6D68B21E59989400161780 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8E6D68BA1E59989400161780 /* AppDelegate.swift in Sources */, 8E6D68CC1E599CF100161780 /* View.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 1CB614331F89456C00A14493 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 8E6D68B51E59989400161780 /* Convex Hull */; targetProxy = 1CB614321F89456C00A14493 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 8E6D68C21E59989400161780 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 8E6D68C31E59989400161780 /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 1CB614351F89456C00A14493 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = Tests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mnespor.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Convex Hull.app/Convex Hull"; }; name = Debug; }; 1CB614361F89456C00A14493 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = Tests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mnespor.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Convex Hull.app/Convex Hull"; }; name = Release; }; 8E6D68C61E59989400161780 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.2; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 8E6D68C71E59989400161780 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 8E6D68C91E59989400161780 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = 4SQG5NJNPF; INFOPLIST_FILE = "Convex Hull/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "workmoose.Convex-Hull"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Debug; }; 8E6D68CA1E59989400161780 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = 4SQG5NJNPF; INFOPLIST_FILE = "Convex Hull/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "workmoose.Convex-Hull"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 1CB614341F89456C00A14493 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 1CB614351F89456C00A14493 /* Debug */, 1CB614361F89456C00A14493 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 8E6D68B11E59989400161780 /* Build configuration list for PBXProject "Convex Hull" */ = { isa = XCConfigurationList; buildConfigurations = ( 8E6D68C61E59989400161780 /* Debug */, 8E6D68C71E59989400161780 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 8E6D68C81E59989400161780 /* Build configuration list for PBXNativeTarget "Convex Hull" */ = { isa = XCConfigurationList; buildConfigurations = ( 8E6D68C91E59989400161780 /* Debug */, 8E6D68CA1E59989400161780 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 8E6D68AE1E59989400161780 /* Project object */; } ================================================ FILE: Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Convex Hull/Convex Hull.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Convex Hull/README.md ================================================ # Convex Hull Given a group of points on a plane. The Convex Hull algorithm calculates the shape (made up from the points itself) containing all these points. It can also be used on a collection of points of different dimensions. This implementation however covers points on a plane. It essentially calculates the lines between points which together contain all points. In comparing different solutions to this problem we can describe each algorithm in terms of it's big-O time complexity. There are multiple Convex Hull algorithms but this solution is called Quickhull, is comes from the work of both W. Eddy in 1977 and also separately A. Bykat in 1978, this algorithm has an expected time complexity of O(n log n), but it's worst-case time-complexity can be O(n^2) . With average conditions the algorithm has ok efficiency, but it's time-complexity can start to become more exponential in cases of high symmetry or where there are points lying on the circumference of a circle for example. ## Quickhull The quickhull algorithm works as follows: - The algorithm takes an input of a collection of points. These points should be ordered on their x-coordinate value. - We first find the two points A and B with the minimum(A) and the maximum(B) x-coordinates (as these will obviously be part of the hull). - Use the line formed by the two points to divide the set in two subsets of points, which will be processed recursively. - Determine the point, on one side of the line, with the maximum distance from the line. The two points found before along with this one form a triangle. - The points lying inside of that triangle cannot be part of the convex hull and can therefore be ignored in the next steps. - Repeat the previous two steps on the two lines formed by the triangle (not the initial line). - Keep on doing so on until no more points are left, the recursion has come to an end and the points selected constitute the convex hull. Our function will have the following defininition: `findHull(points: [CGPoint], p1: CGPoint, p2: CGPoint)` ``` findHull(S1, A, B) findHull(S2, B, A) ``` What this function does is the following: 1. If `points` is empty we return as there are no points to the right of our line to add to our hull. 2. Draw a line from `p1` to `p2`. 3. Find the point in `points` that is furthest away from this line. (`maxPoint`) 4. Add `maxPoint` to the hull right after `p1`. 5. Draw a line (`line1`) from `p1` to `maxPoint`. 6. Draw a line (`line2`) from `maxPoint` to `p2`. (These lines now form a triangle) 7. All points within this triangle are of course not part of the hull and thus can be ignored. We check which points in `points` are to the right of `line1` these are grouped in an array `s1`. 8. All points that are to the right of `line2` are grouped in an array `s2`. Note that there are no points that are both to the right of `line1` and `line2` as then `maxPoint` wouldn't be the point furthest away from our initial line between `p1` and `p2`. 9. We call `findHull(_, _, _)` again on our new groups of points to find more hull points. ``` findHull(s1, p1, maxPoint) findHull(s2, maxPoint, p2) ``` This eventually leaves us with an array of points describing the convex hull. ## See also [Convex Hull on Wikipedia](https://en.wikipedia.org/wiki/Convex_hull_algorithms) *Written for the Swift Algorithm Club by Jaap Wijnen.* ================================================ FILE: Convex Hull/Tests/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Convex Hull/Tests/Tests.swift ================================================ // // Tests.swift // Tests // // Created by Matthew Nespor on 10/7/17. // Copyright © 2017 Workmoose. All rights reserved. // import XCTest class Tests: XCTestCase { func testHorizontalInitialLine() { let view = View() let excludedPoint = CGPoint(x: 146, y: 284) let includedPoints = [ CGPoint(x: 353, y: 22), CGPoint(x: 22, y: 22), CGPoint(x: 157, y: 447), ] view.points = [CGPoint]() view.convexHull = [CGPoint]() view.points.append(contentsOf: includedPoints) view.points.append(excludedPoint) view.points.sort { (a: CGPoint, b: CGPoint) -> Bool in return a.x < b.x } view.quickHull(points: view.points) assert(includedPoints.filter({ view.convexHull.contains($0) }).count == 3, "\(includedPoints) should have been included") assert(!view.convexHull.contains(excludedPoint), "\(excludedPoint) should have been excluded") } } ================================================ FILE: Count Occurrences/CountOccurrences.playground/Contents.swift ================================================ func countOccurrences(of key: T, in array: [T]) -> Int { var leftBoundary: Int { var low = 0 var high = array.count while low < high { let midIndex = low + (high - low)/2 if array[midIndex] < key { low = midIndex + 1 } else { high = midIndex } } return low } var rightBoundary: Int { var low = 0 var high = array.count while low < high { let midIndex = low + (high - low)/2 if array[midIndex] > key { high = midIndex } else { low = midIndex + 1 } } return low } return rightBoundary - leftBoundary } // Simple test let a = [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] countOccurrences(of: 3, in: a) // Test with arrays of random size and contents (see debug output) import Foundation func createArray() -> [Int] { var a = [Int]() for i in 0...5 { if i != 2 { // don't include the number 2 let count = Int(arc4random_uniform(UInt32(6))) + 1 for _ in 0.. ================================================ FILE: Count Occurrences/CountOccurrences.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Count Occurrences/CountOccurrences.swift ================================================ /// Counts the number of times a value appears in an array in O(log n) time. The array must be sorted from low to high. /// /// - Parameter key: the key to be searched for in the array /// - Parameter array: the array to search /// - Returns: the count of occurences of the key in the given array func countOccurrences(of key: T, in array: [T]) -> Int { var leftBoundary: Int { var low = 0 var high = array.count while low < high { let midIndex = low + (high - low)/2 if array[midIndex] < key { low = midIndex + 1 } else { high = midIndex } } return low } var rightBoundary: Int { var low = 0 var high = array.count while low < high { let midIndex = low + (high - low)/2 if array[midIndex] > key { high = midIndex } else { low = midIndex + 1 } } return low } return rightBoundary - leftBoundary } ================================================ FILE: Count Occurrences/README.markdown ================================================ # Count Occurrences Goal: Count how often a certain value appears in an array. The obvious way to do this is with a [linear search](../Linear%20Search/) from the beginning of the array until the end, keeping count of how often you come across the value. That is an **O(n)** algorithm. However, if the array is sorted you can do it much faster, in **O(log n)** time, by using a modification of [binary search](../Binary%20Search/). Let's say we have the following array: [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] If we want to know how often the value `3` occurs, we can do a regular binary search for `3`. That could give us any of these four indices: [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] * * * * But that still doesn't tell you how many other `3`s there are. To find those other `3`s, you'd still have to do a linear search to the left and a linear search to the right. That will be fast enough in most cases, but in the worst case -- when the array consists of nothing but `3`s -- it still takes **O(n)** time. The trick is to use two binary searches, one to find where the `3`s start (the left boundary), and one to find where they end (the right boundary). In code this looks as follows: ```swift func countOccurrences(of key: T, in array: [T]) -> Int { var leftBoundary: Int { var low = 0 var high = array.count while low < high { let midIndex = low + (high - low)/2 if a[midIndex] < key { low = midIndex + 1 } else { high = midIndex } } return low } var rightBoundary: Int { var low = 0 var high = array.count while low < high { let midIndex = low + (high - low)/2 if a[midIndex] > key { high = midIndex } else { low = midIndex + 1 } } return low } return rightBoundary - leftBoundary } ``` Notice that the variables `leftBoundary` and `rightBoundary` are very similar to the [binary search](../Binary%20Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. Also, notice that we constrain the type `T` to be Comparable so that the algorithm can be applied to an array of Strings, Ints or other types that conform to the Swift Comparable protocol. To test this algorithm, copy the code to a playground and then do: ```swift let a = [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] countOccurrences(of: 3, in: a) // returns 4 ``` > **Remember:** If you use your own array, make sure it is sorted first! Let's walk through the example. The array is: [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] To find the left boundary, we start with `low = 0` and `high = 12`. The first mid index is `6`: [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] * With a regular binary search you'd be done now, but here we're not just looking whether the value `3` occurs or not -- instead, we want to find where it occurs *first*. Since this algorithm follows the same principle as binary search, we now ignore the right half of the array and calculate the new mid index: [ 0, 1, 1, 3, 3, 3 | x, x, x, x, x, x ] * Again, we've landed on a `3`, and it's the very first one. But the algorithm doesn't know that, so we split the array again: [ 0, 1, 1 | x, x, x | x, x, x, x, x, x ] * Still not done. Split again, but this time use the right half: [ x, x | 1 | x, x, x | x, x, x, x, x, x ] * The array cannot be split up any further, which means we've found the left boundary, at index 3. Now let's start over and try to find the right boundary. This is very similar, so I'll just show you the different steps: [ 0, 1, 1, 3, 3, 3, 3, 6, 8, 10, 11, 11 ] * [ x, x, x, x, x, x, x | 6, 8, 10, 11, 11 ] * [ x, x, x, x, x, x, x | 6, 8, | x, x, x ] * [ x, x, x, x, x, x, x | 6 | x | x, x, x ] * The right boundary is at index 7. The difference between the two boundaries is 7 - 3 = 4, so the number `3` occurs four times in this array. Each binary search took 4 steps, so in total this algorithm took 8 steps. Not a big gain on an array of only 12 items, but the bigger the array, the more efficient this algorithm becomes. For a sorted array with 1,000,000 items, it only takes 2 x 20 = 40 steps to count the number of occurrences for any particular value. By the way, if the value you're looking for is not in the array, then `rightBoundary` and `leftBoundary` return the same value and so the difference between them is 0. This is an example of how you can modify the basic binary search to solve other algorithmic problems as well. Of course, it does require that the array is sorted. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: CounterClockWise/CounterClockWise.playground/Contents.swift ================================================ /* CounterClockWise(CCW) Algorithm The user cross-multiplies corresponding coordinates to find the area encompassing the polygon, and subtracts it from the surrounding polygon to find the area of the polygon within. This code is based on the "Shoelace formula" by Carl Friedrich Gauss https://en.wikipedia.org/wiki/Shoelace_formula */ import Foundation // MARK : Point struct for defining 2-D coordinate(x,y) public struct Point{ // Coordinate(x,y) var x: Int var y: Int public init(x: Int ,y: Int){ self.x = x self.y = y } } // MARK : Function that determine the area of a simple polygon whose vertices are described // by their Cartesian coordinates in the plane. func ccw(points: [Point]) -> Int{ let polygon = points.count var orientation = 0 // Take the first x-coordinate and multiply it by the second y-value, // then take the second x-coordinate and multiply it by the third y-value, // and repeat as many times until it is done for all wanted points. for i in 0.. 0 : CounterClockWise } } // A few simple tests // Triangle var p1 = Point(x: 5, y: 8) var p2 = Point(x: 9, y: 1) var p3 = Point(x: 3, y: 6) print(ccw(points: [p1,p2,p3])) // -1 means ClockWise // Quadrilateral var p4 = Point(x: 5, y: 8) var p5 = Point(x: 2, y: 3) var p6 = Point(x: 6, y: 1) var p7 = Point(x: 9, y: 3) print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise // Pentagon var p8 = Point(x: 5, y: 11) var p9 = Point(x: 3, y: 4) var p10 = Point(x: 5, y: 6) var p11 = Point(x: 9, y: 5) var p12 = Point(x: 12, y: 8) print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise ================================================ FILE: CounterClockWise/CounterClockWise.playground/contents.xcplayground ================================================ ================================================ FILE: CounterClockWise/CounterClockWise.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: CounterClockWise/CounterClockWise.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: CounterClockWise/CounterClockWise.swift ================================================ /* CounterClockWise(CCW) Algorithm The user cross-multiplies corresponding coordinates to find the area encompassing the polygon, and subtracts it from the surrounding polygon to find the area of the polygon within. This code is based on the "Shoelace formula" by Carl Friedrich Gauss https://en.wikipedia.org/wiki/Shoelace_formula */ import Foundation // MARK : Point struct for defining 2-D coordinate(x,y) public struct Point{ // Coordinate(x,y) var x: Int var y: Int public init(x: Int ,y: Int){ self.x = x self.y = y } } // MARK : Function that determine the area of a simple polygon whose vertices are described // by their Cartesian coordinates in the plane. func ccw(points: [Point]) -> Int{ let polygon = points.count var orientation = 0 // Take the first x-coordinate and multiply it by the second y-value, // then take the second x-coordinate and multiply it by the third y-value, // and repeat as many times until it is done for all wanted points. for i in 0.. 0 : CounterClockWise } } ================================================ FILE: CounterClockWise/README.md ================================================ # CounterClockWise Goal : Determine what direction to take when multiple points are given. CounterClockWise(CCW) is based on [Shoelace formula](https://en.wikipedia.org/wiki/Shoelace_formula#Examples) by Carl Friedrich Gauss. 1. Take the first x-coordinate and multiply it by the second y-value, then take the second x-coordinate and multiply it by the third y-value, and repeat as many times until it is done for all wanted points. 2. If the points are labeled sequentially in the counterclockwise direction, then the sum of the above determinants is positive and the absolute value signs can be omitted if they are labeled in the clockwise direction, the sum of the determinants will be negative. This is because the formula can be viewed as a special case of [Green's theorem](https://en.wikipedia.org/wiki/Green%27s_theorem). ![Shoelace](./Images/Shoelace.png) Here's an implementation in Swift that should be easy to understand: ```swift func ccw(points: [Point]) -> Int{ let polygon = points.count var orientation = 0 for i in 0.. 0 : CounterClockWise } } ``` Put this code in a playground and test it like so: ```swift var p1 = Point(x: 5, y: 8) var p2 = Point(x: 9, y: 1) var p3 = Point(x: 3, y: 6) print(ccw(points: [p1,p2,p3])) // -1 means ClockWise ``` Here's how it works. When given an `[Photo]`, `ccw(points:)` calculates the direction of the given points according to the Shoelaces formula. `orientation` is less than 0, the direction is clockwise. `orientation` is equal to 0, the direction is parallel. `orientation` is greater than 0, the direction is counterclockwise. ## An example **In Triangle** ```swift var p1 = Point(x: 5, y: 8) var p2 = Point(x: 9, y: 1) var p3 = Point(x: 3, y: 6) print(ccw(points: [p1,p2,p3])) // -1 means ClockWise ``` ![triangle](./Images/Triangle_img.jpg) ![triangleExpression](./Images/triangle.png) **In Quadrilateral** ```swift var p4 = Point(x: 5, y: 8) var p5 = Point(x: 2, y: 3) var p6 = Point(x: 6, y: 1) var p7 = Point(x: 9, y: 3) print(ccw(points: [p4,p5,p6,p7])) // 1 means CounterClockWise ``` ![Quadrilateral](./Images/Quadrilateral_img.jpg) ![triangleExpression](./Images/quadrilateral.png) **In Pentagon** ```swift var p8 = Point(x: 5, y: 11) var p9 = Point(x: 3, y: 4) var p10 = Point(x: 5, y: 6) var p11 = Point(x: 9, y: 5) var p12 = Point(x: 12, y: 8) print(ccw(points: [p8,p9,p10,p11,p12])) // 1 means CounterClockWise ``` ![triangle](./Images/Pentagon_img.png) ![triangleExpression](./Images/pentagon.png) You probably won't need to use the CCW in any real-world problems, but it's cool to play around with geometry algorithm. The formula was described by Meister (1724-1788) in 1769 and by Gauss in 1795. It can be verified by dividing the polygon into triangles, and can be considered to be a special case of Green's theorem. *Written for Swift Algorithm Club by TaeJoong Yoon* ================================================ FILE: Counting Sort/CountingSort.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play enum CountingSortError: Error { case arrayEmpty } func countingSort(array: [Int]) throws -> [Int] { guard array.count > 0 else { throw CountingSortError.arrayEmpty } // Step 1 // Create an array to store the count of each element let maxElement = array.max() ?? 0 var countArray = [Int](repeating: 0, count: Int(maxElement + 1)) for element in array { countArray[element] += 1 } // Step 2 // Set each value to be the sum of the previous two values for index in 1 ..< countArray.count { let sum = countArray[index] + countArray[index - 1] countArray[index] = sum } print(countArray) // Step 3 // Place the element in the final array as per the number of elements before it // Loop through the array in reverse to keep the stability of the new array // i.e. 7, is at index 3 and 6, thus in sortedArray the position of 7 at index 3 should be before 7 at index 6 var sortedArray = [Int](repeating: 0, count: array.count) for index in stride(from: array.count - 1, through: 0, by: -1) { let element = array[index] countArray[element] -= 1 sortedArray[countArray[element]] = element } return sortedArray } try countingSort(array: [10, 9, 8, 7, 1, 2, 7, 3]) ================================================ FILE: Counting Sort/CountingSort.playground/contents.xcplayground ================================================ ================================================ FILE: Counting Sort/CountingSort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Counting Sort/CountingSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Counting Sort/CountingSort.swift ================================================ // // Sort.swift // test // // Created by Kauserali on 11/04/16. // Copyright © 2016 Ali Hafizji. All rights reserved. // func countingSort(_ array: [Int])-> [Int] { guard array.count > 0 else {return []} // Step 1 // Create an array to store the count of each element let maxElement = array.max() ?? 0 var countArray = [Int](repeating: 0, count: Int(maxElement + 1)) for element in array { countArray[element] += 1 } // Step 2 // Set each value to be the sum of the previous two values for index in 1 ..< countArray.count { let sum = countArray[index] + countArray[index - 1] countArray[index] = sum } print(countArray) // Step 3 // Place the element in the final array as per the number of elements before it // Loop through the array in reverse to keep the stability of the new sorted array // (For Example: 7 is at index 3 and 6, thus in sortedArray the position of 7 at index 3 should be before 7 at index 6 var sortedArray = [Int](repeating: 0, count: array.count) for index in stride(from: array.count - 1, through: 0, by: -1) { let element = array[index] countArray[element] -= 1 sortedArray[countArray[element]] = element } return sortedArray } ================================================ FILE: Counting Sort/README.markdown ================================================ # Counting Sort Counting sort is an algorithm for sorting a collection of objects according to keys that are small integers. It operates by counting the number of objects that have each distinct key values, and using arithmetic on those counts to determine the positions of each key value in the output sequence. ## Example To understand the algorithm let's walk through a small example. Consider the array: `[ 10, 9, 8, 7, 1, 2, 7, 3 ]` ### Step 1: The first step is to count the total number of occurrences for each item in the array. The output for the first step would be a new array that looks as follows: ``` Index 0 1 2 3 4 5 6 7 8 9 10 Count 0 1 1 1 0 0 0 2 1 1 1 ``` Here is the code to accomplish this: ```swift let maxElement = array.max() ?? 0 var countArray = [Int](repeating: 0, count: Int(maxElement + 1)) for element in array { countArray[element] += 1 } ``` ### Step 2: In this step the algorithm tries to determine the number of elements that are placed before each element. Since, you already know the total occurrences for each element you can use this information to your advantage. The way it works is to sum up the previous counts and store them at each index. The count array would be as follows: ``` Index 0 1 2 3 4 5 6 7 8 9 10 Count 0 1 2 3 3 3 3 5 6 7 8 ``` The code for step 2 is: ```swift for index in 1 ..< countArray.count { let sum = countArray[index] + countArray[index - 1] countArray[index] = sum } ``` ### Step 3: This is the last step in the algorithm. Each element in the original array is placed at the position defined by the output of step 2. For example, the number 10 would be placed at an index of 7 in the output array. Also, as you place the elements you need to reduce the count by 1 as those many elements are reduced from the array. We also have to loop through the array in reverse to keep the stability of the new sorted array. For Example: 7 is at index 3 and 6, thus in sortedArray the position of 7 at index 3 should be before 7 at index 6. The final output would be: ``` Index 0 1 2 3 4 5 6 7 Output 1 2 3 7 7 8 9 10 ``` Here is the code for this final step: ```swift var sortedArray = [Int](repeating: 0, count: array.count) for index in stride(from: array.count - 1, through: 0, by: -1) { let element = array[index] countArray[element] -= 1 sortedArray[countArray[element]] = element } return sortedArray ``` ## Performance The algorithm uses simple loops to sort a collection. Hence, the time to run the entire algorithm is **O(n+k)** where **O(n)** represents the loops that are required to initialize the output arrays and **O(k)** is the loop required to create the count array. The algorithm uses arrays of length **n + 1** and **n**, so the total space required is **O(2n)**. Hence for collections where the keys are scattered in a dense area along the number line it can be space efficient. *Written for Swift Algorithm Club by Ali Hafizji* ================================================ FILE: Counting Sort/Tests/CountingSortTest.swift ================================================ // // CountingSort.swift // CountingSort // // Created by Kauserali on 11/04/16. // // import XCTest class CountingSort: XCTestCase { func testCountingSort() { let sequence = [10, 8, 1, 2, 5, 8] let sortedSequence = [1, 2, 5, 8, 8, 10] do { let afterCountingSort = try countingSort(sequence) XCTAssertEqual(afterCountingSort, sortedSequence) } catch { XCTFail("") } } } ================================================ FILE: Counting Sort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Counting Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B74638C1CBCCC3C006DB977 /* CountingSortTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B74638B1CBCCC3C006DB977 /* CountingSortTest.swift */; }; 7B80C3D81C77A313003CECC7 /* CountingSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3D71C77A313003CECC7 /* CountingSort.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B74638B1CBCCC3C006DB977 /* CountingSortTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountingSortTest.swift; sourceTree = SOURCE_ROOT; }; 7B80C3D71C77A313003CECC7 /* CountingSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CountingSort.swift; path = ../CountingSort.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3D71C77A313003CECC7 /* CountingSort.swift */, 7B74638B1CBCCC3C006DB977 /* CountingSortTest.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0820; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( English, en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B74638C1CBCCC3C006DB977 /* CountingSortTest.swift in Sources */, 7B80C3D81C77A313003CECC7 /* CountingSort.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Counting Sort/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Depth-First Search/DepthFirstSearch.playground/Pages/Simple Example.xcplaygroundpage/Contents.swift ================================================ // last checked with Xcode 10.1 func depthFirstSearch(_ graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true for edge in source.neighbors { if !edge.neighbor.visited { nodesExplored += depthFirstSearch(graph, source: edge.neighbor) } } return nodesExplored } let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") let nodeC = graph.addNode("c") let nodeD = graph.addNode("d") let nodeE = graph.addNode("e") let nodeF = graph.addNode("f") let nodeG = graph.addNode("g") let nodeH = graph.addNode("h") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeD) graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = depthFirstSearch(graph, source: nodeA) print(nodesExplored) ================================================ FILE: Depth-First Search/DepthFirstSearch.playground/Sources/Edge.swift ================================================ public class Edge: Equatable { public var neighbor: Node public init(_ neighbor: Node) { self.neighbor = neighbor } } public func == (_ lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } ================================================ FILE: Depth-First Search/DepthFirstSearch.playground/Sources/Graph.swift ================================================ public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { self.nodes = [] } @discardableResult public func addNode(_ label: String) -> Node { let node = Node(label) nodes.append(node) return node } public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor) source.neighbors.append(edge) } public var description: String { var description = "" for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { let duplicated = Graph() for node in nodes { duplicated.addNode(node.label) } for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(node.label) let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } return duplicated } } public func == (_ lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } ================================================ FILE: Depth-First Search/DepthFirstSearch.playground/Sources/Node.swift ================================================ public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String public var distance: Int? public var visited: Bool public init(_ label: String) { self.label = label neighbors = [] visited = false } public var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } public var hasDistance: Bool { return distance != nil } public func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } public func == (_ lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } ================================================ FILE: Depth-First Search/DepthFirstSearch.playground/contents.xcplayground ================================================ ================================================ FILE: Depth-First Search/DepthFirstSearch.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Depth-First Search/DepthFirstSearch.swift ================================================ func depthFirstSearch(_ graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true for edge in source.neighbors { if !edge.neighbor.visited { nodesExplored += depthFirstSearch(graph, source: edge.neighbor) } } return nodesExplored } ================================================ FILE: Depth-First Search/README.markdown ================================================ # Depth-First Search > This topic has been tutorialized [here](https://www.raywenderlich.com/157949/swift-algorithm-club-depth-first-search) Depth-first search (DFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at a source node and explores as far as possible along each branch before backtracking. Depth-first search can be used on both directed and undirected graphs. ## Animated example Here's how depth-first search works on a graph: ![Animated example](Images/AnimatedExample.gif) Let's say we start the search from node `A`. In depth-first search we look at the starting node's first neighbor and visit that. In the example that is node `B`. Then we look at node `B`'s first neighbor and visit it. This is node `D`. Since `D` doesn't have any unvisited neighbors of its own, we backtrack to node `B` and go to its other neighbor `E`. And so on, until we've visited all the nodes in the graph. Each time we visit the first neighbor and keep going until there's nowhere left to go, and then we backtrack to a point where there are again nodes to visit. When we've backtracked all the way to node `A`, the search is complete. For the example, the nodes were visited in the order `A`, `B`, `D`, `E`, `H`, `F`, `G`, `C`. The depth-first search process can also be visualized as a tree: ![Traversal tree](Images/TraversalTree.png) The parent of a node is the one that "discovered" that node. The root of the tree is the node you started the depth-first search from. Whenever there's a branch, that's where we backtracked. ## The code Simple recursive implementation of depth-first search: ```swift func depthFirstSearch(_ graph: Graph, source: Node) -> [String] { var nodesExplored = [source.label] source.visited = true for edge in source.neighbors { if !edge.neighbor.visited { nodesExplored += depthFirstSearch(graph, source: edge.neighbor) } } return nodesExplored } ``` Where a [breadth-first search](../Breadth-First%20Search/) visits all immediate neighbors first, a depth-first search tries to go as deep down the tree or graph as it can. Put this code in a playground and test it like so: ```swift let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") let nodeC = graph.addNode("c") let nodeD = graph.addNode("d") let nodeE = graph.addNode("e") let nodeF = graph.addNode("f") let nodeG = graph.addNode("g") let nodeH = graph.addNode("h") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeD) graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeG) let nodesExplored = depthFirstSearch(graph, source: nodeA) print(nodesExplored) ``` This will output: `["a", "b", "d", "e", "h", "f", "g", "c"]` ## What is DFS good for? Depth-first search can be used to solve many problems, for example: * Finding connected components of a sparse graph * [Topological sorting](../Topological%20Sort/) of nodes in a graph * Finding bridges of a graph (see: [Bridges](https://en.wikipedia.org/wiki/Bridge_(graph_theory)#Bridge-finding_algorithm)) * And lots of others! *Written for Swift Algorithm Club by Paulo Tanaka and Matthijs Hollemans* ================================================ FILE: Depth-First Search/Tests/DepthFirstSearchTests.swift ================================================ import XCTest class DepthFirstSearchTests: XCTestCase { func testSwift4(){ // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testExploringTree() { let tree = Graph() let nodeA = tree.addNode("a") let nodeB = tree.addNode("b") let nodeC = tree.addNode("c") let nodeD = tree.addNode("d") let nodeE = tree.addNode("e") let nodeF = tree.addNode("f") let nodeG = tree.addNode("g") let nodeH = tree.addNode("h") tree.addEdge(nodeA, neighbor: nodeB) tree.addEdge(nodeA, neighbor: nodeC) tree.addEdge(nodeB, neighbor: nodeD) tree.addEdge(nodeB, neighbor: nodeE) tree.addEdge(nodeC, neighbor: nodeF) tree.addEdge(nodeC, neighbor: nodeG) tree.addEdge(nodeE, neighbor: nodeH) let nodesExplored = depthFirstSearch(tree, source: nodeA) XCTAssertEqual(nodesExplored, ["a", "b", "d", "e", "h", "c", "f", "g"]) } func testExploringDigraph() { let digraph = Graph() let nodeA = digraph.addNode("a") let nodeB = digraph.addNode("b") let nodeC = digraph.addNode("c") let nodeD = digraph.addNode("d") let nodeE = digraph.addNode("e") let nodeF = digraph.addNode("f") let nodeG = digraph.addNode("g") let nodeH = digraph.addNode("h") let nodeI = digraph.addNode("i") digraph.addEdge(nodeA, neighbor: nodeB) digraph.addEdge(nodeA, neighbor: nodeH) digraph.addEdge(nodeB, neighbor: nodeA) digraph.addEdge(nodeB, neighbor: nodeC) digraph.addEdge(nodeB, neighbor: nodeH) digraph.addEdge(nodeC, neighbor: nodeB) digraph.addEdge(nodeC, neighbor: nodeD) digraph.addEdge(nodeC, neighbor: nodeF) digraph.addEdge(nodeC, neighbor: nodeI) digraph.addEdge(nodeD, neighbor: nodeC) digraph.addEdge(nodeD, neighbor: nodeE) digraph.addEdge(nodeD, neighbor: nodeF) digraph.addEdge(nodeE, neighbor: nodeD) digraph.addEdge(nodeE, neighbor: nodeF) digraph.addEdge(nodeF, neighbor: nodeC) digraph.addEdge(nodeF, neighbor: nodeD) digraph.addEdge(nodeF, neighbor: nodeE) digraph.addEdge(nodeF, neighbor: nodeG) digraph.addEdge(nodeG, neighbor: nodeF) digraph.addEdge(nodeG, neighbor: nodeH) digraph.addEdge(nodeG, neighbor: nodeI) digraph.addEdge(nodeH, neighbor: nodeA) digraph.addEdge(nodeH, neighbor: nodeB) digraph.addEdge(nodeH, neighbor: nodeG) digraph.addEdge(nodeH, neighbor: nodeI) digraph.addEdge(nodeI, neighbor: nodeC) digraph.addEdge(nodeI, neighbor: nodeG) digraph.addEdge(nodeI, neighbor: nodeH) let nodesExplored = depthFirstSearch(digraph, source: nodeA) XCTAssertEqual(nodesExplored, ["a", "b", "c", "d", "e", "f", "g", "h", "i"]) } func testExploringDigraphWithASingleNode() { let digraph = Graph() let node = digraph.addNode("a") let nodesExplored = depthFirstSearch(digraph, source: node) XCTAssertEqual(nodesExplored, ["a"]) } } ================================================ FILE: Depth-First Search/Tests/Graph.swift ================================================ // MARK: - Edge open class Edge: Equatable { open var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor } } public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } // MARK: - Node open class Node: CustomStringConvertible, Equatable { open var neighbors: [Edge] open fileprivate(set) var label: String open var distance: Int? open var visited: Bool public init(label: String) { self.label = label neighbors = [] visited = false } open var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } open var hasDistance: Bool { return distance != nil } open func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph open class Graph: CustomStringConvertible, Equatable { open fileprivate(set) var nodes: [Node] public init() { self.nodes = [] } open func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } open func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } open var description: String { var description = "" for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } open func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } open func duplicate() -> Graph { let duplicated = Graph() for node in nodes { _ = duplicated.addNode(node.label) } for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(node.label) let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } return duplicated } } public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } ================================================ FILE: Depth-First Search/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 83F9C96C1C8443E800B3A87F /* DepthFirstSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */; }; 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; FFC6E11E1C8656D10046BA79 /* DepthFirstSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DepthFirstSearchTests.swift; sourceTree = SOURCE_ROOT; }; 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = SOURCE_ROOT; }; FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DepthFirstSearch.swift; path = ../DepthFirstSearch.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 83F9C96E1C84449D00B3A87F /* Graph.swift */, 83F9C96B1C8443E800B3A87F /* DepthFirstSearchTests.swift */, FFC6E11D1C8656D10046BA79 /* DepthFirstSearch.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0820; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, FFC6E11E1C8656D10046BA79 /* DepthFirstSearch.swift in Sources */, 83F9C96C1C8443E800B3A87F /* DepthFirstSearchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Depth-First Search/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Deque/Deque-Optimized.swift ================================================ /* Deque (pronounced "deck"), a double-ended queue All enqueuing and dequeuing operations are O(1). */ public struct Deque { private var array: [T?] private var head: Int private var capacity: Int private let originalCapacity: Int public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) originalCapacity = self.capacity array = [T?](repeating: nil, count: capacity) head = capacity } public var isEmpty: Bool { return count == 0 } public var count: Int { return array.count - head } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func enqueueFront(_ element: T) { if head == 0 { capacity *= 2 let emptySpace = [T?](repeating: nil, count: capacity) array.insert(contentsOf: emptySpace, at: 0) head = capacity } head -= 1 array[head] = element } public mutating func dequeue() -> T? { guard head < array.count, let element = array[head] else { return nil } array[head] = nil head += 1 if capacity >= originalCapacity && head >= capacity*2 { let amountToRemove = capacity + capacity/2 array.removeFirst(amountToRemove) head -= amountToRemove capacity /= 2 } return element } public mutating func dequeueBack() -> T? { if isEmpty { return nil } else { return array.removeLast() } } public func peekFront() -> T? { if isEmpty { return nil } else { return array[head] } } public func peekBack() -> T? { if isEmpty { return nil } else { return array.last! } } } ================================================ FILE: Deque/Deque-Simple.swift ================================================ /* Deque (pronounced "deck"), a double-ended queue This particular implementation is simple but not very efficient. Several operations are O(n). A more efficient implementation would use a doubly linked list or a circular buffer. */ public struct Deque { private var array = [T]() public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func enqueueFront(_ element: T) { array.insert(element, at: 0) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public mutating func dequeueBack() -> T? { if isEmpty { return nil } else { return array.removeLast() } } public func peekFront() -> T? { return array.first } public func peekBack() -> T? { return array.last } } ================================================ FILE: Deque/Deque.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play public struct Deque { private var array = [T]() public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func enqueueFront(_ element: T) { array.insert(element, at: 0) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public mutating func dequeueBack() -> T? { if isEmpty { return nil } else { return array.removeLast() } } public func peekFront() -> T? { return array.first } public func peekBack() -> T? { return array.last } } var deque = Deque() deque.enqueue(1) deque.enqueue(2) deque.enqueue(3) deque.enqueue(4) deque.dequeue() // 1 deque.dequeueBack() // 4 deque.enqueueFront(5) deque.dequeue() // 5 ================================================ FILE: Deque/Deque.playground/contents.xcplayground ================================================ ================================================ FILE: Deque/Deque.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Deque/README.markdown ================================================ # Deque A double-ended queue. For some reason this is pronounced as "deck". A regular [queue](../Queue/) adds elements to the back and removes from the front. The deque also allows enqueuing at the front and dequeuing from the back, and peeking at both ends. Here is a very basic implementation of a deque in Swift: ```swift public struct Deque { private var array = [T]() public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func enqueueFront(_ element: T) { array.insert(element, at: 0) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public mutating func dequeueBack() -> T? { if isEmpty { return nil } else { return array.removeLast() } } public func peekFront() -> T? { return array.first } public func peekBack() -> T? { return array.last } } ``` This uses an array internally. Enqueuing and dequeuing are simply a matter of adding and removing items from the front or back of the array. An example of how to use it in a playground: ```swift var deque = Deque() deque.enqueue(1) deque.enqueue(2) deque.enqueue(3) deque.enqueue(4) deque.dequeue() // 1 deque.dequeueBack() // 4 deque.enqueueFront(5) deque.dequeue() // 5 ``` This particular implementation of `Deque` is simple but not very efficient. Several operations are **O(n)**, notably `enqueueFront()` and `dequeue()`. I've included it only to show the principle of what a deque does. ## A more efficient version The reason that `dequeue()` and `enqueueFront()` are **O(n)** is that they work on the front of the array. If you remove an element at the front of an array, what happens is that all the remaining elements need to be shifted in memory. Let's say the deque's array contains the following items: [ 1, 2, 3, 4 ] Then `dequeue()` will remove `1` from the array and the elements `2`, `3`, and `4`, are shifted one position to the front: [ 2, 3, 4 ] This is an **O(n)** operation because all array elements need to be moved by one position in the computer's memory. Likewise, inserting an element at the front of the array is expensive because it requires that all other elements must be shifted one position to the back. So `enqueueFront(5)` will change the array to be: [ 5, 2, 3, 4 ] First, the elements `2`, `3`, and `4` are moved up by one position in the computer's memory, and then the new element `5` is inserted at the position where `2` used to be. Why is this not an issue at for `enqueue()` and `dequeueBack()`? Well, these operations are performed at the end of the array. The way resizable arrays are implemented in Swift is by reserving a certain amount of free space at the back. Our initial array `[ 1, 2, 3, 4]` actually looks like this in memory: [ 1, 2, 3, 4, x, x, x ] where the `x`s denote additional positions in the array that are not being used yet. Calling `enqueue(6)` simply copies the new item into the next unused spot: [ 1, 2, 3, 4, 6, x, x ] The `dequeueBack()` function uses `array.removeLast()` to delete that item. This does not shrink the array's memory but only decrements `array.count` by one. There are no expensive memory copies involved here. So operations at the back of the array are fast, **O(1)**. It is possible the array runs out of free spots at the back. In that case, Swift will allocate a new, larger array and copy over all the data. This is an **O(n)** operation but because it only happens once in a while, adding new elements at the end of an array is still **O(1)** on average. Of course, we can use this same trick at the *beginning* of the array. That will make our deque efficient too for operations at the front of the queue. Our array will look like this: [ x, x, x, 1, 2, 3, 4, x, x, x ] There is now also a chunk of free space at the start of the array, which allows adding or removing elements at the front of the queue to be **O(1)** as well. Here is the new version of `Deque`: ```swift public struct Deque { private var array: [T?] private var head: Int private var capacity: Int private let originalCapacity:Int public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) originalCapacity = self.capacity array = [T?](repeating: nil, count: capacity) head = capacity } public var isEmpty: Bool { return count == 0 } public var count: Int { return array.count - head } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func enqueueFront(_ element: T) { // this is explained below } public mutating func dequeue() -> T? { // this is explained below } public mutating func dequeueBack() -> T? { if isEmpty { return nil } else { return array.removeLast() } } public func peekFront() -> T? { if isEmpty { return nil } else { return array[head] } } public func peekBack() -> T? { if isEmpty { return nil } else { return array.last! } } } ``` It still largely looks the same -- `enqueue()` and `dequeueBack()` haven't changed -- but there are also a few important differences. The array now stores objects of type `T?` instead of just `T` because we need some way to mark array elements as being empty. The `init` method allocates a new array that contains a certain number of `nil` values. This is the free room we have to work with at the beginning of the array. By default this creates 10 empty spots. The `head` variable is the index in the array of the front-most object. Since the queue is currently empty, `head` points at an index beyond the end of the array. [ x, x, x, x, x, x, x, x, x, x ] | head To enqueue an object at the front, we move `head` one position to the left and then copy the new object into the array at index `head`. For example, `enqueueFront(5)` gives: [ x, x, x, x, x, x, x, x, x, 5 ] | head Followed by `enqueueFront(7)`: [ x, x, x, x, x, x, x, x, 7, 5 ] | head And so on... the `head` keeps moving to the left and always points at the first item in the queue. `enqueueFront()` is now **O(1)** because it only involves copying a value into the array, a constant-time operation. Here is the code: ```swift public mutating func enqueueFront(element: T) { head -= 1 array[head] = element } ``` Appending to the back of the queue has not changed (it's the exact same code as before). For example, `enqueue(1)` gives: [ x, x, x, x, x, x, x, x, 7, 5, 1, x, x, x, x, x, x, x, x, x ] | head Notice how the array has resized itself. There was no room to add the `1`, so Swift decided to make the array larger and add a number of empty spots to the end. If you enqueue another object, it gets added to the next empty spot in the back. For example, `enqueue(2)`: [ x, x, x, x, x, x, x, x, 7, 5, 1, 2, x, x, x, x, x, x, x, x ] | head > **Note:** You won't see those empty spots at the back of the array when you `print(deque.array)`. This is because Swift hides them from you. Only the ones at the front of the array show up. The `dequeue()` method does the opposite of `enqueueFront()`, it reads the value at `head`, sets the array element back to `nil`, and then moves `head` one position to the right: ```swift public mutating func dequeue() -> T? { guard head < array.count, let element = array[head] else { return nil } array[head] = nil head += 1 return element } ``` There is one tiny problem... If you enqueue a lot of objects at the front, you're going to run out of empty spots at the front at some point. When this happens at the back of the array, Swift automatically resizes it. But at the front of the array we have to handle this situation ourselves, with some extra logic in `enqueueFront()`: ```swift public mutating func enqueueFront(element: T) { if head == 0 { capacity *= 2 let emptySpace = [T?](repeating: nil, count: capacity) array.insert(contentsOf: emptySpace, at: 0) head = capacity } head -= 1 array[head] = element } ``` If `head` equals 0, there is no room left at the front. When that happens, we add a whole bunch of new `nil` elements to the array. This is an **O(n)** operation but since this cost gets divided over all the `enqueueFront()`s, each individual call to `enqueueFront()` is still **O(1)** on average. > **Note:** We also multiply the capacity by 2 each time this happens, so if your queue grows bigger and bigger, the resizing happens less often. This is also what Swift arrays automatically do at the back. We have to do something similar for `dequeue()`. If you mostly enqueue a lot of elements at the back and mostly dequeue from the front, then you may end up with an array that looks as follows: [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] | head Those empty spots at the front only get used when you call `enqueueFront()`. But if enqueuing objects at the front happens only rarely, this leaves a lot of wasted space. So let's add some code to `dequeue()` to clean this up: ```swift public mutating func dequeue() -> T? { guard head < array.count, let element = array[head] else { return nil } array[head] = nil head += 1 if capacity >= originalCapacity && head >= capacity*2 { let amountToRemove = capacity + capacity/2 array.removeFirst(amountToRemove) head -= amountToRemove capacity /= 2 } return element } ``` Recall that `capacity` is the original number of empty places at the front of the queue. If the `head` has advanced more to the right than twice the capacity, then it's time to trim off a bunch of these empty spots. We reduce it to about 25%. > **Note:** The deque will keep at least its original capacity by comparing `capacity` to `originalCapacity`. For example, this: [ x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, 1, 2, 3 ] | | capacity head becomes after trimming: [ x, x, x, x, x, 1, 2, 3 ] | head capacity This way we can strike a balance between fast enqueuing and dequeuing at the front and keeping the memory requirements reasonable. > **Note:** We don't perform trimming on very small arrays. It's not worth it for saving just a few bytes of memory. ## See also Other ways to implement deque are by using a [doubly linked list](../Linked%20List/), a [circular buffer](../Ring%20Buffer/), or two [stacks](../Stack/) facing opposite directions. [A fully-featured deque implementation in Swift](https://github.com/lorentey/Deque) *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Dijkstra Algorithm/Dijkstra.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation var vertices: Set = Set() func createNotConnectedVertices() { //change this value to increase or decrease amount of vertices in the graph let numberOfVerticesInGraph = 15 for i in 0.. Vertex { var newSet = vertices newSet.remove(vertex) let offset = Int(arc4random_uniform(UInt32(newSet.count))) let index = newSet.index(newSet.startIndex, offsetBy: offset) return newSet[index] } func randomVertex() -> Vertex { let offset = Int(arc4random_uniform(UInt32(vertices.count))) let index = vertices.index(vertices.startIndex, offsetBy: offset) return vertices[index] } //initialize random graph createNotConnectedVertices() setupConnections() //initialize Dijkstra algorithm with graph vertices let dijkstra = Dijkstra(vertices: vertices) //decide which vertex will be the starting one let startVertex = randomVertex() let startTime = Date() //ask algorithm to find shortest paths from start vertex to all others dijkstra.findShortestPaths(from: startVertex) let endTime = Date() print("calculation time is = \((endTime.timeIntervalSince(startTime))) sec") //printing results let destinationVertex = randomVertex(except: startVertex) print(destinationVertex.pathLengthFromStart) var pathVerticesFromStartString: [String] = [] for vertex in destinationVertex.pathVerticesFromStart { pathVerticesFromStartString.append(vertex.identifier) } print(pathVerticesFromStartString.joined(separator: "->")) ================================================ FILE: Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift ================================================ import Foundation public class Dijkstra { private var totalVertices: Set public init(vertices: Set) { totalVertices = vertices } private func clearCache() { totalVertices.forEach { $0.clearCache() } } public func findShortestPaths(from startVertex: Vertex) { clearCache() var currentVertices = self.totalVertices startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) var currentVertex: Vertex? = startVertex while let vertex = currentVertex { currentVertices.remove(vertex) let filteredNeighbors = vertex.neighbors.filter { currentVertices.contains($0.0) } for neighbor in filteredNeighbors { let neighborVertex = neighbor.0 let weight = neighbor.1 let theoreticNewWeight = vertex.pathLengthFromStart + weight if theoreticNewWeight < neighborVertex.pathLengthFromStart { neighborVertex.pathLengthFromStart = theoreticNewWeight neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } if currentVertices.isEmpty { currentVertex = nil break } currentVertex = currentVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } } } } ================================================ FILE: Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift ================================================ import Foundation open class Vertex { open var identifier: String open var neighbors: [(Vertex, Double)] = [] open var pathLengthFromStart = Double.infinity open var pathVerticesFromStart: [Vertex] = [] public init(identifier: String) { self.identifier = identifier } open func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] } } extension Vertex: Hashable { open var hashValue: Int { return identifier.hashValue } } extension Vertex: Equatable { public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { return lhs.hashValue == rhs.hashValue } } ================================================ FILE: Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground ================================================ ================================================ FILE: Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Dijkstra Algorithm/README.md ================================================ # Weighted graph general concepts Every weighted graph should contain: 1. Vertices/Nodes (I will use "vertex" in this readme). 2. Edges connecting vertices. Let's add some edges to our graph. For simplicity let's create directed graph for now. Directed means that edge has a direction, i.e. vertex, where it starts and vertex, where it ends. But remember a VERY IMPORTANT thing: * All undirected graphs can be viewed as a directed graph. * A directed graph is undirected if and only if every edge is paired with an edge going in the opposite direction. 3. Weights for every edge. Final result. Directed weighted graph: Undirected weighted graph: And once again: An undirected graph it is a directed graph with every edge paired with an edge going in the opposite direction. This statement is clear on the image above. Great! Now we are familiar with general concepts about graphs. # The Dijkstra's algorithm This [algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) was invented in 1956 by Edsger W. Dijkstra. It can be used when you have one source vertex and want to find the shortest paths to ALL other vertices in the graph. The best example is a road network. If you want to find the shortest path from your house to your job or if you want to find the closest store to your house then it is time for the Dijkstra's algorithm. The algorithm repeats following cycle until all vertices are marked as visited. Cycle: 1. From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value then algorithm picks any of them) 2. The algorithm marks picked vertex as visited. 3. The algorithm checks all of its neighbours. If the current vertex path length from the start plus an edge weight to a neighbour less than the neighbour current path length from the start than it assigns new path length from the start to the neighbour. When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. I have created **VisualizedDijkstra.playground** game/tutorial to improve your understanding of the algorithm's flow. Besides, below is step by step algorithm's description. A short sidenote. The Swift Algorithm Club also contains the A* algorithm, which essentially is a faster version of Dijkstra's algorithm for which the only extra prerequisite is you have to know where the destination is located. ## Example Let's imagine that you want to go to the shop. Your house is A vertex and there are 4 possible stores around your house. How to find the closest one/ones? Luckily, you have a graph that connects your house with all these stores. So, you know what to do :) ### Initialisation When the algorithm starts to work initial graph looks like this: The table below represents graph state: | | A | B | C | D | E | |:------------------------- |:---:|:---:|:---:|:---:|:---:| | Visited | F | F | F | F | F | | Path Length From Start | inf | inf | inf | inf | inf | | Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | >inf is equal infinity which basically means that algorithm doesn't know how far away is this vertex from start one. >F states for False >T states for True To initialize our graph we have to set source vertex path length from source vertex to 0 and append itself to path vertices from start. | | A | B | C | D | E | |:------------------------- |:---:|:---:|:---:|:---:|:---:| | Visited | F | F | F | F | F | | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | Great, now our graph is initialised and we can pass it to the Dijkstra's algorithm, let's start! Let's follow the algorithm's cycle and pick the first vertex which neighbours we want to check. All our vertices are not visited but there is only one has the smallest path length from start. It is A. This vertex is the first one which neighbors we will check. First of all, set this vertex as visited. A.visited = true After this step graph has this state: | | A | B | C | D | E | |:------------------------- |:---:|:---:|:---:|:---:|:---:| | Visited | T | F | F | F | F | | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | ### Step 1 Then we check all of its neighbours. If checking vertex path length from start + edge weight is smaller than neighbour's path length from start then we set neighbour's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. for clarity: ```swift if (A.pathLengthFromStart + AB.weight) < B.pathLengthFromStart { B.pathLengthFromStart = A.pathLengthFromStart + AB.weight B.pathVerticesFromStart = A.pathVerticesFromStart B.pathVerticesFromStart.append(B) } ``` And now our graph looks like this one: And its state is here: | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | F | F | F | F | | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | ### Step 2 From now we repeat all actions again and fill our table with new info! | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | F | F | T | F | | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | ### Step 3 | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | F | F | T | T | | Path Length From Start | 0 | 3 | 11 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | ### Step 4 | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | T | F | T | T | | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | ### Step 5 | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | T | T | T | T | | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | ## Code implementation First of all, let’s create class that will describe any Vertex in the graph. It is pretty simple ```swift open class Vertex { //Every vertex should be unique that's why we set up identifier open var identifier: String //For Dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some usecases //when you firstly initialize all vertices without neighbours. And then on next iteration you set up their neighbours. So, initially neighbours is an empty array. //Array contains tuples (Vertex, Double). Vertex is a neighbour and Double is as edge weight to that neighbour. open var neighbours: [(Vertex, Double)] = [] //As it was mentioned in the algorithm description, default path length from start for all vertices should be as much as possible. //It is var because we will update it during the algorithm execution. open var pathLengthFromStart = Double.infinity //This array contains vertices which we need to go through to reach this vertex from starting one //As with path length from start, we will change this array during the algorithm execution. open var pathVerticesFromStart: [Vertex] = [] public init(identifier: String) { self.identifier = identifier } //This function let us use the same array of vertices again and again to calculate paths with different starting vertex. //When we will need to set new starting vertex and recalculate paths then we will simply clear graph vertices' cashes. open func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] } } ``` As every vertex should be unique it is useful to make them Hashable and according Equatable. We use an identifier for this purposes. ```swift extension Vertex: Hashable { open var hashValue: Int { return identifier.hashValue } } extension Vertex: Equatable { public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { return lhs.hashValue == rhs.hashValue } } ``` We've created a base for our algorithm. Now let's create a house :) Dijkstra's realisation is really straightforward. ```swift public class Dijkstra { //This is a storage for vertices in the graph. //Assuming that our vertices are unique we can use Set instead of array. This approach will bring some benefits later. private var totalVertices: Set public init(vertices: Set) { totalVertices = vertices } //Remember clearCache function in the Vertex class implementation? //This is just a wrapper that cleans cache for all stored vertices. private func clearCache() { totalVertices.forEach { $0.clearCache() } } public func findShortestPaths(from startVertex: Vertex) { //Before we start searching the shortest path from startVertex, //we need to clear vertices cache just to be sure that out graph is clean. //Remember that every Vertex is a class and classes are passed by reference. //So whenever you change vertex outside of this class it will affect this vertex inside totalVertices Set clearCache() //Now all our vertices have Double.infinity pathLengthFromStart and an empty pathVerticesFromStart array. //The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) //Here starts the main part. We will use while loop to iterate through all vertices in the graph. //For this purpose we define currentVertex variable which we will change in the end of each while cycle. var currentVertex: Vertex? = startVertex while let vertex = currentVertex { //Next line of code is an implementation of setting vertex as visited. //As it has been said, we should check only unvisited vertices in the graph, //So why don't just delete it from the set? This approach let us skip checking for *"if !vertex.visited then"* totalVertices.remove(vertex) //filteredNeighbours is an array that contains current vertex neighbours which aren't yet visited let filteredNeighbours = vertex.neighbours.filter { totalVertices.contains($0.0) } //Let's iterate through them for neighbour in filteredNeighbours { //These variable are more representative, than neighbour.0 or neighbour.1 let neighbourVertex = neighbour.0 let weight = neighbour.1 //Here we calculate new weight, that we can offer to neighbour. let theoreticNewWeight = vertex.pathLengthFromStart + weight //If it is smaller than neighbour's current pathLengthFromStart //Then we perform this code if theoreticNewWeight < neighbourVertex.pathLengthFromStart { //set new pathLengthFromStart neighbourVertex.pathLengthFromStart = theoreticNewWeight //set new pathVerticesFromStart neighbourVertex.pathVerticesFromStart = vertex.pathVerticesFromStart //append current vertex to neighbour's pathVerticesFromStart neighbourVertex.pathVerticesFromStart.append(neighbourVertex) } } //If totalVertices is empty, i.e. all vertices are visited //Than break the loop if totalVertices.isEmpty { currentVertex = nil break } //If loop is not broken, than pick next vertex for checkin from not visited. //Next vertex pathLengthFromStart should be the smallest one. currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } } } } ``` That's all! Now you can check this algorithm in the playground. On the main page there is a code for creating a random graph. Also there is a **VisualizedDijkstra.playground**. Use it to figure out the algorithm's flow in real (slowed :)) time. It is up to you how to implement some specific parts of the algorithm, you can use Array instead of Set, add _visited_ property to Vertex or you can create some local totalVertices Array/Set inside _func findShortestPaths(from startVertex: Vertex)_ to keep totalVertices Array/Set unchanged. This is a general explanation with one possible implementation :) # About this repository This repository contains two playgrounds: * To understand how does this algorithm works, I created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover, there are play/pause/stop buttons. * If you need only realisation of the algorithm without visualisation then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. # Demo video Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) # Credits WWDC 2017 Scholarship Project (Rejected) created by [Taras Nikulin](https://github.com/crabman448) ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift ================================================ /*: ## Dijkstra's algorithm visualization This playground is about the [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). Plyground works in 2 modes: * Auto visualization * Interactive visualization */ import UIKit import PlaygroundSupport /*: First of all, let's set up colors for our window and graph. The visited color will be applied to visited vertices. The checking color will be applied to an edge and an edge neighbor every time the algorithm is checking some vertex neighbors. And default colors are just initial colors for elements. */ GraphColors.sharedInstance.visitedColor = #colorLiteral(red: 0, green: 0.5898008943, blue: 1, alpha: 1) GraphColors.sharedInstance.checkingColor = #colorLiteral(red: 0.9411764741, green: 0.4980392158, blue: 0.3529411852, alpha: 1) GraphColors.sharedInstance.defaultEdgeColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) GraphColors.sharedInstance.defaultVertexColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) GraphColors.sharedInstance.mainWindowBackgroundColor = #colorLiteral(red: 0.921431005, green: 0.9214526415, blue: 0.9214410186, alpha: 1) GraphColors.sharedInstance.topViewBackgroundColor = #colorLiteral(red: 1, green: 0.4932718873, blue: 0.4739984274, alpha: 1) GraphColors.sharedInstance.buttonsBackgroundColor = #colorLiteral(red: 0, green: 0.3285208941, blue: 0.5748849511, alpha: 1) GraphColors.sharedInstance.graphBackgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) /*: Now, we need to create some graph. You can create graph with any vertices amount but I aware you from setting up too many, otherwise it will be hard to place all of them nicely on the screen. Also, you can change the animations' duration: slow down or speed up. */ let graph = Graph(verticesCount: 6) graph.interactiveNeighborCheckAnimationDuration = 1.2 graph.visualizationNeighborCheckAnimationDuration = 1.2 /*: Now, let's configure the graph's visual representation by passing the virtual graph to our window. For better perception open live view in full screen. */ let screenBounds = UIScreen.main.bounds let frame = CGRect(x: 0, y: 0, width: screenBounds.width * 0.8, height: screenBounds.height * 0.8) let window = Window(frame: frame) window.configure(graph: graph) PlaygroundPage.current.liveView = window /*: **Great!** Now we have graph on the screen. It is beautiful, isn't it? ;) Before the visualization starts, I recommend you to move vertices around the screen using you finger to be sure that all vertices and edges are properly visible. And a final step! Before you will see the visualization **(by pressing "Visualization" button),** please, read explanation of how the Dijkstra's algorithm works. Algorithm's flow: First of all, this program randomly decides which vertex will be the start one, then the program assigns a zero value to the start vertex path length from the start. Then the algorithm repeats following cycle until all vertices are marked as visited. Cycle: 1) From the non-visited vertices the algorithm picks a vertex with the shortest path length from the start (if there are more than one vertex with the same shortest path value, then algorithm picks any of them) 2) The algorithm marks picked vertex as visited. 3) The algorithm check all of its neighbors. If the current vertex path length from the start plus an edge weight to a neighbor less than the neighbor current path length from the start, than it assigns new path length from the start to the neihgbor. When all vertices are marked as visited, the algorithm's job is done. Now, you can see the shortest path from the start for every vertex by pressing the one you are interested in. Now, try yourself at the Dijkstra's algorithm. Press **"Interactive" button.** The program will mark the start vertex as visited and calculate new paths for its neighbors. You have to pick next vertex for the algorithm to check. If you are wrong, you will see a message on the screen. Good luck and have fun! ;) */ ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift ================================================ import UIKit public class EdgeRepresentation { private var graphColors: GraphColors = GraphColors.sharedInstance public private(set)var label: UILabel! public private(set)var layer: MyShapeLayer! public init(from vertex1: Vertex, to vertex2: Vertex, weight: Double) { guard let vertex1View = vertex1.view, let vertex2View = vertex2.view else { assertionFailure("passed vertices without configured views") return } let x1 = vertex1View.frame.origin.x let y1 = vertex1View.frame.origin.y let width1 = vertex1View.frame.width let height1 = vertex1View.frame.height let x2 = vertex2View.frame.origin.x let y2 = vertex2View.frame.origin.y let width2 = vertex2View.frame.width let height2 = vertex2View.frame.height var startPoint: CGPoint var endPoint: CGPoint if y1 == y2 { if x1 < x2 { startPoint = CGPoint(x: x1 + width1, y: y1 + height1 / 2) endPoint = CGPoint(x: x2, y: y2 + height2 / 2) } else { startPoint = CGPoint(x: x1, y: y1 + height1 / 2) endPoint = CGPoint(x: x2 + width2, y: y2 + height2 / 2) } } else { startPoint = CGPoint(x: x1 + width1 / 2, y: y1 + height1) endPoint = CGPoint(x: x2 + width2 / 2, y: y2) } let arcDiameter: CGFloat = 20 var circleOrigin: CGPoint! if endPoint.x == startPoint.x { startPoint.y -= 1 endPoint.y += 1 let x = startPoint.x - arcDiameter / 2 let y = startPoint.y + ((endPoint.y - startPoint.y) / 2 * 1.25 - arcDiameter / 2) circleOrigin = CGPoint(x: x, y: y) } else if endPoint.y == startPoint.y { let x = startPoint.x + ((endPoint.x - startPoint.x) / 2 * 1.25 - arcDiameter / 2) let y = startPoint.y + ((endPoint.y - startPoint.y) / 2 * 1.25 - arcDiameter / 2) circleOrigin = CGPoint(x: x, y: y) } else { startPoint.x -= 1 endPoint.x += 1 startPoint.y -= 1 endPoint.y += 1 let x = startPoint.x + ((endPoint.x - startPoint.x) / 2 * 1.25 - arcDiameter / 2) let y = startPoint.y + ((endPoint.y - startPoint.y) / 2 * 1.25 - arcDiameter / 2) circleOrigin = CGPoint(x: x, y: y) } let path = UIBezierPath() path.move(to: startPoint) path.addLine(to: endPoint) let label = UILabel(frame: CGRect(origin: circleOrigin, size: CGSize(width: arcDiameter, height: arcDiameter))) label.textAlignment = .center label.backgroundColor = graphColors.defaultEdgeColor label.clipsToBounds = true label.adjustsFontSizeToFitWidth = true label.layer.cornerRadius = arcDiameter / 2 label.text = "" let shapeLayer = MyShapeLayer() shapeLayer.path = path.cgPath shapeLayer.strokeColor = graphColors.defaultEdgeColor.cgColor shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.lineWidth = 2.0 shapeLayer.startPoint = startPoint shapeLayer.endPoint = endPoint shapeLayer.actions = ["position" : NSNull(), "bounds" : NSNull(), "path" : NSNull()] self.layer = shapeLayer self.label = label self.label.text = "\(weight)" } public func setCheckingColor() { layer.strokeColor = graphColors.checkingColor.cgColor label.backgroundColor = graphColors.checkingColor } public func setDefaultColor() { layer.strokeColor = graphColors.defaultEdgeColor.cgColor label.backgroundColor = graphColors.defaultEdgeColor } public func setText(text: String) { label.text = text } } extension EdgeRepresentation: Equatable { public static func ==(lhs: EdgeRepresentation, rhs: EdgeRepresentation) -> Bool { return lhs.label.hashValue == rhs.label.hashValue && lhs.layer.hashValue == rhs.layer.hashValue } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift ================================================ import UIKit public class ErrorView: UIView { private var label: UILabel! public override init(frame: CGRect) { super.init(frame: frame) commonInit() } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func commonInit() { backgroundColor = UIColor(red: 242/255, green: 156/255, blue: 84/255, alpha: 1) layer.cornerRadius = 10 let labelFrame = CGRect(x: 10, y: 10, width: frame.width - 20, height: frame.height - 20) label = UILabel(frame: labelFrame) label.numberOfLines = 0 label.adjustsFontSizeToFitWidth = true label.textAlignment = .center label.textColor = UIColor.white addSubview(label) } public func setText(text: String) { label.text = text } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift ================================================ import UIKit public class MyShapeLayer: CAShapeLayer { public var startPoint: CGPoint? public var endPoint: CGPoint? } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift ================================================ import UIKit public class RoundedButton: UIButton { private var graphColors: GraphColors = GraphColors.sharedInstance public override init(frame: CGRect) { super.init(frame: frame) commonInit() } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func commonInit() { backgroundColor = graphColors.buttonsBackgroundColor titleLabel?.adjustsFontSizeToFitWidth = true layer.cornerRadius = 7 } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift ================================================ import UIKit public class VertexView: UIButton { public var vertex: Vertex? private var idLabel: UILabel! private var pathLengthLabel: UILabel! private var graphColors: GraphColors = GraphColors.sharedInstance public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } public override init(frame: CGRect) { precondition(frame.height == frame.width) precondition(frame.height >= 30) super.init(frame: frame) backgroundColor = graphColors.defaultVertexColor layer.cornerRadius = frame.width / 2 clipsToBounds = true setupIdLabel() setupPathLengthFromStartLabel() } private func setupIdLabel() { let x: CGFloat = frame.width * 0.2 let y: CGFloat = 0 let width: CGFloat = frame.width * 0.6 let height: CGFloat = frame.height / 2 let idLabelFrame = CGRect(x: x, y: y, width: width, height: height) idLabel = UILabel(frame: idLabelFrame) idLabel.textAlignment = .center idLabel.adjustsFontSizeToFitWidth = true addSubview(idLabel) } private func setupPathLengthFromStartLabel() { let x: CGFloat = frame.width * 0.2 let y: CGFloat = frame.height / 2 let width: CGFloat = frame.width * 0.6 let height: CGFloat = frame.height / 2 let pathLengthLabelFrame = CGRect(x: x, y: y, width: width, height: height) pathLengthLabel = UILabel(frame: pathLengthLabelFrame) pathLengthLabel.textAlignment = .center pathLengthLabel.adjustsFontSizeToFitWidth = true addSubview(pathLengthLabel) } public func setIdLabel(text: String) { idLabel.text = text } public func setPathLengthLabel(text: String) { pathLengthLabel.text = text } public func setLabelsTextColor(color: UIColor) { idLabel.textColor = color pathLengthLabel.textColor = color } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift ================================================ import Foundation import UIKit public enum GraphState { case initial case autoVisualization case interactiveVisualization case parsing case completed } public class Graph { private var verticesCount: UInt private var _vertices: Set = Set() public weak var delegate: GraphDelegate? public var nextVertices: [Vertex] = [] public var state: GraphState = .initial public var pauseVisualization = false public var stopVisualization = false public var startVertex: Vertex? public var interactiveNeighborCheckAnimationDuration: Double = 1.8 { didSet { _interactiveOneSleepDuration = UInt32(interactiveNeighborCheckAnimationDuration * 1000000.0 / 3.0) } } private var _interactiveOneSleepDuration: UInt32 = 600000 public var visualizationNeighborCheckAnimationDuration: Double = 2.25 { didSet { _visualizationOneSleepDuration = UInt32(visualizationNeighborCheckAnimationDuration * 1000000.0 / 3.0) } } private var _visualizationOneSleepDuration: UInt32 = 750000 public var vertices: Set { return _vertices } public init(verticesCount: UInt) { self.verticesCount = verticesCount } public func removeGraph() { _vertices.removeAll() startVertex = nil } public func createNewGraph() { guard _vertices.isEmpty, startVertex == nil else { assertionFailure("Clear graph before creating new one") return } createNotConnectedVertices() setupConnections() let offset = Int(arc4random_uniform(UInt32(_vertices.count))) let index = _vertices.index(_vertices.startIndex, offsetBy: offset) startVertex = _vertices[index] setVertexLevels() } private func clearCache() { _vertices.forEach { $0.clearCache() } } public func reset() { for vertex in _vertices { vertex.clearCache() } } private func createNotConnectedVertices() { for i in 0.. Vertex { var newSet = _vertices newSet.remove(vertex) let offset = Int(arc4random_uniform(UInt32(newSet.count))) let index = newSet.index(newSet.startIndex, offsetBy: offset) return newSet[index] } private func setVertexLevels() { _vertices.forEach { $0.clearLevelInfo() } guard let startVertex = startVertex else { assertionFailure() return } var queue: [Vertex] = [startVertex] startVertex.levelChecked = true //BFS while !queue.isEmpty { let currentVertex = queue.first! for edge in currentVertex.edges { let neighbor = edge.neighbor if !neighbor.levelChecked { neighbor.levelChecked = true neighbor.level = currentVertex.level + 1 queue.append(neighbor) } } queue.removeFirst() } } public func findShortestPathsWithVisualization(completion: () -> Void) { guard let startVertex = self.startVertex else { assertionFailure("start vertex is nil") return } clearCache() startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) var currentVertex: Vertex? = startVertex var totalVertices = _vertices breakableLoop: while let vertex = currentVertex { totalVertices.remove(vertex) while pauseVisualization == true { if stopVisualization == true { break breakableLoop } } if stopVisualization == true { break breakableLoop } DispatchQueue.main.async { vertex.setVisitedColor() } usleep(750000) vertex.visited = true let filteredEdges = vertex.edges.filter { !$0.neighbor.visited } for edge in filteredEdges { let neighbor = edge.neighbor let weight = edge.weight let edgeRepresentation = edge.edgeRepresentation while pauseVisualization == true { if stopVisualization == true { break breakableLoop } } if stopVisualization == true { break breakableLoop } DispatchQueue.main.async { edgeRepresentation?.setCheckingColor() neighbor.setCheckingPathColor() self.delegate?.willCompareVertices(startVertexPathLength: vertex.pathLengthFromStart, edgePathLength: weight, endVertexPathLength: neighbor.pathLengthFromStart) } usleep(_visualizationOneSleepDuration) let theoreticNewWeight = vertex.pathLengthFromStart + weight if theoreticNewWeight < neighbor.pathLengthFromStart { while pauseVisualization == true { if stopVisualization == true { break breakableLoop } } if stopVisualization == true { break breakableLoop } neighbor.pathLengthFromStart = theoreticNewWeight neighbor.pathVerticesFromStart = vertex.pathVerticesFromStart neighbor.pathVerticesFromStart.append(neighbor) } usleep(_visualizationOneSleepDuration) DispatchQueue.main.async { self.delegate?.didFinishCompare() edge.edgeRepresentation?.setDefaultColor() edge.neighbor.setDefaultColor() } usleep(_visualizationOneSleepDuration) } if totalVertices.isEmpty { currentVertex = nil break } currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } } if stopVisualization == true { DispatchQueue.main.async { self.delegate?.didStop() } } else { completion() } } public func parseNeighborsFor(vertex: Vertex, completion: @escaping () -> ()) { DispatchQueue.main.async { vertex.setVisitedColor() } DispatchQueue.global(qos: .background).async { vertex.visited = true let nonVisitedVertices = self._vertices.filter { $0.visited == false } if nonVisitedVertices.isEmpty { self.state = .completed DispatchQueue.main.async { self.delegate?.didCompleteGraphParsing() } return } let filteredEdges = vertex.edges.filter { !$0.neighbor.visited } breakableLoop: for edge in filteredEdges { while self.pauseVisualization == true { if self.stopVisualization == true { break breakableLoop } } if self.stopVisualization == true { break breakableLoop } let weight = edge.weight let neighbor = edge.neighbor DispatchQueue.main.async { edge.neighbor.setCheckingPathColor() edge.edgeRepresentation?.setCheckingColor() self.delegate?.willCompareVertices(startVertexPathLength: vertex.pathLengthFromStart, edgePathLength: weight, endVertexPathLength: neighbor.pathLengthFromStart) } usleep(self._interactiveOneSleepDuration) let theoreticNewWeight = vertex.pathLengthFromStart + weight if theoreticNewWeight < neighbor.pathLengthFromStart { while self.pauseVisualization == true { if self.stopVisualization == true { break breakableLoop } } if self.stopVisualization == true { break breakableLoop } neighbor.pathLengthFromStart = theoreticNewWeight neighbor.pathVerticesFromStart = vertex.pathVerticesFromStart neighbor.pathVerticesFromStart.append(neighbor) } usleep(self._interactiveOneSleepDuration) while self.pauseVisualization == true { if self.stopVisualization == true { break breakableLoop } } if self.stopVisualization == true { break breakableLoop } DispatchQueue.main.async { self.delegate?.didFinishCompare() edge.neighbor.setDefaultColor() edge.edgeRepresentation?.setDefaultColor() } usleep(self._interactiveOneSleepDuration) } if self.stopVisualization == true { DispatchQueue.main.async { self.delegate?.didStop() } } else { let nextVertexPathLength = nonVisitedVertices.sorted { $0.pathLengthFromStart < $1.pathLengthFromStart }.first!.pathLengthFromStart self.nextVertices = nonVisitedVertices.filter { $0.pathLengthFromStart == nextVertexPathLength } completion() } } } public func didTapVertex(vertex: Vertex) { if nextVertices.contains(vertex) { delegate?.willStartVertexNeighborsChecking() state = .parsing parseNeighborsFor(vertex: vertex) { self.state = .interactiveVisualization self.delegate?.didFinishVertexNeighborsChecking() } } else { self.delegate?.didTapWrongVertex() } } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift ================================================ import UIKit public class GraphColors { public static let sharedInstance: GraphColors = GraphColors() private init() { } public var mainWindowBackgroundColor: UIColor = #colorLiteral(red: 0.921431005, green: 0.9214526415, blue: 0.9214410186, alpha: 1) public var topViewBackgroundColor: UIColor = #colorLiteral(red: 1, green: 0.4932718873, blue: 0.4739984274, alpha: 1) public var graphBackgroundColor: UIColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) public var defaultVertexColor: UIColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) public var defaultEdgeColor: UIColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) public var checkingColor: UIColor = #colorLiteral(red: 0.9411764741, green: 0.4980392158, blue: 0.3529411852, alpha: 1) public var visitedColor: UIColor = #colorLiteral(red: 0, green: 0.5898008943, blue: 1, alpha: 1) public var buttonsBackgroundColor: UIColor = #colorLiteral(red: 0, green: 0.3285208941, blue: 0.5748849511, alpha: 1) } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift ================================================ import UIKit public class GraphView: UIView { private var graph: Graph private var panningView: VertexView? = nil private var graphColors = GraphColors.sharedInstance public init(frame: CGRect, graph: Graph) { self.graph = graph super.init(frame: frame) backgroundColor = graphColors.graphBackgroundColor layer.cornerRadius = 15 } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } public func removeGraph() { for vertex in graph.vertices { if let view = vertex.view { view.removeFromSuperview() vertex.view = nil } } for vertex in graph.vertices { for edge in vertex.edges { if let edgeRepresentation = edge.edgeRepresentation { edgeRepresentation.layer.removeFromSuperlayer() edgeRepresentation.label.removeFromSuperview() edge.edgeRepresentation = nil } } } } public func createNewGraph() { setupVertexViews() setupEdgeRepresentations() addGraph() } public func reset() { for vertex in graph.vertices { vertex.edges.forEach { $0.edgeRepresentation?.setDefaultColor() } vertex.setDefaultColor() } } private func addGraph() { for vertex in graph.vertices { for edge in vertex.edges { if let edgeRepresentation = edge.edgeRepresentation { layer.addSublayer(edgeRepresentation.layer) addSubview(edgeRepresentation.label) } } } for vertex in graph.vertices { if let view = vertex.view { addSubview(view) } } } private func setupVertexViews() { var level = 0 var buildViewQueue = [graph.startVertex!] let itemWidth: CGFloat = 40 while !buildViewQueue.isEmpty { let levelItemsCount = CGFloat(buildViewQueue.count) let xStep = (frame.width - levelItemsCount * itemWidth) / (levelItemsCount + 1) var previousVertexMaxX: CGFloat = 0.0 for vertex in buildViewQueue { let x: CGFloat = previousVertexMaxX + xStep let y: CGFloat = CGFloat(level * 100) previousVertexMaxX = x + itemWidth let frame = CGRect(x: x, y: y, width: itemWidth, height: itemWidth) let vertexView = VertexView(frame: frame) vertex.view = vertexView vertexView.vertex = vertex vertex.view?.setIdLabel(text: vertex.identifier) vertex.view?.setPathLengthLabel(text: "\(vertex.pathLengthFromStart)") vertex.view?.addTarget(self, action: #selector(didTapVertex(sender:)), for: .touchUpInside) let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(recognizer:))) vertex.view?.addGestureRecognizer(panGesture) } level += 1 buildViewQueue = graph.vertices.filter { $0.level == level } } } private var movingVertexInputEdges: [EdgeRepresentation] = [] private var movingVertexOutputEdges: [EdgeRepresentation] = [] @objc private func handlePan(recognizer: UIPanGestureRecognizer) { guard let vertexView = recognizer.view as? VertexView, let vertex = vertexView.vertex else { return } if panningView != nil { if panningView != vertexView { return } } switch recognizer.state { case .began: let movingVertexViewFrame = vertexView.frame let sizedVertexView = CGRect(x: movingVertexViewFrame.origin.x - 10, y: movingVertexViewFrame.origin.y - 10, width: movingVertexViewFrame.width + 20, height: movingVertexViewFrame.height + 20) vertex.edges.forEach { edge in if let edgeRepresentation = edge.edgeRepresentation{ if sizedVertexView.contains(edgeRepresentation.layer.startPoint!) { movingVertexOutputEdges.append(edgeRepresentation) } else { movingVertexInputEdges.append(edgeRepresentation) } } } panningView = vertexView case .changed: if movingVertexOutputEdges.isEmpty && movingVertexInputEdges.isEmpty { return } let translation = recognizer.translation(in: self) if vertexView.frame.origin.x + translation.x <= 0 || vertexView.frame.origin.y + translation.y <= 0 || (vertexView.frame.origin.x + vertexView.frame.width + translation.x) >= frame.width || (vertexView.frame.origin.y + vertexView.frame.height + translation.y) >= frame.height { break } movingVertexInputEdges.forEach { edgeRepresentation in let originalLabelCenter = edgeRepresentation.label.center edgeRepresentation.label.center = CGPoint(x: originalLabelCenter.x + translation.x * 0.625, y: originalLabelCenter.y + translation.y * 0.625) CATransaction.begin() CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions) let newPath = path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: false) edgeRepresentation.layer.path = newPath CATransaction.commit() } movingVertexOutputEdges.forEach { edgeRepresentation in let originalLabelCenter = edgeRepresentation.label.center edgeRepresentation.label.center = CGPoint(x: originalLabelCenter.x + translation.x * 0.375, y: originalLabelCenter.y + translation.y * 0.375) CATransaction.begin() CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions) let newPath = path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: true) edgeRepresentation.layer.path = newPath CATransaction.commit() } vertexView.center = CGPoint(x: vertexView.center.x + translation.x, y: vertexView.center.y + translation.y) recognizer.setTranslation(CGPoint.zero, in: self) case .ended: movingVertexInputEdges = [] movingVertexOutputEdges = [] panningView = nil default: break } } private func path(fromEdgeRepresentation edgeRepresentation: EdgeRepresentation, movingVertex: Vertex, translation: CGPoint, outPath: Bool) -> CGPath { let bezier = UIBezierPath() if outPath == true { bezier.move(to: edgeRepresentation.layer.endPoint!) let startPoint = CGPoint(x: edgeRepresentation.layer.startPoint!.x + translation.x, y: edgeRepresentation.layer.startPoint!.y + translation.y) edgeRepresentation.layer.startPoint = startPoint bezier.addLine(to: startPoint) } else { bezier.move(to: edgeRepresentation.layer.startPoint!) let endPoint = CGPoint(x: edgeRepresentation.layer.endPoint!.x + translation.x, y: edgeRepresentation.layer.endPoint!.y + translation.y) edgeRepresentation.layer.endPoint = endPoint bezier.addLine(to: endPoint) } return bezier.cgPath } @objc private func didTapVertex(sender: AnyObject) { DispatchQueue.main.async { if self.graph.state == .completed { for vertex in self.graph.vertices { vertex.edges.forEach { $0.edgeRepresentation?.setDefaultColor() } vertex.setVisitedColor() } if let vertexView = sender as? VertexView, let vertex = vertexView.vertex { for (index, pathVertex) in vertex.pathVerticesFromStart.enumerated() { pathVertex.setCheckingPathColor() if vertex.pathVerticesFromStart.count > index + 1 { let nextVertex = vertex.pathVerticesFromStart[index + 1] if let edge = pathVertex.edges.filter({ $0.neighbor == nextVertex }).first { edge.edgeRepresentation?.setCheckingColor() } } } } } else if self.graph.state == .interactiveVisualization { if let vertexView = sender as? VertexView, let vertex = vertexView.vertex { if vertex.visited { return } else { self.graph.didTapVertex(vertex: vertex) } } } } } private func setupEdgeRepresentations() { var edgeQueue: [Vertex] = [graph.startVertex!] //BFS while !edgeQueue.isEmpty { let currentVertex = edgeQueue.first! currentVertex.haveAllEdges = true for edge in currentVertex.edges { let neighbor = edge.neighbor let weight = edge.weight if !neighbor.haveAllEdges { let edgeRepresentation = EdgeRepresentation(from: currentVertex, to: neighbor, weight: weight) edge.edgeRepresentation = edgeRepresentation let index = neighbor.edges.index(where: { $0.neighbor == currentVertex })! neighbor.edges[index].edgeRepresentation = edgeRepresentation edgeQueue.append(neighbor) } } edgeQueue.removeFirst() } } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift ================================================ import Foundation public class Edge { public var neighbor: Vertex public var weight: Double public var edgeRepresentation: EdgeRepresentation? public init(vertex: Vertex, weight: Double) { self.neighbor = vertex self.weight = weight } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift ================================================ import UIKit public class Vertex { private var graphColors: GraphColors = GraphColors.sharedInstance public var view: VertexView? public var identifier: String public var edges: [Edge] = [] public var pathVerticesFromStart: [Vertex] = [] public var level: Int = 0 public var levelChecked: Bool = false public var haveAllEdges: Bool = false public var visited: Bool = false public var pathLengthFromStart: Double = Double.infinity { didSet { DispatchQueue.main.async { self.view?.setPathLengthLabel(text: "\(self.pathLengthFromStart)") } } } public init(identifier: String) { self.identifier = identifier } public func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] visited = false } public func clearLevelInfo() { level = 0 levelChecked = false } public func setVisitedColor() { view?.backgroundColor = graphColors.visitedColor view?.setLabelsTextColor(color: UIColor.white) } public func setCheckingPathColor() { view?.backgroundColor = graphColors.checkingColor } public func setDefaultColor() { view?.backgroundColor = graphColors.defaultVertexColor view?.setLabelsTextColor(color: UIColor.black) } } extension Vertex: Hashable { public var hashValue: Int { return identifier.hashValue } } extension Vertex: Equatable { public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { return lhs.hashValue == rhs.hashValue } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift ================================================ import Foundation import UIKit public protocol GraphDelegate: class { func willCompareVertices(startVertexPathLength: Double, edgePathLength: Double, endVertexPathLength: Double) func didFinishCompare() func didCompleteGraphParsing() func didTapWrongVertex() func didStop() func willStartVertexNeighborsChecking() func didFinishVertexNeighborsChecking() } public class Window: UIView, GraphDelegate { public var graphView: GraphView! private var topView: UIView! private var createGraphButton: RoundedButton! private var startVisualizationButton: RoundedButton! private var startInteractiveVisualizationButton: RoundedButton! private var startButton: UIButton! private var pauseButton: UIButton! private var stopButton: UIButton! private var comparisonLabel: UILabel! private var activityIndicator: UIActivityIndicatorView! private var graph: Graph! private var numberOfVertices: UInt! private var graphColors = GraphColors.sharedInstance public override init(frame: CGRect) { super.init(frame: frame) self.frame = frame backgroundColor = graphColors.mainWindowBackgroundColor } public required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } public func configure(graph: Graph) { self.graph = graph graph.createNewGraph() graph.delegate = self let frame = CGRect(x: 10, y: 170, width: self.frame.width - 20, height: self.frame.height - 180) graphView = GraphView(frame: frame, graph: graph) graphView.createNewGraph() addSubview(graphView) configureCreateGraphButton() configureStartVisualizationButton() configureStartInteractiveVisualizationButton() configureStartButton() configurePauseButton() configureStopButton() configureComparisonLabel() configureActivityIndicator() topView = UIView(frame: CGRect(x: 10, y: 10, width: frame.width - 20, height: 150)) topView.backgroundColor = graphColors.topViewBackgroundColor topView.layer.cornerRadius = 15 addSubview(topView) topView.addSubview(createGraphButton) topView.addSubview(startVisualizationButton) topView.addSubview(startInteractiveVisualizationButton) topView.addSubview(startButton) topView.addSubview(pauseButton) topView.addSubview(stopButton) topView.addSubview(comparisonLabel) topView.addSubview(activityIndicator) } private func configureCreateGraphButton() { let frame = CGRect(x: center.x - 200, y: 12, width: 100, height: 34) createGraphButton = RoundedButton(frame: frame) createGraphButton.setTitle("New graph", for: .normal) createGraphButton.addTarget(self, action: #selector(createGraphButtonTap), for: .touchUpInside) } private func configureStartVisualizationButton() { let frame = CGRect(x: center.x - 50, y: 12, width: 100, height: 34) startVisualizationButton = RoundedButton(frame: frame) startVisualizationButton.setTitle("Auto", for: .normal) startVisualizationButton.addTarget(self, action: #selector(startVisualizationButtonDidTap), for: .touchUpInside) } private func configureStartInteractiveVisualizationButton() { let frame = CGRect(x: center.x + 100, y: 12, width: 100, height: 34) startInteractiveVisualizationButton = RoundedButton(frame: frame) startInteractiveVisualizationButton.setTitle("Interactive", for: .normal) startInteractiveVisualizationButton.addTarget(self, action: #selector(startInteractiveVisualizationButtonDidTap), for: .touchUpInside) } private func configureStartButton() { let frame = CGRect(x: center.x - 65, y: 56, width: 30, height: 30) startButton = UIButton(frame: frame) let playImage = UIImage(named: "Start.png") startButton.setImage(playImage, for: .normal) startButton.isEnabled = false startButton.addTarget(self, action: #selector(didTapStartButton), for: .touchUpInside) } private func configurePauseButton() { let frame = CGRect(x: center.x - 15, y: 56, width: 30, height: 30) pauseButton = UIButton(frame: frame) let pauseImage = UIImage(named: "Pause.png") pauseButton.setImage(pauseImage, for: .normal) pauseButton.isEnabled = false pauseButton.addTarget(self, action: #selector(didTapPauseButton), for: .touchUpInside) } private func configureStopButton() { let frame = CGRect(x: center.x + 35, y: 56, width: 30, height: 30) stopButton = UIButton(frame: frame) let stopImage = UIImage(named: "Stop.png") stopButton.setImage(stopImage, for: .normal) stopButton.isEnabled = false stopButton.addTarget(self, action: #selector(didTapStopButton), for: .touchUpInside) } private func configureComparisonLabel() { let size = CGSize(width: 250, height: 42) let origin = CGPoint(x: center.x - 125, y: 96) let frame = CGRect(origin: origin, size: size) comparisonLabel = UILabel(frame: frame) comparisonLabel.textAlignment = .center comparisonLabel.text = "Have fun!" } private func configureActivityIndicator() { let size = CGSize(width: 50, height: 42) let origin = CGPoint(x: center.x - 25, y: 100) let activityIndicatorFrame = CGRect(origin: origin, size: size) activityIndicator = UIActivityIndicatorView(frame: activityIndicatorFrame) activityIndicator.style = .whiteLarge } @objc private func createGraphButtonTap() { comparisonLabel.text = "" graphView.removeGraph() graph.removeGraph() graph.createNewGraph() graphView.createNewGraph() graph.state = .initial } @objc private func startVisualizationButtonDidTap() { comparisonLabel.text = "" pauseButton.isEnabled = true stopButton.isEnabled = true createGraphButton.isEnabled = false startVisualizationButton.isEnabled = false startInteractiveVisualizationButton.isEnabled = false createGraphButton.alpha = 0.5 startVisualizationButton.alpha = 0.5 startInteractiveVisualizationButton.alpha = 0.5 if graph.state == .completed { graphView.reset() graph.reset() } graph.state = .autoVisualization DispatchQueue.global(qos: .background).async { self.graph.findShortestPathsWithVisualization { self.graph.state = .completed DispatchQueue.main.async { self.startButton.isEnabled = false self.pauseButton.isEnabled = false self.stopButton.isEnabled = false self.createGraphButton.isEnabled = true self.startVisualizationButton.isEnabled = true self.startInteractiveVisualizationButton.isEnabled = true self.createGraphButton.alpha = 1 self.startVisualizationButton.alpha = 1 self.startInteractiveVisualizationButton.alpha = 1 self.comparisonLabel.text = "Completed!" } } } } @objc private func startInteractiveVisualizationButtonDidTap() { comparisonLabel.text = "" pauseButton.isEnabled = true stopButton.isEnabled = true createGraphButton.isEnabled = false startVisualizationButton.isEnabled = false startInteractiveVisualizationButton.isEnabled = false createGraphButton.alpha = 0.5 startVisualizationButton.alpha = 0.5 startInteractiveVisualizationButton.alpha = 0.5 if graph.state == .completed { graphView.reset() graph.reset() } guard let startVertex = graph.startVertex else { assertionFailure("startVertex is nil") return } startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) graph.state = .parsing graph.parseNeighborsFor(vertex: startVertex) { self.graph.state = .interactiveVisualization DispatchQueue.main.async { self.comparisonLabel.text = "Pick next vertex" } } } @objc private func didTapStartButton() { startButton.isEnabled = false pauseButton.isEnabled = true DispatchQueue.global(qos: .utility).async { self.graph.pauseVisualization = false } } @objc private func didTapPauseButton() { startButton.isEnabled = true pauseButton.isEnabled = false DispatchQueue.global(qos: .utility).async { self.graph.pauseVisualization = true } } @objc private func didTapStopButton() { startButton.isEnabled = false pauseButton.isEnabled = false comparisonLabel.text = "" activityIndicator.startAnimating() if graph.state == .parsing || graph.state == .autoVisualization { graph.stopVisualization = true } else if graph.state == .interactiveVisualization { didStop() } } private func setButtonsToInitialState() { createGraphButton.isEnabled = true startVisualizationButton.isEnabled = true startInteractiveVisualizationButton.isEnabled = true startButton.isEnabled = false pauseButton.isEnabled = false stopButton.isEnabled = false createGraphButton.alpha = 1 startVisualizationButton.alpha = 1 startInteractiveVisualizationButton.alpha = 1 } private func showError(error: String) { DispatchQueue.main.async { let size = CGSize(width: 250, height: 42) let origin = CGPoint(x: self.topView.center.x - 125, y: 96) let frame = CGRect(origin: origin, size: size) let errorView = ErrorView(frame: frame) errorView.setText(text: error) self.topView.addSubview(errorView) UIView.animate(withDuration: 2, animations: { errorView.alpha = 0 }, completion: { _ in errorView.removeFromSuperview() }) } } // MARK: GraphDelegate public func didCompleteGraphParsing() { graph.state = .completed setButtonsToInitialState() comparisonLabel.text = "Completed!" } public func didTapWrongVertex() { if !subviews.contains { $0 is ErrorView } { showError(error: "You have picked wrong next vertex") } } public func willCompareVertices(startVertexPathLength: Double, edgePathLength: Double, endVertexPathLength: Double) { DispatchQueue.main.async { if startVertexPathLength + edgePathLength < endVertexPathLength { self.comparisonLabel.text = "\(startVertexPathLength) + \(edgePathLength) < \(endVertexPathLength) 👍" } else { self.comparisonLabel.text = "\(startVertexPathLength) + \(edgePathLength) >= \(endVertexPathLength) 👎" } } } public func didFinishCompare() { DispatchQueue.main.async { self.comparisonLabel.text = "" } } public func didStop() { graph.state = .initial graph.stopVisualization = false graph.pauseVisualization = false graphView.reset() graph.reset() setButtonsToInitialState() activityIndicator.stopAnimating() } public func willStartVertexNeighborsChecking() { DispatchQueue.main.async { self.comparisonLabel.text = "" } } public func didFinishVertexNeighborsChecking() { DispatchQueue.main.async { self.comparisonLabel.text = "Pick next vertex" } } } ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground ================================================ ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ OBJ_18 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_9 /* main.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 232D7939216F76F700831A74 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; OBJ_12 /* DiningPhilosophers */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = DiningPhilosophers; sourceTree = BUILT_PRODUCTS_DIR; }; OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; OBJ_9 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ OBJ_19 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 0; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ OBJ_11 /* Products */ = { isa = PBXGroup; children = ( OBJ_12 /* DiningPhilosophers */, ); name = Products; sourceTree = BUILT_PRODUCTS_DIR; }; OBJ_5 = { isa = PBXGroup; children = ( 232D7939216F76F700831A74 /* README.md */, OBJ_6 /* Package.swift */, OBJ_7 /* Sources */, OBJ_11 /* Products */, ); sourceTree = ""; }; OBJ_7 /* Sources */ = { isa = PBXGroup; children = ( OBJ_8 /* DiningPhilosophers */, ); path = Sources; sourceTree = ""; }; OBJ_8 /* DiningPhilosophers */ = { isa = PBXGroup; children = ( OBJ_9 /* main.swift */, ); name = DiningPhilosophers; path = Sources; sourceTree = SOURCE_ROOT; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ OBJ_13 /* DiningPhilosophers */ = { isa = PBXNativeTarget; buildConfigurationList = OBJ_14 /* Build configuration list for PBXNativeTarget "DiningPhilosophers" */; buildPhases = ( OBJ_17 /* Sources */, OBJ_19 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = DiningPhilosophers; productName = DiningPhilosophers; productReference = OBJ_12 /* DiningPhilosophers */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ OBJ_1 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 9999; TargetAttributes = { OBJ_13 = { LastSwiftMigration = 1000; }; }; }; buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "DiningPhilosophers" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = OBJ_5; productRefGroup = OBJ_11 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( OBJ_13 /* DiningPhilosophers */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ OBJ_17 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 0; files = ( OBJ_18 /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ OBJ_15 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = "$(PLATFORM_DIR)/Developer/Library/Frameworks"; HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = DiningPhilosophers.xcodeproj/DiningPhilosophers_Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; SUPPORTED_PLATFORMS = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; SWIFT_VERSION = 4.2; TARGET_NAME = DiningPhilosophers; }; name = Debug; }; OBJ_16 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = "$(PLATFORM_DIR)/Developer/Library/Frameworks"; HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = DiningPhilosophers.xcodeproj/DiningPhilosophers_Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx @executable_path"; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited)"; SUPPORTED_PLATFORMS = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; SWIFT_FORCE_DYNAMIC_LINK_STDLIB = YES; SWIFT_FORCE_STATIC_LINK_STDLIB = NO; SWIFT_VERSION = 4.2; TARGET_NAME = DiningPhilosophers; }; name = Release; }; OBJ_3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_NS_ASSERTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; OTHER_SWIFT_FLAGS = "-DXcode"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; USE_HEADERMAP = NO; }; name = Debug; }; OBJ_4 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_INSTALL_NAME_BASE = "@rpath"; GCC_OPTIMIZATION_LEVEL = s; MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_SWIFT_FLAGS = "-DXcode"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; SWIFT_OPTIMIZATION_LEVEL = "-O"; USE_HEADERMAP = NO; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ OBJ_14 /* Build configuration list for PBXNativeTarget "DiningPhilosophers" */ = { isa = XCConfigurationList; buildConfigurations = ( OBJ_15 /* Debug */, OBJ_16 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; OBJ_2 /* Build configuration list for PBXProject "DiningPhilosophers" */ = { isa = XCConfigurationList; buildConfigurations = ( OBJ_3 /* Debug */, OBJ_4 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ }; rootObject = OBJ_1 /* Project object */; } ================================================ FILE: DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme ================================================ ================================================ FILE: DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist ================================================ SchemeUserState DiningPhilosophers.xcscheme SuppressBuildableAutocreation ================================================ FILE: DiningPhilosophers/LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: DiningPhilosophers/Package.swift ================================================ import PackageDescription let package = Package( name: "DiningPhilosophers" ) ================================================ FILE: DiningPhilosophers/README.md ================================================ # Dining Philosophers The dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using [GCD](https://apple.github.io/swift-corelibs-libdispatch/) and [Semaphore](https://developer.apple.com/reference/dispatch/dispatchsemaphore) in Swift) Written for Swift Algorithm Club by Jacopo Mangiavacchi # Introduction In computer science, the dining philosophers problem is often used in the concurrent algorithm design to illustrate synchronization issues and techniques for resolving them. It was originally formulated in 1965 by Edsger Dijkstra as a student exam exercise, presented in terms of computers competing for access to tape drive peripherals. Soon after, Tony Hoare gave the problem its present formulation. This Swift implementation is based on the Chandy/Misra solution, and it uses the GCD Dispatch and Semaphores on the Swift cross platform. # Problem statement Five silent philosophers sit at a round table with bowls of spaghetti. Forks are placed between each pair of adjacent philosophers. Each philosopher must alternately think and eat. A philosopher can only eat spaghetti when they have both left and right forks. Since each fork can be held by only one philosopher, a philosopher can use the fork only if it is not being used by another philosopher. When a philosopher finishes eating, they need to put down both forks so that the forks become available to others. A philosopher can take the fork on their right or the one on their left as they become available, but they cannot start eating before getting both forks. Eating is not limited by the remaining amounts of spaghetti or stomach space; an infinite supply and an infinite demand are assumed. The problem is how to design a discipline of behavior (a concurrent algorithm) such that no philosopher will starve; i.e., each can forever continue to alternate between eating and thinking, assuming that no philosopher can know when others may want to eat or think. This is an illustration of a dining table: ![Dining Philosophers table](https://upload.wikimedia.org/wikipedia/commons/7/7b/An_illustration_of_the_dining_philosophers_problem.png) # Solution There are different solutions for this classic algorithm, and this Swift implementation is based on the Chandy/Misra solution. This implementation allows agents to contend for an arbitrary number of resources in a completely distributed scenario with no need for a central authority to control the locking and serialization of resources. However, this solution violates the requirement that "the philosophers do not speak to each other" (due to the request messages). # Description For every pair of philosophers contending for a resource, create a fork and give it to the philosopher with the lower ID (n for agent Pn). Each fork can either be dirty or clean. Initially, all forks are dirty. When a philosopher wants to use a set of resources (i.e. eat), said philosopher must obtain the forks from their contending neighbors. The philospher send a message for all such forks needed. When a philosopher with a fork receives a request message, they keep the fork if it is clean, but give it up when it is dirty. If the philosopher sends the fork over, they clean the fork before doing so. After a philosopher is done eating, all their forks become dirty. If another philosopher had previously requested one of the forks, the philosopher that has just finished eating cleans the fork and sends it. This solution also allows for a large degree of concurrency, and it will solve an arbitrarily large problem. In addition, it solves the starvation problem. The clean / dirty labels give a preference to the most "starved" processes and a disadvantage to processes that have just "eaten". One could compare their solution to one where philosophers are not allowed to eat twice in a row without letting others use the forks in between. The Chandy and Misra's solution is more flexible but has an element tending in that direction. Based on the Chandy and Misra's analysis, a system of preference levels is derived from the distribution of the forks and their clean/dirty states. This system may describe an acyclic graph, and if so, the solution's protocol cannot turn that graph into a cyclic one. This guarantees that deadlock cannot occur. However, if the system is initialized to a perfectly symmetric state, such as all philosophers holding their left side forks, then the graph is cyclic at the outset, and the solution cannot prevent a deadlock. Initializing the system so that philosophers with lower IDs have dirty forks ensures the graph is initially acyclic. # Swift implementation This Swift 3.0 implementation of the Chandy/Misra solution is based on the GCD and Semaphore technique that can be built on both macOS and Linux. The code is based on a ForkPair struct used for holding an array of DispatchSemaphore and a Philosopher struct for associate a couple of forks to each Philosopher. The ForkPair DispatchSemaphore static array is used for waking the neighbour Philosophers any time a fork pair is put down on the table. A background DispatchQueue is then used to let any Philosopher run asyncrounosly on the background, and a global DispatchSemaphore is used to keep the main thread on wait forever and let the Philosophers continue forever in their alternate think and eat cycle. # See also Dining Philosophers on Wikipedia https://en.wikipedia.org/wiki/Dining_philosophers_problem Written for Swift Algorithm Club by Jacopo Mangiavacchi Swift 4.2 check by Bruno Scheele ================================================ FILE: DiningPhilosophers/Sources/main.swift ================================================ // // Swift Dining philosophers problem Algorithm // https://en.wikipedia.org/wiki/Dining_philosophers_problem // // Created by Jacopo Mangiavacchi on 11/02/16. // // // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif import Dispatch let numberOfPhilosophers = 4 struct ForkPair { static let forksSemaphore: [DispatchSemaphore] = Array(repeating: DispatchSemaphore(value: 1), count: numberOfPhilosophers) let leftFork: DispatchSemaphore let rightFork: DispatchSemaphore init(leftIndex: Int, rightIndex: Int) { //Order forks by index to prevent deadlock if leftIndex > rightIndex { leftFork = ForkPair.forksSemaphore[leftIndex] rightFork = ForkPair.forksSemaphore[rightIndex] } else { leftFork = ForkPair.forksSemaphore[rightIndex] rightFork = ForkPair.forksSemaphore[leftIndex] } } func pickUp() { //Acquire by starting with the lower index leftFork.wait() rightFork.wait() } func putDown() { //The order does not matter here leftFork.signal() rightFork.signal() } } struct Philosophers { let forkPair: ForkPair let philosopherIndex: Int var leftIndex = -1 var rightIndex = -1 init(philosopherIndex: Int) { leftIndex = philosopherIndex rightIndex = philosopherIndex - 1 if rightIndex < 0 { rightIndex += numberOfPhilosophers } self.forkPair = ForkPair(leftIndex: leftIndex, rightIndex: rightIndex) self.philosopherIndex = philosopherIndex print("Philosopher: \(philosopherIndex) left: \(leftIndex) right: \(rightIndex)") } func run() { while true { print("Acquiring lock for Philosopher: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") forkPair.pickUp() print("Start Eating Philosopher: \(philosopherIndex)") //sleep(1000) print("Releasing lock for Philosopher: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") forkPair.putDown() } } } // Layout of the table (P = philosopher, f = fork) for 4 Philosophers // P0 // f3 f0 // P3 P1 // f2 f1 // P2 let globalSem = DispatchSemaphore(value: 0) for i in 0.. Int { guard numberOfEggs != 0 && numberOfFloors != 0 else { return 0 } guard numberOfEggs != 1 && numberOfFloors != 1 else { return 1 } var eggFloor: [[Int]] = .init(repeating: .init(repeating: 0, count: numberOfFloors + 1), count: numberOfEggs + 1) var attempts = 0 for floorNumber in stride(from: 0, through: numberOfFloors, by: 1) { eggFloor[1][floorNumber] = floorNumber } eggFloor[2][1] = 1 for eggNumber in stride(from: 2, through: numberOfEggs, by: 1) { for floorNumber in stride(from: 2, through: numberOfFloors, by: 1) { eggFloor[eggNumber][floorNumber] = Int.max for visitingFloor in stride(from: 1, through: floorNumber, by: 1) { attempts = 1 + max(eggFloor[eggNumber - 1][visitingFloor - 1], eggFloor[eggNumber][floorNumber - visitingFloor]) if attempts < eggFloor[eggNumber][floorNumber] { eggFloor[eggNumber][floorNumber] = attempts } } } } return eggFloor[numberOfEggs][numberOfFloors] } ================================================ FILE: Egg Drop Problem/EggDrop.playground/contents.xcplayground ================================================ ================================================ FILE: Egg Drop Problem/EggDrop.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Egg Drop Problem/EggDrop.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Egg Drop Problem/EggDrop.playground/playground.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ ================================================ FILE: Egg Drop Problem/EggDrop.swift ================================================ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } if numberOfEggs == 1 || numberOfFloors == 1{ //edge case: When either number of eggs or number of floors is 1, answer is 1 return 1 } var eggFloor = [[Int]](repeating: [Int](repeating: 0, count: numberOfFloors+1), count: numberOfEggs+1) //egg(rows) floor(cols) array to store the solutions var attempts: Int = 0 for var floorNumber in (0..<(numberOfFloors+1)){ eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts } eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt for var eggNumber in (2..<(numberOfEggs+1)){ for var floorNumber in (2..<(numberOfFloors+1)){ eggFloor[eggNumber][floorNumber] = Int.max //setting the final result a high number to find out minimum for var visitingFloor in (1..<(floorNumber+1)){ //there are two cases //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> visitingFloor-1 //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floorNumber-visitingFloor attempts = 1 + max(eggFloor[eggNumber-1][visitingFloor-1], eggFloor[eggNumber][floorNumber-visitingFloor])//we add one taking into account the attempt we're taking at the moment if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min eggFloor[eggNumber][floorNumber] = attempts; } } } } return eggFloor[numberOfEggs][numberOfFloors] } //Helper function to find max of two integers public func max(_ x1: Int, _ x2: Int) -> Int{ return x1 > x2 ? x1 : x2 } ================================================ FILE: Egg Drop Problem/README.markdown ================================================ # Egg Drop The *egg drop* problem is an interview question popularized by Google. The premise is simple; You're given a task to evaluate the *shatter resistance* of unknown objects by dropping them at a certain height. For simplicity, you test this by going inside a multi-story building and performing tests by dropping the objects out the window and onto the ground: ![building with eggs being dropped](images/eggdrop.png) Your goal is to find out the **minimum** height that causes the object to shatter. Consider the trivial case you're given **1** object to obtain the results with. Since you've only got one sample for testing, you need to play it safe by performing drop tests starting with the bottom floor and working your way up: ![dropping from first floor](images/eggdrop2.png) If the object is incredibly resilient, and you may need to do the testing on the world's tallest building - the [Burj Khalifa](https://en.wikipedia.org/wiki/Burj_Khalifa). With **163** floors, that's a lot of climbing. Let's assume you complain, and your employer hears your plight. You are now given *several* samples to work with. How can you make use of these extra samples to expedite your testing process? The problem for this situation is popularized as the **egg drop** problem. ## Description You're in a building with **m** floors and you are given **n** eggs. What is the minimum number of attempts it will take to find out the floor that breaks the egg? For convenience, here are a few rules to keep in mind: - An egg that survives a fall can be used again. - A broken egg must be discarded. - The effect of a fall is the same for all eggs. - If an egg breaks, then it would break if dropped from a higher floor. - If an egg survives, then it would survive a shorter fall. ## Solution - eggNumber -> Number of eggs at the moment - floorNumber -> Floor number at the moment - visitingFloor -> Floor being visited at the moment - attempts -> Minimum number of attempts it will take to find out from which floor egg will break We store all the solutions in a 2D array. Where rows represents number of eggs and columns represent number of floors. First, we set base cases: 1) If there's only one egg, it takes as many attempts as number of floors 2) If there are two eggs and one floor, it takes one attempt ```swift for var floorNumber in (0..<(numberOfFloors+1)){ eggFloor[1][floorNumber] = floorNumber //base case 1: if there's only one egg, it takes 'numberOfFloors' attempts } eggFloor[2][1] = 1 //base case 2: if there are two eggs and one floor, it takes one attempt ``` When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. 1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. 2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. We find the answer based on the base cases and previously found answers as follows. ```swift attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min eggFloor[eggNumber][floorNumber] = attempts; } ``` ## Example Let's assume we have 2 eggs and 2 floors. 1) We drop one egg from the first floor. If it breaks, then we get the answer. If it doesn't we'll have 2 eggs and 1 floors to work with. attempts = 1 + maximum of 0(got the answer) and eggFloor[2][1] (base case 2 which gives us 1) attempts = 1 + 1 = 2 2) We drop one egg from the second floor. If it breaks, we'll have 1 egg and 1 floors to work with. If it doesn't, we'll get the answer. attempts = 1 + maximum of eggFloor[1][1](base case 1 which gives us 1) and 0(got the answer) attempts = 1 + 1 = 2 3) Finding the minimum of 2 and 2 gives us 2, so the answer is 2. 2 is the minimum number of attempts it will take to find out from which floor egg will break. *Written for the Swift Algorithm Club by Arkalyk Akash. Revisions and additions by Kelvin Lau* ================================================ FILE: Encode and Decode Tree/EncodeAndDecodeTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play func printTree(_ root: BinaryNode?) { guard let root = root else { return } let leftVal = root.left == nil ? "nil" : root.left!.val let rightVal = root.right == nil ? "nil" : root.right!.val print("val: \(root.val) left: \(leftVal) right: \(rightVal)") printTree(root.left) printTree(root.right) } let coder = BinaryNodeCoder() let node1 = BinaryNode("a") let node2 = BinaryNode("b") let node3 = BinaryNode("c") let node4 = BinaryNode("d") let node5 = BinaryNode("e") node1.left = node2 node1.right = node3 node3.left = node4 node3.right = node5 let encodeStr = try coder.encode(node1) print(encodeStr) // "a b # # c d # # e # #" let root: BinaryNode = coder.decode(from: encodeStr)! print("Tree:") printTree(root) /* Tree: val: a left: b right: c val: b left: nil right: nil val: c left: d right: e val: d left: nil right: nil val: e left: nil right: nil */ ================================================ FILE: Encode and Decode Tree/EncodeAndDecodeTree.playground/Sources/EncodeAndDecodeTree.swift ================================================ // // EncodeAndDecodeTree.swift // // // Created by Kai Chen on 19/07/2017. // // import Foundation protocol BinaryNodeEncoder { func encode(_ node: BinaryNode?) throws -> String } protocol BinaryNodeDecoder { func decode(from string: String) -> BinaryNode? } public class BinaryNodeCoder: BinaryNodeEncoder, BinaryNodeDecoder { // MARK: Private private let separator: Character = "," private let nilNode = "X" private func decode(from array: inout [String]) -> BinaryNode? { guard !array.isEmpty else { return nil } let value = array.removeLast() guard value != nilNode, let val = value as? T else { return nil } let node = BinaryNode(val) node.left = decode(from: &array) node.right = decode(from: &array) return node } // MARK: Public public init() {} public func encode(_ node: BinaryNode?) throws -> String { var str = "" node?.preOrderTraversal { data in if let data = data { let string = String(describing: data) str.append(string) } else { str.append(nilNode) } str.append(separator) } return str } public func decode(from string: String) -> BinaryNode? { var components = string.split(separator: separator).reversed().map(String.init) return decode(from: &components) } } public class BinaryNode { public var val: Element public var left: BinaryNode? public var right: BinaryNode? public init(_ val: Element, left: BinaryNode? = nil, right: BinaryNode? = nil) { self.val = val self.left = left self.right = right } public func preOrderTraversal(visit: (Element?) throws -> ()) rethrows { try visit(val) if let left = left { try left.preOrderTraversal(visit: visit) } else { try visit(nil) } if let right = right { try right.preOrderTraversal(visit: visit) } else { try visit(nil) } } } ================================================ FILE: Encode and Decode Tree/EncodeAndDecodeTree.playground/contents.xcplayground ================================================ ================================================ FILE: Encode and Decode Tree/EncodeAndDecodeTree.swift ================================================ // // EncodeAndDecodeTree.swift // // // Created by Kai Chen on 19/07/2017. // // import Foundation protocol BinaryNodeEncoder { func encode(_ node: BinaryNode?) throws -> String } protocol BinaryNodeDecoder { func decode(from string: String) -> BinaryNode? } public class BinaryNodeCoder: BinaryNodeEncoder, BinaryNodeDecoder { // MARK: Private private let separator: Character = "," private let nilNode = "X" private func decode(from array: inout [String]) -> BinaryNode? { guard !array.isEmpty else { return nil } let value = array.removeLast() guard value != nilNode, let val = value as? T else { return nil } let node = BinaryNode(val) node.left = decode(from: &array) node.right = decode(from: &array) return node } // MARK: Public public init() {} public func encode(_ node: BinaryNode?) throws -> String { var str = "" node?.preOrderTraversal { data in if let data = data { let string = String(describing: data) str.append(string) } else { str.append(nilNode) } str.append(separator) } return str } public func decode(from string: String) -> BinaryNode? { var components = string.split(separator: separator).reversed().map(String.init) return decode(from: &components) } } public class BinaryNode { public var val: Element public var left: BinaryNode? public var right: BinaryNode? public init(_ val: Element, left: BinaryNode? = nil, right: BinaryNode? = nil) { self.val = val self.left = left self.right = right } public func preOrderTraversal(visit: (Element?) throws -> ()) rethrows { try visit(val) if let left = left { try left.preOrderTraversal(visit: visit) } else { try visit(nil) } if let right = right { try right.preOrderTraversal(visit: visit) } else { try visit(nil) } } } ================================================ FILE: Encode and Decode Tree/readme.md ================================================ # Encode and Decode Binary Tree > **Note**: The prerequisite for this article is an understanding of how [binary trees](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Binary%20Tree) work. Trees are complex structures. Unlike linear collections such as arrays or linked lists, trees are *non-linear* and each element in a tree has positional information such as the *parent-child* relationship between nodes. When you want to send a tree structure to your backend, you need to send the data of each node, and a way to represent the parent-child relationship for each node. Your strategy in how you choose to represent this information is called your **encoding** strategy. The opposite of that - changing your encoded data back to its original form - is your **decoding** strategy. There are many ways to encode a tree and decode a tree. The important thing to keep in mind is that encoding and decoding strategies are closely related. The way you choose to encode a tree directly affects how you might decode a tree. Encoding and decoding are synonyms to *serializing* and *deserializing* trees. As a reference, the following code represents the typical `Node` type of a binary tree: ```swift class BinaryNode { var data: Element var leftChild: BinaryNode? var rightChild: BinaryNode? // ... (rest of the implementation) } ``` Your encoding and decoding methods will reside in the `BinaryNodeEncoder` and `BinaryNodeDecoder` classes: ```swift class BinaryNodeCoder { // transforms nodes into string representation func encode(_ node: BinaryNode) throws -> String where T: Encodable { } // transforms string into `BinaryNode` representation func decode(from string: String) throws -> BinaryNode where T: Decodable { } } ``` ## Encoding As mentioned before, there are different ways to do encoding. For no particular reason, you'll opt for the following rules: 1. The result of the encoding will be a `String` object. 2. You'll encode using *pre-order* traversal. Here's an example of this operation in code: ```swift fileprivate extension BinaryNode { // 1 func preOrderTraversal(visit: (Element?) throws -> ()) rethrows { try visit(data) if let leftChild = leftChild { try leftChild.preOrderTraversal(visit: visit) } else { try visit(nil) } if let rightChild = rightChild { try rightChild.preOrderTraversal(visit: visit) } else { try visit(nil) } } } class BinaryNodeCoder { // 2 private var separator: String { return "," } // 3 private var nilNode: String { return "X" } // 4 func encode(_ node: BinaryNode) -> String { var str = "" node.preOrderTraversal { data in if let data = data { let string = String(describing: data) str.append(string) } else { str.append(nilNode) } str.append(separator) } return str } // ... } ``` Here's a high level overview of the above code: 2. `separator` is a way to distinguish the nodes in a string. To illustrate its importance, consider the following encoded string "banana". How did the tree structure look like before encoding? Without the `separator`, you can't tell. 3. `nilNode` is used to identify empty children. This a necesssary piece of information to retain in order to rebuild the tree later. 4. `encode` returns a `String` representation of the `BinaryNode`. For example: "ba,nana,nil" represents a tree with two nodes - "ba" and "nana" - in pre-order format. ## Decoding Your decoding strategy is the exact opposite of your encoding strategy. You'll take an encoded string, and turn it back into your binary tree. Your encoding strategy followed the following rules: 1. The result of the encoding will be a `String` object. 2. You'll encode using *pre-order* traversal. The implementation also added a few important details: * node values are separated by `,` * `nil` children are denoted by the `nil` string These details will shape your `decode` operation. Here's a possible implementation: ```swift class BinaryNodeCoder { // ... // 1 func decode(_ string: String) -> BinaryNode? { let components = encoded.lazy.split(separator: separator).reversed().map(String.init) return decode(from: components) } // 2 private func decode(from array: inout [String]) -> BinaryNode? { guard !array.isEmpty else { return nil } let value = array.removeLast() guard value != "\(nilNode)" else { return nil } let node = AVLNode(value: value) node.leftChild = decode(from: &array) node.rightChild = decode(from: &array) return node } } ``` Here's a high level overview of the above code: 1. Takes a `String`, and uses `split` to partition the contents of `string` into an array based on the `separator` defined in the encoding step. The result is first `reversed`, and then mapped to a `String`. The `reverse` step is an optimization for the next function, allowing us to use `array.removeLast()` instead of `array.removeFirst()`. 2. Using an array as a stack, you recursively decode each node. The array keeps track of sequence of nodes and progress. Here's an example output of a tree undergoing the encoding and decoding process: ``` Original Tree ┌──8423 ┌──8391 │ └──nil ┌──7838 │ │ ┌──4936 │ └──3924 │ └──2506 830 │ ┌──701 └──202 └──169 Encoded tree: 830,202,169,X,X,701,X,X,7838,3924,2506,X,X,4936,X,X,8391,X,8423,X,X, Decoded tree ┌──8423 ┌──8391 │ └──nil ┌──7838 │ │ ┌──4936 │ └──3924 │ └──2506 830 │ ┌──701 └──202 └──169 ``` Notice the original tree and decoded tree are identical. ## Further Reading & References - [LeetCode](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/description/) *Written for the Swift Algorithm Club by Kai Chen & Kelvin Lau* ================================================ FILE: Fixed Size Array/FixedSizeArray.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play /* An unordered array with a maximum size. Performance is always O(1). */ struct FixedSizeArray { private var maxSize: Int private var defaultValue: T private var array: [T] private (set) var count = 0 init(maxSize: Int, defaultValue: T) { self.maxSize = maxSize self.defaultValue = defaultValue self.array = [T](repeating: defaultValue, count: maxSize) } subscript(index: Int) -> T { assert(index >= 0) assert(index < count) return array[index] } mutating func append(_ newElement: T) { assert(count < maxSize) array[count] = newElement count += 1 } mutating func removeAt(index: Int) -> T { assert(index >= 0) assert(index < count) count -= 1 let result = array[index] array[index] = array[count] array[count] = defaultValue return result } mutating func removeAll() { for i in 0.. ================================================ FILE: Fixed Size Array/FixedSizeArray.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Fixed Size Array/FixedSizeArray.playground/timeline.xctimeline ================================================ ================================================ FILE: Fixed Size Array/README.markdown ================================================ # Fixed-Size Arrays Early programming languages didn't have very fancy arrays. You'd create the array with a specific size and from that moment on it would never grow or shrink. Even the standard arrays in C and Objective-C are still of this type. When you define an array like so, int myArray[10]; the compiler allocates one contiguous block of memory that can hold 40 bytes (assuming an `int` is 4 bytes): ![An array with room for 10 elements](Images/array.png) That's your array. It will always be this size. If you need to fit more than 10 elements, you're out of luck... there is no room for it. To get an array that grows when it gets full you need to use a [dynamic array](https://en.wikipedia.org/wiki/Dynamic_array) object such as `NSMutableArray` in Objective-C or `std::vector` in C++, or a language like Swift whose arrays increase their capacity as needed. A major downside of the old-style arrays is that they need to be big enough or you run out of space. But if they are too big you're wasting memory. And you need to be careful about security flaws and crashes due to buffer overflows. In summary, fixed-size arrays are not flexible and they leave no room for error. That said, **I like fixed-size arrays** because they are simple, fast, and predictable. The following operations are typical for an array: - append a new element to the end - insert a new element at the beginning or somewhere in the middle - delete an element - look up an element by index - count the size of the array For a fixed-size array, appending is easy as long as the array isn't full yet: ![Appending a new element](Images/append.png) Looking up by index is also quick and easy: ![Indexing the array](Images/indexing.png) These two operations have complexity **O(1)**, meaning the time it takes to perform them is independent of the size of the array. For an array that can grow, appending is more involved: if the array is full, new memory must be allocated and the old contents copied over to the new memory buffer. On average, appending is still an **O(1)** operation, but what goes on under the hood is less predictable. The expensive operations are inserting and deleting. When you insert an element somewhere that's not at the end, it requires moving up the remainder of the array by one position. That involves a relatively costly memory copy operation. For example, inserting the value `7` in the middle of the array: ![Insert requires a memory copy](Images/insert.png) If your code was using any indexes into the array beyond the insertion point, these indexes are now referring to the wrong objects. Deleting requires a copy the other way around: ![Delete also requires a memory copy](Images/delete.png) This, by the way, is also true for `NSMutableArray` or Swift arrays. Inserting and deleting are **O(n)** operations -- the larger the array the more time it takes. Fixed-size arrays are a good solution when: 1. You know beforehand the maximum number of elements you'll need. In a game this could be the number of sprites that can be active at a time. It's not unreasonable to put a limit on this. (For games it's a good idea to allocate all the objects you need in advance anyway.) 2. It is not necessary to have a sorted version of the array, i.e. the order of the elements does not matter. If the array does not need to be sorted, then an `insertAt(index)` operation is not needed. You can simply append any new elements to the end, until the array is full. The code for adding an element becomes: ```swift func append(_ newElement: T) { if count < maxSize { array[count] = newElement count += 1 } } ``` The `count` variable keeps track of the size of the array and can be considered the index just beyond the last element. That's the index where you'll insert the new element. Determining the number of elements in the array is just a matter of reading the `count` variable, a **O(1)** operation. The code for removing an element is equally simple: ```swift func removeAt(index: Int) { count -= 1 array[index] = array[count] } ``` This copies the last element on top of the element you want to remove, and then decrements the size of the array. ![Deleting just means copying one element](Images/delete-no-copy.png) This is why the array is not sorted. To avoid an expensive copy of a potentially large portion of the array we copy just one element, but that does change the order of the elements. There are now two copies of element `6` in the array, but what was previously the last element is no longer part of the active array. It's just junk data -- the next time you append an new element, this old version of `6` will be overwritten. Under these two constraints -- a limit on the number of elements and an unsorted array -- fixed-size arrays are still perfectly suitable for use in modern software. Here is an implementation in Swift: ```swift struct FixedSizeArray { private var maxSize: Int private var defaultValue: T private var array: [T] private (set) var count = 0 init(maxSize: Int, defaultValue: T) { self.maxSize = maxSize self.defaultValue = defaultValue self.array = [T](repeating: defaultValue, count: maxSize) } subscript(index: Int) -> T { assert(index >= 0) assert(index < count) return array[index] } mutating func append(_ newElement: T) { assert(count < maxSize) array[count] = newElement count += 1 } mutating func removeAt(index: Int) -> T { assert(index >= 0) assert(index < count) count -= 1 let result = array[index] array[index] = array[count] array[count] = defaultValue return result } mutating func removeAll() { for i in 0..= 1 else { print("Number of turns must be >= 1") return } for i in 1...numberOfTurns { switch (i.isMultiple(of: 3), i.isMultiple(of: 5)) { case (false, false): print("\(i)") case (true, false): print("Fizz") case (false, true): print("Buzz") case (true, true): print("Fizz Buzz") } } } fizzBuzz(15) ================================================ FILE: Fizz Buzz/FizzBuzz.swift ================================================ // Last checked with Xcode Version 11.4.1 (11E503a) func fizzBuzz(_ numberOfTurns: Int) { guard numberOfTurns >= 1 else { print("Number of turns must be >= 1") return } for i in 1...numberOfTurns { switch (i.isMultiple(of: 3), i.isMultiple(of: 5)) { case (false, false): print("\(i)") case (true, false): print("Fizz") case (false, true): print("Buzz") case (true, true): print("Fizz Buzz") } } } ================================================ FILE: Fizz Buzz/README.markdown ================================================ # Fizz Buzz Fizz buzz is a group word game for children to teach them about division. Players take turns to count incrementally, replacing any number divisible by three with the word "fizz", and any number divisible by five with the word "buzz". Fizz buzz has been used as an interview screening device for computer programmers. ## Example A typical round of fizz buzz: `1`, `2`, `Fizz`, `4`, `Buzz`, `Fizz`, `7`, `8`, `Fizz`, `Buzz`, `11`, `Fizz`, `13`, `14`, `Fizz Buzz`, `16`, `17`, `Fizz`, `19`, `Buzz`, `Fizz`, `22`, `23`, `Fizz`, `Buzz`, `26`, `Fizz`, `28`, `29`, `Fizz Buzz`, `31`, `32`, `Fizz`, `34`, `Buzz`, `Fizz`, ... ## Modulus Operator The modulus operator `%` is the key to solving fizz buzz. The modulus operator returns the remainder after an integer division. Here is an example of the modulus operator: | Division | Division Result | Modulus | Modulus Result| | ----------- | --------------------- | ------------- | :-----------: | | 1 / 3 | 0 with a remainder of 3 | 1 % 3 | 1 | | 5 / 3 | 1 with a remainder of 2 | 5 % 3 | 2 | | 16 / 3 | 5 with a remainder of 1 | 16 % 3 | 1 | A common approach to determine if a number is even or odd is to use the modulus operator: | Modulus | Result | Swift Code | Swift Code
Result | Comment | | -------- | :-----:| -------------------------------- | :----------------:| --------------------------------------------- | | 6 % 2 | 0 | `let isEven = (number % 2 == 0)` | `true` | If a number is divisible by 2 it is *even* | | 5 % 2 | 1 | `let isOdd = (number % 2 != 0)` | `true` | If a number is not divisible by 2 it is *odd* | Alternatively, Swift's built in function .isMultiple(of:) can be used, i.e. 6.isMultiple(of: 2) will return true, 5.isMultiple(of: 2) will return false ## Solving fizz buzz Now we can use the modulus operator `%` or .isMultiple(of:) method to solve fizz buzz. Finding numbers divisible by three: | Modulus | Modulus
Result | Swift Code
using Modulo | Swift Code
using .isMultiple(of:) | Swift Code
Result | | ------- | :---------------: | -------------------------- | ------------------------------------ | ------------------- | |1 % 3 | 1 | `1 % 3 == 0` | `1.isMultiple(of: 3)` | `false` | |2 % 3 | 2 | `2 % 3 == 0` | `2.isMultiple(of: 3)` | `false` | |3 % 3 | 0 | `3 % 3 == 0` | `3.isMultiple(of: 3)` | `true` | |4 % 3 | 1 | `4 % 3 == 0` | `4.isMultiple(of: 3)` | `false` | Finding numbers divisible by five: | Modulus | Modulus
Result | Swift Code
using Modulo | Swift Code
using .isMultiple(of:) | Swift Code
Result | | ------- | :---------------: | -------------------------- | ------------------------------------ | -------------------- | | 1 % 5 | 1 | `1 % 5 == 0` | `1.isMultiple(of: 5)` | `false` | | 2 % 5 | 2 | `2 % 5 == 0` | `2.isMultiple(of: 5)` | `false` | | 3 % 5 | 3 | `3 % 5 == 0` | `3.isMultiple(of: 5)` | `false` | | 4 % 5 | 4 | `4 % 5 == 0` | `4.isMultiple(of: 5)` | `false` | | 5 % 5 | 0 | `5 % 5 == 0` | `5.isMultiple(of: 5)` | `true` | | 6 % 5 | 1 | `6 % 5 == 0` | `6.isMultiple(of: 5)` | `false` | ## The code Here is a simple implementation in Swift using Modulus approach ```swift func fizzBuzz(_ numberOfTurns: Int) { for i in 1...numberOfTurns { var result = "" if i % 3 == 0 { result += "Fizz" } if i % 5 == 0 { result += (result.isEmpty ? "" : " ") + "Buzz" } if result.isEmpty { result += "\(i)" } print(result) } } ``` Here is simple implementation in Swift using .isMultiple(of:) and switch statement ```swift func fizzBuzz(_ numberOfTurns: Int) { guard numberOfTurns >= 1 else { print("Number of turns must be >= 1") return } for i in 1...numberOfTurns { switch (i.isMultiple(of: 3), i.isMultiple(of: 5)) { case (false, false): print("\(i)") case (true, false): print("Fizz") case (false, true): print("Buzz") case (true, true): print("Fizz Buzz") } } } ``` Put either code in a playground and test it like so: ```swift fizzBuzz(15) ``` This will output: 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 Fizz Buzz ## See also [Fizz buzz on Wikipedia](https://en.wikipedia.org/wiki/Fizz_buzz) *Originally written by [Chris Pilcher](https://github.com/chris-pilcher)*
*Updated by [Lance Rettberg](https://github.com/l-rettberg)* ================================================ FILE: GCD/GCD.playground/Contents.swift ================================================ gcd(52, 39) // 13 gcd(228, 36) // 12 gcd(51357, 3819) // 57 gcd(841, 299) // 1 gcd(52, 39, using: gcdRecursiveEuklid) // 13 gcd(228, 36, using: gcdRecursiveEuklid) // 12 gcd(51357, 3819, using: gcdRecursiveEuklid) // 57 gcd(841, 299, using: gcdRecursiveEuklid) // 1 gcd(52, 39, using: gcdBinaryRecursiveStein) // 13 gcd(228, 36, using: gcdBinaryRecursiveStein) // 12 gcd(51357, 3819, using: gcdBinaryRecursiveStein) // 57 gcd(841, 299, using: gcdBinaryRecursiveStein) // 1 do { try lcm(2, 3) // 6 try lcm(10, 8, using: gcdRecursiveEuklid) // 40 } catch { dump(error) } ================================================ FILE: GCD/GCD.playground/Sources/GCD.swift ================================================ /* Finds the largest positive integer that divides both m and n without a remainder. - Parameter m: First natural number - Parameter n: Second natural number - Parameter using: The used algorithm to calculate the gcd. If nothing provided, the Iterative Euclidean algorithm is used. - Returns: The natural gcd of m and n. */ public func gcd(_ m: Int, _ n: Int, using gcdAlgorithm: (Int, Int) -> (Int) = gcdIterativeEuklid) -> Int { return gcdAlgorithm(m, n) } /* Iterative approach based on the Euclidean algorithm. The Euclidean algorithm is based on the principle that the greatest common divisor of two numbers does not change if the larger number is replaced by its difference with the smaller number. - Parameter m: First natural number - Parameter n: Second natural number - Returns: The natural gcd of m and n. */ public func gcdIterativeEuklid(_ m: Int, _ n: Int) -> Int { var a: Int = 0 var b: Int = max(m, n) var r: Int = min(m, n) while r != 0 { a = b b = r r = a % b } return b } /* Recursive approach based on the Euclidean algorithm. - Parameter m: First natural number - Parameter n: Second natural number - Returns: The natural gcd of m and n. - Note: The recursive version makes only tail recursive calls. Most compilers for imperative languages do not optimize these. The swift compiler as well as the obj-c compiler is able to do optimizations for tail recursive calls, even though it still ends up to be the same in terms of complexity. That said, tail call elimination is not mutually exclusive to recursion. */ public func gcdRecursiveEuklid(_ m: Int, _ n: Int) -> Int { let r: Int = m % n if r != 0 { return gcdRecursiveEuklid(n, r) } else { return n } } /* The binary GCD algorithm, also known as Stein's algorithm, is an algorithm that computes the greatest common divisor of two nonnegative integers. Stein's algorithm uses simpler arithmetic operations than the conventional Euclidean algorithm; it replaces division with arithmetic shifts, comparisons, and subtraction. - Parameter m: First natural number - Parameter n: Second natural number - Returns: The natural gcd of m and n - Complexity: worst case O(n^2), where n is the number of bits in the larger of the two numbers. Although each step reduces at least one of the operands by at least a factor of 2, the subtract and shift operations take linear time for very large integers */ public func gcdBinaryRecursiveStein(_ m: Int, _ n: Int) -> Int { if let easySolution = findEasySolution(m, n) { return easySolution } if (m & 1) == 0 { // m is even if (n & 1) == 1 { // and n is odd return gcdBinaryRecursiveStein(m >> 1, n) } else { // both m and n are even return gcdBinaryRecursiveStein(m >> 1, n >> 1) << 1 } } else if (n & 1) == 0 { // m is odd, n is even return gcdBinaryRecursiveStein(m, n >> 1) } else if (m > n) { // reduce larger argument return gcdBinaryRecursiveStein((m - n) >> 1, n) } else { // reduce larger argument return gcdBinaryRecursiveStein((n - m) >> 1, m) } } /* Finds an easy solution for the gcd. - Parameter m: First natural number - Parameter n: Second natural number - Returns: A natural gcd of m and n if possible. - Note: It might be relevant for different usecases to try finding an easy solution for the GCD calculation before even starting more difficult operations. */ func findEasySolution(_ m: Int, _ n: Int) -> Int? { if m == n { return m } if m == 0 { return n } if n == 0 { return m } return nil } public enum LCMError: Error { case divisionByZero } /* Calculates the lcm for two given numbers using a specified gcd algorithm. - Parameter m: First natural number. - Parameter n: Second natural number. - Parameter using: The used gcd algorithm to calculate the lcm. If nothing provided, the Iterative Euclidean algorithm is used. - Throws: Can throw a `divisionByZero` error if one of the given attributes turns out to be zero or less. - Returns: The least common multiplier of the two attributes as an unsigned integer */ public func lcm(_ m: Int, _ n: Int, using gcdAlgorithm: (Int, Int) -> (Int) = gcdIterativeEuklid) throws -> Int { guard m & n != 0 else { throw LCMError.divisionByZero } return m / gcdAlgorithm(m, n) * n } ================================================ FILE: GCD/GCD.playground/contents.xcplayground ================================================ ================================================ FILE: GCD/GCD.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: GCD/GCD.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: GCD/README.markdown ================================================ # Greatest Common Divisor The *greatest common divisor* (or Greatest Common Factor) of two numbers `a` and `b` is the largest positive integer that divides both `a` and `b` without a remainder. The GCD.swift file contains three different algorithms of how to calculate the greatest common divisor. For example, `gcd(39, 52) = 13` because 13 divides 39 (`39 / 13 = 3`) as well as 52 (`52 / 13 = 4`). But there is no larger number than 13 that divides them both. You've probably had to learn about this in school at some point. :-) You probably won't need to use the GCD or LCM in any real-world problems, but it's cool to play around with this ancient algorithm. It was first described by Euklid in his [Elements](http://publicdomainreview.org/collections/the-first-six-books-of-the-elements-of-euclid-1847/) around 300 BC. Rumor has it that he discovered this algorithm while he was hacking on his Commodore 64. ## Different Algorithms This example includes three different algorithms to find the same result. ### Iterative Euklidean The laborious way to find the GCD of two numbers is to first figure out the factors of both numbers, then take the greatest number they have in common. The problem is that factoring numbers is quite difficult, especially when they get larger. (On the plus side, that difficulty is also what keeps your online payments secure.) There is a smarter way to calculate the GCD: Euklid's algorithm. The big idea here is that, gcd(a, b) = gcd(b, a % b) where `a % b` calculates the remainder of `a` divided by `b`. Here is an implementation of this idea in Swift: ```swift func gcdIterativeEuklid(_ m: Int, _ n: Int) -> Int { var a: Int = 0 var b: Int = max(m, n) var r: Int = min(m, n) while r != 0 { a = b b = r r = a % b } return b } ``` Put it in a playground and try it out with these examples: ```swift gcd(52, 39, using: gcdIterativeEuklid) // 13 gcd(228, 36, using: gcdIterativeEuklid) // 12 gcd(51357, 3819, using: gcdIterativeEuklid) // 57 ``` ### Recursive Euklidean Here is a slightly different implementation of Euklid's algorithm. Unlike the first version this doesn't use a `while` loop, but leverages recursion. ```swift func gcdRecursiveEuklid(_ m: Int, _ n: Int) -> Int { let r: Int = m % n if r != 0 { return gcdRecursiveEuklid(n, r) } else { return n } } ``` Put it in a playground and compare it with the results of the iterative Eulidean gcd. They should return the same results: ```swift gcd(52, 39, using: gcdRecursiveEuklid) // 13 gcd(228, 36, using: gcdRecursiveEuklid) // 12 gcd(51357, 3819, using: gcdRecursiveEuklid) // 57 ``` The `max()` and `min()` at the top of the function make sure we always divide the larger number by the smaller one. Let's step through the third example using the *recursive Euklidean algorithm* here: gcd(51357, 3819) According to Euklid's rule, this is equivalent to, gcd(3819, 51357 % 3819) = gcd(3819, 1710) because the remainder of `51357 % 3819` is `1710`. If you work out this division you get `51357 = (13 * 3819) + 1710` but we only care about the remainder part. So `gcd(51357, 3819)` is the same as `gcd(3819, 1710)`. That's useful because we can keep simplifying: gcd(3819, 1710) = gcd(1710, 3819 % 1710) = gcd(1710, 399) = gcd(399, 1710 % 399) = gcd(399, 114) = gcd(114, 399 % 114) = gcd(114, 57) = gcd(57, 114 % 57) = gcd(57, 0) And now can't divide any further. The remainder of `114 / 57` is zero because `114 = 57 * 2` exactly. That means we've found the answer: gcd(3819, 51357) = gcd(57, 0) = 57 So in each step of Euklid's algorithm the numbers become smaller and at some point it ends when one of them becomes zero. By the way, it's also possible that two numbers have a GCD of 1. They are said to be *relatively prime*. This happens when there is no number that divides them both, for example: ```swift gcd(841, 299) // 1 ``` ### Binary Recursive Stein The binary GCD algorithm, also known as Stein's algorithm, is an algorithm that computes the greatest common divisor of two nonnegative integers. Stein's algorithm is very similar to the recursive Eulidean algorithm, but uses arithmetical operations, which are simpler for computers to perform, than the conventional Euclidean algorithm does. It replaces division with arithmetic shifts, comparisons, and subtraction. ```swift func gcdBinaryRecursiveStein(_ m: Int, _ n: Int) -> Int { if let easySolution = findEasySolution(m, n) { return easySolution } if (m & 1) == 0 { // m is even if (n & 1) == 1 { // and n is odd return gcdBinaryRecursiveStein(m >> 1, n) } else { // both m and n are even return gcdBinaryRecursiveStein(m >> 1, n >> 1) << 1 } } else if (n & 1) == 0 { // m is odd, n is even return gcdBinaryRecursiveStein(m, n >> 1) } else if (m > n) { // reduce larger argument return gcdBinaryRecursiveStein((m - n) >> 1, n) } else { // reduce larger argument return gcdBinaryRecursiveStein((n - m) >> 1, m) } } ``` Depending on your application and your input expectations, it might be reasonable to also search for an "easy solution" using the other gcd implementations: ```swift func findEasySolution(_ m: Int, _ n: Int) -> Int? { if m == n { return m } if m == 0 { return n } if n == 0 { return m } return nil } ``` Put it in a playground and compare it with the results of the other gcd implementations: ```swift gcd(52, 39, using: gcdBinaryRecursiveStein) // 13 gcd(228, 36, using: gcdBinaryRecursiveStein) // 12 gcd(51357, 3819, using: gcdBinaryRecursiveStein) // 57 ``` ### Least Common Multiple Another algorithm related to the GCD is the *least common multiple* or LCM. The least common multiple of two numbers `a` and `b` is the smallest positive integer that is a multiple of both. In other words, the LCM is evenly divisible by `a` and `b`. The example implementation of the LCM takes two numbers and an optional specification which GCD algorithm is used. For example: `lcm(2, 3, using: gcdRecursiveEuklid) = 6` , which tells us that 6 is the smallest number that can be devided by 2 as well as 3. We can calculate the LCM using Euklid's algorithm too: a * b lcm(a, b) = --------- gcd(a, b) In code: ```swift func lcm(_ m: Int, _ n: Int, using gcdAlgorithm: (Int, Int) -> (Int) = gcdIterativeEuklid) throws -> Int { guard (m & n) != 0 else { throw LCMError.divisionByZero } return m / gcdAlgorithm(m, n) * n } ``` And to try it out in a playground: ```swift lcm(10, 8) // 40 ``` ## Discussion While these algorithms all calculate the same result, comparing their plane complexity might not be enough to decide for one of them, though. The original iterative Euklidean algorithm is easier to understand. The recursive Euklidean and Stein's algorithm, while being generally faster, their runtime is heavily dependend on the environment they are running on. _If a fast calculation of the gcd is necessary, a runtime comparison for the specific platform and compiler optimization level should be done for the rekursive Euklidean and Stein's algorithm._ *Written for Swift Algorithm Club by Matthijs Hollemans* *Extended by Simon C. Krüger* ================================================ FILE: Genetic/README.markdown ================================================ # Genetic Algorthim ## What is it? A genetic algorithm (GA) is process inspired by natural selection to find high quality solutions. Most commonly used for optimization. GAs rely on the bio-inspired processes of natural selection, more specifically the process of selection (fitness), crossover and mutation. To understand more, let's walk through these processes in terms of biology: ### Selection >**Selection**, in biology, the preferential survival and reproduction or preferential elimination of individuals with certain genotypes (genetic compositions), by means of natural or artificial controlling factors. In other words, survival of the fittest. Organisms that survive in their environment tend to reproduce more. With GAs we generate a fitness model that will rank individuals and give them a better chance for reproduction. ### Crossover >**Chromosomal crossover** (or crossing over) is the exchange of genetic material between homologous chromosomes that results in recombinant chromosomes during sexual reproduction [Wikipedia](https://en.wikipedia.org/wiki/Chromosomal_crossover) Simply reproduction. A generation will be a mixed representation of the previous generation, with offspring taking DNA from both parents. GAs do this by randomly, but weightily, mating offspring to create new generations. ### Mutation >**Mutation**, an alteration in the genetic material (the genome) of a cell of a living organism or of a virus that is more or less permanent and that can be transmitted to the cell’s or the virus’s descendants. [Britannica](https://www.britannica.com/science/mutation-genetics) The randomization that allows for organisms to change over time. In GAs we build a randomization process that will mutate offspring in a population in order to introduce fitness variance. ### Resources: * [Genetic Algorithms in Search Optimization, and Machine Learning](https://www.amazon.com/Genetic-Algorithms-Optimization-Machine-Learning/dp/0201157675/ref=sr_1_sc_1?ie=UTF8&qid=1520628364&sr=8-1-spell&keywords=Genetic+Algortithms+in+search) * [Wikipedia](https://en.wikipedia.org/wiki/Genetic_algorithm) * [My Original Gist](https://gist.github.com/blainerothrock/efda6e12fe10792c99c990f8ff3daeba) ## The Code ### Problem For this quick and dirty example, we are going to produce an optimized string using a simple genetic algorithm. More specifically we are trying to take a randomly generated origin string of a fixed length and evolve it into the most optimized string of our choosing. We will be creating a bio-inspired world where the absolute existence is the string `Hello, World!`. Nothing in this universe is better and it's our goal to get as close to it as possible to ensure survival. ### Define the Universe Before we dive into the core processes we need to set up our "universe". First let's define a lexicon, a set of everything that exists in our universe. ```swift let lex: [UInt8] = " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".asciiArray ``` To make things easier, we are actually going to work in [Unicode values](https://en.wikipedia.org/wiki/List_of_Unicode_characters), so let's define a String extension to help with that. ```swift extension String { var unicodeArray: [UInt8] { return [UInt8](self.utf8) } } ``` Now, let's define a few global variables for the universe: * `OPTIMAL`: This is the end goal and what we will be using to rate fitness. In the real world this will not exist * `DNA_SIZE`: The length of the string in our population. Organisms need to be similar * `POP_SIZE`: Size of each generation * `MAX_GENERATIONS`: Max number of generations, script will stop when it reach 5000 if the optimal value is not found * `MUTATION_CHANCE`: The chance in which a random nucleotide can mutate (`1/MUTATION_CHANCE`) ```swift let OPTIMAL:[UInt8] = "Hello, World".unicodeArray let DNA_SIZE = OPTIMAL.count let POP_SIZE = 50 let GENERATIONS = 5000 let MUTATION_CHANCE = 100 ``` ### Population Zero Before selecting, crossover and mutation, we need a population to start with. Now that we have the universe defined we can write that function: ```swift func randomPopulation(from lexicon: [UInt8], populationSize: Int, dnaSize: Int) -> [[UInt8]] { guard lexicon.count > 1 else { return [] } var pop = [[UInt8]]() (0.. Int { guard dna.count == optimal.count else { return -1 } var fitness = 0 for index in dna.indices { fitness += abs(Int(dna[index]) - Int(optimal[index])) } return fitness } ``` The above will produce a fitness value to an individual. The perfect solution, "Hello, World" will have a fitness of 0. "Gello, World" will have a fitness of 1 since it is one unicode value off from the optimal (`H->G`). This example is very simple, but it'll work for our example. In a real world problem, the optimal solution is unknown or impossible. [Here](https://iccl.inf.tu-dresden.de/w/images/b/b7/GA_for_TSP.pdf) is a paper about optimizing a solution for the famous [traveling salesman problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) using a GA. In this example the problem is unsolvable by modern computers, but you can rate a individual solution by distance traveled. The optimal fitness here is an impossible 0. The closer the solution is to 0, the better chance for survival. In our example we will reach our goal, a fitness of 0. The second part to selection is weighted choice, also called roulette wheel selection. This defines how individuals are selected for the reproduction process out of the current population. Just because you are the best choice for natural selection doesn't mean the environment will select you. The individual could fall off a cliff, get dysentery or be unable to reproduce. Let's take a second and ask why on this one. Why would you not always want to select the most fit from a population? It's hard to see from this simple example, but let's think about dog breeding, because breeders remove this process and hand select dogs for the next generation. As a result you get improved desired characteristics, but the individuals will also continue to carry genetic disorders that come along with those traits. A certain "branch" of evolution may beat out the current fittest solution at a later time. This may be ok depending on the problem, but to keep this educational we will go with the bio-inspired way. With all that, here is our weight choice function: func weightedChoice(items: [(dna: [UInt8], weight: Double)]) -> (dna: [UInt8], weight: Double) { let total = items.reduce(0) { $0 + $1.weight } var n = Double.random(in: 0..<(total * 1000000)) / 1000000.0 for item in items { if n < item.weight { return item } n = n - item.weight } return items[1] } The above function takes a list of individuals with their calculated fitness. Then selects one at random offset by their fitness value. The horrible 1,000,000 multiplication and division is to insure precision by calculating decimals. `Double.random` only uses integers so this is required to convert to a precise Double, it's not perfect, but enough for our example. ## Mutation The all powerful mutation, the thing that introduces otherwise non existent fitness variance. It can either hurt of improve a individuals fitness but over time it will cause evolution towards more fit populations. Imagine if our initial random population was missing the charachter `H`, in that case we need to rely on mutation to introduce that character into the population in order to achieve the optimal solution. ```swift func mutate(lexicon: [UInt8], dna: [UInt8], mutationChance: Int) -> [UInt8] { var outputDna = dna (0.. [UInt8] { let pos = Int.random(in: 0..?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".unicodeArray // This is the end goal and what we will be using to rate fitness. In the real world this will not exist let OPTIMAL:[UInt8] = "Hello, World".unicodeArray // The length of the string in our population. Organisms need to be similar let DNA_SIZE = OPTIMAL.count // Size of each generation let POP_SIZE = 50 // Max number of generations, script will stop when it reaches 5000 if the optimal value is not found let GENERATIONS = 5000 // The chance in which a random nucleotide can mutate (1/n) let MUTATION_CHANCE = 100 func randomPopulation(from lexicon: [UInt8], populationSize: Int, dnaSize: Int) -> [[UInt8]] { var pop = [[UInt8]]() (0.. Int { var fitness = 0 for index in dna.indices { fitness += abs(Int(dna[index]) - Int(optimal[index])) } return fitness } func weightedChoice(items: [(dna: [UInt8], weight: Double)]) -> (dna: [UInt8], weight: Double) { let total = items.reduce(0) { $0 + $1.weight } var n = Double.random(in: 0..<(total * 1000000)) / 1000000.0 for item in items { if n < item.weight { return item } n = n - item.weight } return items[1] } func mutate(lexicon: [UInt8], dna: [UInt8], mutationChance: Int) -> [UInt8] { var outputDna = dna (0.. [UInt8] { let pos = Int.random(in: 0.. ================================================ FILE: Genetic/gen.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Genetic/gen.swift ================================================ //: Playground - noun: a place where people can play import Foundation extension String { var unicodeArray: [UInt8] { return [UInt8](self.utf8) } } let lex: [UInt8] = " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~".unicodeArray // This is the end goal and what we will be using to rate fitness. In the real world this will not exist let OPTIMAL:[UInt8] = "Hello, World".unicodeArray // The length of the string in our population. Organisms need to be similar let DNA_SIZE = OPTIMAL.count // size of each generation let POP_SIZE = 50 // max number of generations, script will stop when it reach 5000 if the optimal value is not found let MAX_GENERATIONS = 5000 // The chance in which a random nucleotide can mutate (1/n) let MUTATION_CHANCE = 100 func randomChar(from lexicon: [UInt8]) -> UInt8 { let len = UInt32(lexicon.count-1) let rand = Int(arc4random_uniform(len)) return lexicon[rand] } func randomPopulation(from lexicon: [UInt8], populationSize: Int, dnaSize: Int) -> [[UInt8]] { var pop = [[UInt8]]() (0.. Int { var fitness = 0 (0...dna.count-1).forEach { c in fitness += abs(Int(dna[c]) - Int(optimal[c])) } return fitness } func weightedChoice(items:[(dna:[UInt8], weight:Double)]) -> (dna:[UInt8], weight:Double) { let total = items.reduce(0.0) { return $0 + $1.weight} var n = Double(arc4random_uniform(UInt32(total * 1000000.0))) / 1000000.0 for item in items { if n < item.weight { return item } n = n - item.weight } return items[1] } func mutate(lexicon: [UInt8], dna:[UInt8], mutationChance:Int) -> [UInt8] { var outputDna = dna (0.. [UInt8] { let pos = Int(arc4random_uniform(UInt32(dnaSize-1))) let dna1Index1 = dna1.index(dna1.startIndex, offsetBy: pos) let dna2Index1 = dna2.index(dna2.startIndex, offsetBy: pos) return [UInt8](dna1.prefix(upTo: dna1Index1) + dna2.suffix(from: dna2Index1)) } func main() { // generate the starting random population var population:[[UInt8]] = randomPopulation(from: lex, populationSize: POP_SIZE, dnaSize: DNA_SIZE) // print("population: \(population), dnaSize: \(DNA_SIZE) ") var fittest = [UInt8]() for generation in 0...MAX_GENERATIONS { var weightedPopulation = [(dna:[UInt8], weight:Double)]() // calulcated the fitness of each individual in the population // and add it to the weight population (weighted = 1.0/fitness) for individual in population { let fitnessValue = calculateFitness(dna: individual, optimal: OPTIMAL) let pair = ( individual, fitnessValue == 0 ? 1.0 : Double(100/POP_SIZE)/Double( fitnessValue ) ) weightedPopulation.append(pair) } population = [] // create a new generation using the individuals in the origional population (0...POP_SIZE).forEach { _ in let ind1 = weightedChoice(items: weightedPopulation) let ind2 = weightedChoice(items: weightedPopulation) let offspring = crossover(dna1: ind1.dna, dna2: ind2.dna, dnaSize: DNA_SIZE) // append to the population and mutate population.append(mutate(lexicon: lex, dna: offspring, mutationChance: MUTATION_CHANCE)) } fittest = population[0] var minFitness = calculateFitness(dna: fittest, optimal: OPTIMAL) // parse the population for the fittest string population.forEach { indv in let indvFitness = calculateFitness(dna: indv, optimal: OPTIMAL) if indvFitness < minFitness { fittest = indv minFitness = indvFitness } } if minFitness == 0 { break; } print("\(generation): \(String(bytes: fittest, encoding: .utf8)!)") } print("fittest string: \(String(bytes: fittest, encoding: .utf8)!)") } main() ================================================ FILE: Graph/Graph/AdjacencyListGraph.swift ================================================ // // AdjacencyListGraph.swift // Graph // // Created by Andrew McKnight on 5/13/16. // import Foundation private class EdgeList where T: Hashable { var vertex: Vertex var edges: [Edge]? init(vertex: Vertex) { self.vertex = vertex } func addEdge(_ edge: Edge) { edges?.append(edge) } } open class AdjacencyListGraph: AbstractGraph where T: Hashable { fileprivate var adjacencyList: [EdgeList] = [] public required init() { super.init() } public required init(fromGraph graph: AbstractGraph) { super.init(fromGraph: graph) } open override var vertices: [Vertex] { var vertices = [Vertex]() for edgeList in adjacencyList { vertices.append(edgeList.vertex) } return vertices } open override var edges: [Edge] { var allEdges = Set>() for edgeList in adjacencyList { guard let edges = edgeList.edges else { continue } for edge in edges { allEdges.insert(edge) } } return Array(allEdges) } open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists let matchingVertices = vertices.filter { vertex in return vertex.data == data } if matchingVertices.count > 0 { return matchingVertices.last! } // if the vertex doesn't exist, create a new one let vertex = Vertex(data: data, index: adjacencyList.count) adjacencyList.append(EdgeList(vertex: vertex)) return vertex } open override func addDirectedEdge(_ from: Vertex, to: Vertex, withWeight weight: Double?) { // works let edge = Edge(from: from, to: to, weight: weight) let edgeList = adjacencyList[from.index] if edgeList.edges != nil { edgeList.addEdge(edge) } else { edgeList.edges = [edge] } } open override func addUndirectedEdge(_ vertices: (Vertex, Vertex), withWeight weight: Double?) { addDirectedEdge(vertices.0, to: vertices.1, withWeight: weight) addDirectedEdge(vertices.1, to: vertices.0, withWeight: weight) } open override func weightFrom(_ sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { guard let edges = adjacencyList[sourceVertex.index].edges else { return nil } for edge: Edge in edges { if edge.to == destinationVertex { return edge.weight } } return nil } open override func edgesFrom(_ sourceVertex: Vertex) -> [Edge] { return adjacencyList[sourceVertex.index].edges ?? [] } open override var description: String { var rows = [String]() for edgeList in adjacencyList { guard let edges = edgeList.edges else { continue } var row = [String]() for edge in edges { var value = "\(edge.to.data)" if edge.weight != nil { value = "(\(value): \(edge.weight!))" } row.append(value) } rows.append("\(edgeList.vertex.data) -> [\(row.joined(separator: ", "))]") } return rows.joined(separator: "\n") } } ================================================ FILE: Graph/Graph/AdjacencyMatrixGraph.swift ================================================ // // AdjacencyMatrixGraph.swift // Graph // // Created by Andrew McKnight on 5/13/16. // import Foundation open class AdjacencyMatrixGraph: AbstractGraph where T: Hashable { // If adjacencyMatrix[i][j] is not nil, then there is an edge from // vertex i to vertex j. fileprivate var adjacencyMatrix: [[Double?]] = [] fileprivate var _vertices: [Vertex] = [] public required init() { super.init() } public required init(fromGraph graph: AbstractGraph) { super.init(fromGraph: graph) } open override var vertices: [Vertex] { return _vertices } open override var edges: [Edge] { var edges = [Edge]() for row in 0 ..< adjacencyMatrix.count { for column in 0 ..< adjacencyMatrix.count { if let weight = adjacencyMatrix[row][column] { edges.append(Edge(from: vertices[row], to: vertices[column], weight: weight)) } } } return edges } // Adds a new vertex to the matrix. // Performance: possibly O(n^2) because of the resizing of the matrix. open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists let matchingVertices = vertices.filter { vertex in return vertex.data == data } if matchingVertices.count > 0 { return matchingVertices.last! } // if the vertex doesn't exist, create a new one let vertex = Vertex(data: data, index: adjacencyMatrix.count) // Expand each existing row to the right one column. for i in 0 ..< adjacencyMatrix.count { adjacencyMatrix[i].append(nil) } // Add one new row at the bottom. let newRow = [Double?](repeating: nil, count: adjacencyMatrix.count + 1) adjacencyMatrix.append(newRow) _vertices.append(vertex) return vertex } open override func addDirectedEdge(_ from: Vertex, to: Vertex, withWeight weight: Double?) { adjacencyMatrix[from.index][to.index] = weight } open override func addUndirectedEdge(_ vertices: (Vertex, Vertex), withWeight weight: Double?) { addDirectedEdge(vertices.0, to: vertices.1, withWeight: weight) addDirectedEdge(vertices.1, to: vertices.0, withWeight: weight) } open override func weightFrom(_ sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { return adjacencyMatrix[sourceVertex.index][destinationVertex.index] } open override func edgesFrom(_ sourceVertex: Vertex) -> [Edge] { var outEdges = [Edge]() let fromIndex = sourceVertex.index for column in 0..: Equatable where T: Hashable { public let from: Vertex public let to: Vertex public let weight: Double? } extension Edge: CustomStringConvertible { public var description: String { guard let unwrappedWeight = weight else { return "\(from.description) -> \(to.description)" } return "\(from.description) -(\(unwrappedWeight))-> \(to.description)" } } extension Edge: Hashable { public func hash(into hasher: inout Hasher) { hasher.combine(from) hasher.combine(to) if weight != nil { hasher.combine(weight) } } } public func == (lhs: Edge, rhs: Edge) -> Bool { guard lhs.from == rhs.from else { return false } guard lhs.to == rhs.to else { return false } guard lhs.weight == rhs.weight else { return false } return true } ================================================ FILE: Graph/Graph/Graph.h ================================================ // // Graph.h // Graph // // Created by Andrew McKnight on 5/8/16. // #import //! Project version number for Graph. FOUNDATION_EXPORT double GraphVersionNumber; //! Project version string for Graph. FOUNDATION_EXPORT const unsigned char GraphVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import ================================================ FILE: Graph/Graph/Graph.swift ================================================ // // Graph.swift // Graph // // Created by Andrew McKnight on 5/8/16. // import Foundation open class AbstractGraph: CustomStringConvertible where T: Hashable { public required init() {} public required init(fromGraph graph: AbstractGraph) { for edge in graph.edges { let from = createVertex(edge.from.data) let to = createVertex(edge.to.data) addDirectedEdge(from, to: to, withWeight: edge.weight) } } open var description: String { fatalError("abstract property accessed") } open var vertices: [Vertex] { fatalError("abstract property accessed") } open var edges: [Edge] { fatalError("abstract property accessed") } // Adds a new vertex to the matrix. // Performance: possibly O(n^2) because of the resizing of the matrix. open func createVertex(_ data: T) -> Vertex { fatalError("abstract function called") } open func addDirectedEdge(_ from: Vertex, to: Vertex, withWeight weight: Double?) { fatalError("abstract function called") } open func addUndirectedEdge(_ vertices: (Vertex, Vertex), withWeight weight: Double?) { fatalError("abstract function called") } open func weightFrom(_ sourceVertex: Vertex, to destinationVertex: Vertex) -> Double? { fatalError("abstract function called") } open func edgesFrom(_ sourceVertex: Vertex) -> [Edge] { fatalError("abstract function called") } } ================================================ FILE: Graph/Graph/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass ================================================ FILE: Graph/Graph/Vertex.swift ================================================ // // Vertex.swift // Graph // // Created by Andrew McKnight on 5/8/16. // import Foundation public struct Vertex: Equatable where T: Hashable { public var data: T public let index: Int } extension Vertex: CustomStringConvertible { public var description: String { return "\(index): \(data)" } } extension Vertex: Hashable { public func hasher(into hasher: inout Hasher) { hasher.combine(data) hasher.combine(index) } } public func ==(lhs: Vertex, rhs: Vertex) -> Bool { guard lhs.index == rhs.index else { return false } guard lhs.data == rhs.data else { return false } return true } ================================================ FILE: Graph/Graph.playground/Contents.swift ================================================ import Graph for graph in [AdjacencyMatrixGraph(), AdjacencyListGraph()] { let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) let v4 = graph.createVertex(4) let v5 = graph.createVertex(5) // Set up a cycle like so: // v5 // ^ // | (3.2) // | // v1 ---(1)---> v2 ---(1)---> v3 ---(4.5)---> v4 // ^ | // | V // ---------<-----------<---------(2.8)----<----| graph.addDirectedEdge(v1, to: v2, withWeight: 1.0) graph.addDirectedEdge(v2, to: v3, withWeight: 1.0) graph.addDirectedEdge(v3, to: v4, withWeight: 4.5) graph.addDirectedEdge(v4, to: v1, withWeight: 2.8) graph.addDirectedEdge(v2, to: v5, withWeight: 3.2) // Returns the weight of the edge from v1 to v2 (1.0) graph.weightFrom(v1, to: v2) // Returns the weight of the edge from v1 to v3 (nil, since there is not an edge) graph.weightFrom(v1, to: v3) // Returns the weight of the edge from v3 to v4 (4.5) graph.weightFrom(v3, to: v4) // Returns the weight of the edge from v4 to v1 (2.8) graph.weightFrom(v4, to: v1) print(graph) print() // separate by a newline } ================================================ FILE: Graph/Graph.playground/contents.xcplayground ================================================ ================================================ FILE: Graph/Graph.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Graph/Graph.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Graph/Graph.playground/timeline.xctimeline ================================================ ================================================ FILE: Graph/Graph.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 491AA3761CE6B81C00A2E2C5 /* AdjacencyListGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491AA3751CE6B81C00A2E2C5 /* AdjacencyListGraph.swift */; }; 491AA3781CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491AA3771CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift */; }; 49BFA3011CDF886B00522D66 /* Graph.h in Headers */ = {isa = PBXBuildFile; fileRef = 49BFA3001CDF886B00522D66 /* Graph.h */; settings = {ATTRIBUTES = (Public, ); }; }; 49BFA3081CDF886B00522D66 /* Graph.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49BFA2FD1CDF886B00522D66 /* Graph.framework */; }; 49BFA30D1CDF886B00522D66 /* GraphTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA30C1CDF886B00522D66 /* GraphTests.swift */; }; 49BFA3181CDF887E00522D66 /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA3171CDF887E00522D66 /* Graph.swift */; }; 49BFA3271CDF899400522D66 /* Edge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA3261CDF899400522D66 /* Edge.swift */; }; 49BFA32F1CDF89FC00522D66 /* Vertex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA32E1CDF89FC00522D66 /* Vertex.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 49BFA3091CDF886B00522D66 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 49BFA2F41CDF886B00522D66 /* Project object */; proxyType = 1; remoteGlobalIDString = 49BFA2FC1CDF886B00522D66; remoteInfo = Graph; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 491AA3751CE6B81C00A2E2C5 /* AdjacencyListGraph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdjacencyListGraph.swift; sourceTree = ""; }; 491AA3771CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdjacencyMatrixGraph.swift; sourceTree = ""; }; 49BFA2FD1CDF886B00522D66 /* Graph.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Graph.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 49BFA3001CDF886B00522D66 /* Graph.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Graph.h; sourceTree = ""; }; 49BFA3021CDF886B00522D66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49BFA3071CDF886B00522D66 /* GraphTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GraphTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 49BFA30C1CDF886B00522D66 /* GraphTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphTests.swift; sourceTree = ""; }; 49BFA30E1CDF886B00522D66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49BFA3171CDF887E00522D66 /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = ""; }; 49BFA3261CDF899400522D66 /* Edge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Edge.swift; sourceTree = ""; }; 49BFA32E1CDF89FC00522D66 /* Vertex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vertex.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 49BFA2F91CDF886B00522D66 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 49BFA3041CDF886B00522D66 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 49BFA3081CDF886B00522D66 /* Graph.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 49BFA2F31CDF886B00522D66 = { isa = PBXGroup; children = ( 49BFA2FF1CDF886B00522D66 /* Graph */, 49BFA30B1CDF886B00522D66 /* GraphTests */, 49BFA2FE1CDF886B00522D66 /* Products */, ); sourceTree = ""; }; 49BFA2FE1CDF886B00522D66 /* Products */ = { isa = PBXGroup; children = ( 49BFA2FD1CDF886B00522D66 /* Graph.framework */, 49BFA3071CDF886B00522D66 /* GraphTests.xctest */, ); name = Products; sourceTree = ""; }; 49BFA2FF1CDF886B00522D66 /* Graph */ = { isa = PBXGroup; children = ( 49BFA3001CDF886B00522D66 /* Graph.h */, 49BFA3021CDF886B00522D66 /* Info.plist */, 49BFA3261CDF899400522D66 /* Edge.swift */, 49BFA32E1CDF89FC00522D66 /* Vertex.swift */, 49BFA3171CDF887E00522D66 /* Graph.swift */, 491AA3751CE6B81C00A2E2C5 /* AdjacencyListGraph.swift */, 491AA3771CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift */, ); path = Graph; sourceTree = ""; }; 49BFA30B1CDF886B00522D66 /* GraphTests */ = { isa = PBXGroup; children = ( 49BFA30C1CDF886B00522D66 /* GraphTests.swift */, 49BFA30E1CDF886B00522D66 /* Info.plist */, ); path = GraphTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 49BFA2FA1CDF886B00522D66 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 49BFA3011CDF886B00522D66 /* Graph.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 49BFA2FC1CDF886B00522D66 /* Graph */ = { isa = PBXNativeTarget; buildConfigurationList = 49BFA3111CDF886B00522D66 /* Build configuration list for PBXNativeTarget "Graph" */; buildPhases = ( 49BFA2F81CDF886B00522D66 /* Sources */, 49BFA2F91CDF886B00522D66 /* Frameworks */, 49BFA2FA1CDF886B00522D66 /* Headers */, 49BFA2FB1CDF886B00522D66 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Graph; productName = Graph; productReference = 49BFA2FD1CDF886B00522D66 /* Graph.framework */; productType = "com.apple.product-type.framework"; }; 49BFA3061CDF886B00522D66 /* GraphTests */ = { isa = PBXNativeTarget; buildConfigurationList = 49BFA3141CDF886B00522D66 /* Build configuration list for PBXNativeTarget "GraphTests" */; buildPhases = ( 49BFA3031CDF886B00522D66 /* Sources */, 49BFA3041CDF886B00522D66 /* Frameworks */, 49BFA3051CDF886B00522D66 /* Resources */, ); buildRules = ( ); dependencies = ( 49BFA30A1CDF886B00522D66 /* PBXTargetDependency */, ); name = GraphTests; productName = GraphTests; productReference = 49BFA3071CDF886B00522D66 /* GraphTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 49BFA2F41CDF886B00522D66 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 49BFA2FC1CDF886B00522D66 = { CreatedOnToolsVersion = 7.3; LastSwiftMigration = 0900; }; 49BFA3061CDF886B00522D66 = { CreatedOnToolsVersion = 7.3; LastSwiftMigration = 0820; }; }; }; buildConfigurationList = 49BFA2F71CDF886B00522D66 /* Build configuration list for PBXProject "Graph" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 49BFA2F31CDF886B00522D66; productRefGroup = 49BFA2FE1CDF886B00522D66 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 49BFA2FC1CDF886B00522D66 /* Graph */, 49BFA3061CDF886B00522D66 /* GraphTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 49BFA2FB1CDF886B00522D66 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 49BFA3051CDF886B00522D66 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 49BFA2F81CDF886B00522D66 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 491AA3761CE6B81C00A2E2C5 /* AdjacencyListGraph.swift in Sources */, 49BFA3271CDF899400522D66 /* Edge.swift in Sources */, 491AA3781CE6B82E00A2E2C5 /* AdjacencyMatrixGraph.swift in Sources */, 49BFA3181CDF887E00522D66 /* Graph.swift in Sources */, 49BFA32F1CDF89FC00522D66 /* Vertex.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 49BFA3031CDF886B00522D66 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 49BFA30D1CDF886B00522D66 /* GraphTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 49BFA30A1CDF886B00522D66 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 49BFA2FC1CDF886B00522D66 /* Graph */; targetProxy = 49BFA3091CDF886B00522D66 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 49BFA30F1CDF886B00522D66 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 49BFA3101CDF886B00522D66 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.2; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 49BFA3121CDF886B00522D66 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = Graph/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.Graph"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.2; }; name = Debug; }; 49BFA3131CDF886B00522D66 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = Graph/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.Graph"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.2; }; name = Release; }; 49BFA3151CDF886B00522D66 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = GraphTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.GraphTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Debug; }; 49BFA3161CDF886B00522D66 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = GraphTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.GraphTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 49BFA2F71CDF886B00522D66 /* Build configuration list for PBXProject "Graph" */ = { isa = XCConfigurationList; buildConfigurations = ( 49BFA30F1CDF886B00522D66 /* Debug */, 49BFA3101CDF886B00522D66 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 49BFA3111CDF886B00522D66 /* Build configuration list for PBXNativeTarget "Graph" */ = { isa = XCConfigurationList; buildConfigurations = ( 49BFA3121CDF886B00522D66 /* Debug */, 49BFA3131CDF886B00522D66 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 49BFA3141CDF886B00522D66 /* Build configuration list for PBXNativeTarget "GraphTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 49BFA3151CDF886B00522D66 /* Debug */, 49BFA3161CDF886B00522D66 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 49BFA2F41CDF886B00522D66 /* Project object */; } ================================================ FILE: Graph/Graph.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Graph/Graph.xcodeproj/xcshareddata/xcschemes/Graph.xcscheme ================================================ ================================================ FILE: Graph/Graph.xcodeproj/xcshareddata/xcschemes/GraphTests.xcscheme ================================================ ================================================ FILE: Graph/Graph.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Graph/Graph.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Graph/Graph.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: Graph/GraphTests/GraphTests.swift ================================================ // // GraphTests.swift // GraphTests // // Created by Andrew McKnight on 5/8/16. // import XCTest @testable import Graph class GraphTests: XCTestCase { func testAdjacencyMatrixGraphDescription() { let graph = AdjacencyMatrixGraph() let a = graph.createVertex("a") let b = graph.createVertex("b") let c = graph.createVertex("c") graph.addDirectedEdge(a, to: b, withWeight: 1.0) graph.addDirectedEdge(b, to: c, withWeight: 2.0) let expectedValue = " ø 1.0 ø \n ø ø 2.0 \n ø ø ø " XCTAssertEqual(graph.description, expectedValue) } func testAdjacencyListGraphDescription() { let graph = AdjacencyListGraph() let a = graph.createVertex("a") let b = graph.createVertex("b") let c = graph.createVertex("c") graph.addDirectedEdge(a, to: b, withWeight: 1.0) graph.addDirectedEdge(b, to: c, withWeight: 2.0) graph.addDirectedEdge(a, to: c, withWeight: -5.5) let expectedValue = "a -> [(b: 1.0), (c: -5.5)]\nb -> [(c: 2.0)]" XCTAssertEqual(graph.description, expectedValue) } func testAddingPreexistingVertex() { let adjacencyList = AdjacencyListGraph() let adjacencyMatrix = AdjacencyMatrixGraph() for graph in [adjacencyList, adjacencyMatrix] { let a = graph.createVertex("a") let b = graph.createVertex("a") XCTAssertEqual(a, b, "Should have returned the same vertex when creating a new one with identical data") XCTAssertEqual(graph.vertices.count, 1, "Graph should only contain one vertex after trying to create two vertices with identical data") } } func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) let b = graph.createVertex(2) graph.addDirectedEdge(a, to: b, withWeight: 1.0) let edgesFromA = graph.edgesFrom(a) let edgesFromB = graph.edgesFrom(b) XCTAssertEqual(edgesFromA.count, 1) XCTAssertEqual(edgesFromB.count, 0) XCTAssertEqual(edgesFromA.first?.to, b) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) let b = graph.createVertex(2) graph.addUndirectedEdge((a, b), withWeight: 1.0) let edgesFromA = graph.edgesFrom(a) let edgesFromB = graph.edgesFrom(b) XCTAssertEqual(edgesFromA.count, 1) XCTAssertEqual(edgesFromB.count, 1) XCTAssertEqual(edgesFromA.first?.to, b) XCTAssertEqual(edgesFromB.first?.to, a) } func testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) let b = graph.createVertex(2) XCTAssertEqual(graph.edgesFrom(a).count, 0) XCTAssertEqual(graph.edgesFrom(b).count, 0) } func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let verticesCount = 100 var vertices: [Vertex] = [] for i in 0...self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedMatrixGraph() { testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsNoInNoEdgeMatrixGraph() { testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedMatrixGraph() { testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedListGraph() { testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedListGraph() { testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsNoInNoEdgeListGraph() { testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedListGraph() { testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyListGraph.self) } } ================================================ FILE: Graph/GraphTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Graph/README.markdown ================================================ # Graph > This topic has been tutorialized [here](https://www.raywenderlich.com/152046/swift-algorithm-club-graphs-adjacency-list) A graph looks like the following picture: ![A graph](Images/Graph.png) In computer science, a graph is defined as a set of *vertices* paired with a set of *edges*. The vertices are represented by circles, and the edges are the lines between them. Edges connect a vertex to other vertices. > **Note:** Vertices are sometimes called "nodes", and edges are called "links". A graph can represent a social network. Each person is a vertex, and people who know each other are connected by edges. Here is a somewhat historically inaccurate example: ![Social network](Images/SocialNetwork.png) Graphs have various shapes and sizes. The edges can have a *weight*, where a positive or negative numeric value is assigned to each edge. Consider an example of a graph representing airplane flights. Cities can be vertices, and flights can be edges. Then, an edge weight could describe flight time or the price of a ticket. ![Airplane flights](Images/Flights.png) With this hypothetical airline, flying from San Francisco to Moscow is cheapest by going through New York. Edges can also be *directed*. In examples mentioned above, the edges are undirected. For instance, if Ada knows Charles, then Charles also knows Ada. A directed edge, on the other hand, implies a one-way relationship. A directed edge from vertex X to vertex Y connects X to Y, but *not* Y to X. Continuing from the flights example, a directed edge from San Francisco to Juneau in Alaska indicates that there is a flight from San Francisco to Juneau, but not from Juneau to San Francisco (I suppose that means you're walking back). ![One-way flights](Images/FlightsDirected.png) The following are also graphs: ![Tree and linked list](Images/TreeAndList.png) On the left is a [tree](../Tree/) structure, on the right a [linked list](../Linked%20List/). They can be considered graphs but in a simpler form. They both have vertices (nodes) and edges (links). The first graph includes *cycles*, where you can start off at a vertex, follow a path, and come back to the original vertex. A tree is a graph without such cycles. Another common type of graph is the *directed acyclic graph* or DAG: ![DAG](Images/DAG.png) Like a tree, this graph does not have any cycles (no matter where you start, there is no path back to the starting vertex), but this graph has directional edges with the shape that does not necessarily form a hierarchy. ## Why use graphs? Maybe you're shrugging your shoulders and thinking, what's the big deal? Well, it turns out that a graph is a useful data structure. If you have a programming problem where you can represent your data as vertices and edges, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First%20Search/) or [depth-first search](../Depth-First%20Search) to find a solution. For example, suppose you have a list of tasks where some tasks have to wait on others before they can begin. You can model this using an acyclic directed graph: ![Tasks as a graph](Images/Tasks.png) Each vertex represents a task. An edge between two vertices means the source task must be completed before the destination task can start. As an example, task C cannot start before B and D are finished, and B nor D can start before A is finished. Now that the problem is expressed using a graph, you can use a depth-first search to perform a [topological sort](../Topological%20Sort/). This will put the tasks in an optimal order so that you minimize the time spent waiting for tasks to complete. (One possible order here is A, B, D, E, C, F, G, H, I, J, K.) Whenever you are faced with a tough programming problem, ask yourself, "how can I express this problem using a graph?" Graphs are all about representing relationships between your data. The trick is in how you define "relationships". If you are a musician you might appreciate this graph: ![Chord map](Images/ChordMap.png) The vertices are chords from the C major scale. The edges -- the relationships between the chords -- represent how [likely one chord is to follow another](http://mugglinworks.com/chordmaps/genmap.htm). This is a directed graph, so the direction of the arrows shows how you can go from one chord to the next. It is also a weighted graph, where the weight of the edges -- portrayed here by line thickness -- shows a strong relationship between two chords. As you can see, a G7-chord is very likely to be followed by a C chord, and much less likely by a Am chord. You are probably already using graphs without even knowing it. Your data model is also a graph (from Apple's Core Data documentation): ![Core Data model](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreDataVersioning/Art/recipe_version2.0.jpg) Another common graph used by programmers is the state machine, where edges depict the conditions for transitioning between states. Here is a state machine that models my cat: ![State machine](Images/StateMachine.png) Graphs are awesome. Facebook made a fortune from their social graph. If you are going to learn any data structure, you must choose the graph and the vast collection of standard graph algorithms. ## Vertices and edges, oh my! In theory, a graph is just a bunch of vertex and edge objects, but how do you describe this in code? There are two main strategies: adjacency list and adjacency matrix. **Adjacency List.** In an adjacency list implementation, each vertex stores a list of edges that originate from that vertex. For example, if vertex A has an edge to vertices B, C, and D, then vertex A would have a list containing 3 edges. ![Adjacency list](Images/AdjacencyList.png) The adjacency list describes outgoing edges. A has an edge to B, but B does not have an edge back to A, so A does not appear in B's adjacency list. Finding an edge or weight between two vertices can be expensive because there is no random access to edges. You must traverse the adjacency lists until it is found. **Adjacency Matrix.** In an adjacency matrix implementation, a matrix with rows and columns representing vertices stores a weight to indicate if vertices are connected and by what weight. For example, if there is a directed edge of weight 5.6 from vertex A to vertex B, then the entry with row for vertex A and column for vertex B would have the value 5.6: ![Adjacency matrix](Images/AdjacencyMatrix.png) Adding another vertex to the graph is expensive, because a new matrix structure must be created with enough space to hold the new row/column, and the existing structure must be copied into the new one. So which one should you use? Most of the time, the adjacency list is the right approach. What follows is a more detailed comparison between the two. Let *V* be the number of vertices in the graph, and *E* the number of edges. Then we have: | Operation | Adjacency List | Adjacency Matrix | |-----------------|----------------|------------------| | Storage Space | O(V + E) | O(V^2) | | Add Vertex | O(1) | O(V^2) | | Add Edge | O(1) | O(1) | | Check Adjacency | O(V) | O(1) | "Checking adjacency" means that we try to determine that a given vertex is an immediate neighbor of another vertex. The time to check adjacency for an adjacency list is **O(V)**, because in the worst case a vertex is connected to *every* other vertex. In the case of a *sparse* graph, where each vertex is connected to only a handful of other vertices, an adjacency list is the best way to store the edges. If the graph is *dense*, where each vertex is connected to most of the other vertices, then a matrix is preferred. Here are sample implementations of both adjacency list and adjacency matrix: ## The code: edges and vertices The adjacency list for each vertex consists of `Edge` objects: ```swift public struct Edge: Equatable where T: Equatable, T: Hashable { public let from: Vertex public let to: Vertex public let weight: Double? } ``` This struct describes the "from" and "to" vertices and a weight value. Note that an `Edge` object is always directed, a one-way connection (shown as arrows in the illustrations above). If you want an undirected connection, you also need to add an `Edge` object in the opposite direction. Each `Edge` optionally stores a weight, so they can be used to describe both weighted and unweighted graphs. The `Vertex` looks like this: ```swift public struct Vertex: Equatable where T: Equatable, T: Hashable { public var data: T public let index: Int } ``` It stores arbitrary data with a generic type `T`, which is `Hashable` to enforce uniqueness, and also `Equatable`. Vertices themselves are also `Equatable`. ## The code: graphs > **Note:** There are many ways to implement graphs. The code given here is just one possible implementation. You probably want to tailor the graph code to each individual problem you are trying to solve. For instance, your edges may not need a `weight` property, or you may not have the need to distinguish between directed and undirected edges. Here is an example of a simple graph: ![Demo](Images/Demo1.png) We can represent it as an adjacency matrix or adjacency list. The classes implementing those concepts both inherit a common API from `AbstractGraph`, so they can be created in an identical fashion, with different optimized data structures behind the scenes. Let's create some directed, weighted graphs, using each representation, to store the example: ```swift for graph in [AdjacencyMatrixGraph(), AdjacencyListGraph()] { let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) let v4 = graph.createVertex(4) let v5 = graph.createVertex(5) graph.addDirectedEdge(v1, to: v2, withWeight: 1.0) graph.addDirectedEdge(v2, to: v3, withWeight: 1.0) graph.addDirectedEdge(v3, to: v4, withWeight: 4.5) graph.addDirectedEdge(v4, to: v1, withWeight: 2.8) graph.addDirectedEdge(v2, to: v5, withWeight: 3.2) } ``` As mentioned earlier, to create an undirected edge you need to make two directed edges. For undirected graphs, we call the following method instead: ```swift graph.addUndirectedEdge(v1, to: v2, withWeight: 1.0) graph.addUndirectedEdge(v2, to: v3, withWeight: 1.0) graph.addUndirectedEdge(v3, to: v4, withWeight: 4.5) graph.addUndirectedEdge(v4, to: v1, withWeight: 2.8) graph.addUndirectedEdge(v2, to: v5, withWeight: 3.2) ``` We could provide `nil` as the values for the `withWeight` parameter in either case to make unweighted graphs. ## The code: adjacency list To maintain the adjacency list, there is a class that maps a list of edges to a vertex. The graph simply maintains an array of such objects and modifies them as necessary. ```swift private class EdgeList where T: Equatable, T: Hashable { var vertex: Vertex var edges: [Edge]? = nil init(vertex: Vertex) { self.vertex = vertex } func addEdge(_ edge: Edge) { edges?.append(edge) } } ``` They are implemented as a class as opposed to structs, so we can modify them by reference, in place, like when adding an edge to a new vertex, where the source vertex already has an edge list: ```swift open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists let matchingVertices = vertices.filter() { vertex in return vertex.data == data } if matchingVertices.count > 0 { return matchingVertices.last! } // if the vertex doesn't exist, create a new one let vertex = Vertex(data: data, index: adjacencyList.count) adjacencyList.append(EdgeList(vertex: vertex)) return vertex } ``` The adjacency list for the example looks like this: ``` v1 -> [(v2: 1.0)] v2 -> [(v3: 1.0), (v5: 3.2)] v3 -> [(v4: 4.5)] v4 -> [(v1: 2.8)] ``` where the general form `a -> [(b: w), ...]` means an edge exists from `a` to `b` with weight `w` (with possibly more edges connecting `a` to other vertices as well). ## The code: adjacency matrix We will keep track of the adjacency matrix in a two-dimensional `[[Double?]]` array. An entry of `nil` indicates no edge, while any other value indicates an edge of the given weight. If `adjacencyMatrix[i][j]` is not nil, then there is an edge from vertex `i` to vertex `j`. To index into the matrix using vertices, we use the `index` property in `Vertex`, which is assigned when creating the vertex through the graph object. When creating a new vertex, the graph must resize the matrix: ```swift open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists let matchingVertices = vertices.filter() { vertex in return vertex.data == data } if matchingVertices.count > 0 { return matchingVertices.last! } // if the vertex doesn't exist, create a new one let vertex = Vertex(data: data, index: adjacencyMatrix.count) // Expand each existing row to the right one column. for i in 0 ..< adjacencyMatrix.count { adjacencyMatrix[i].append(nil) } // Add one new row at the bottom. let newRow = [Double?](repeating: nil, count: adjacencyMatrix.count + 1) adjacencyMatrix.append(newRow) _vertices.append(vertex) return vertex } ``` Then the adjacency matrix looks like this: [[nil, 1.0, nil, nil, nil] v1 [nil, nil, 1.0, nil, 3.2] v2 [nil, nil, nil, 4.5, nil] v3 [2.8, nil, nil, nil, nil] v4 [nil, nil, nil, nil, nil]] v5 v1 v2 v3 v4 v5 ## See also This article described what a graph is, and how you can implement the basic data structure. We have other articles on practical uses of graphs, so check those out too! *Written by Donald Pinckney and Matthijs Hollemans* ================================================ FILE: Hash Set/HashSet.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play var set = HashSet() set.insert("one") set.insert("two") set.insert("three") set.allElements() set.insert("two") set.allElements() set.contains("one") set.remove("one") set.allElements() set.contains("one") /* Union */ var setA = HashSet() setA.insert(1) setA.insert(2) setA.insert(3) setA.insert(4) var setB = HashSet() setB.insert(3) setB.insert(4) setB.insert(5) setB.insert(6) let union = setA.union(setB) union.allElements() // [5, 6, 2, 3, 1, 4] /* Intersection */ let intersection = setA.intersect(setB) intersection.allElements() // [3, 4] /* Difference */ let difference1 = setA.difference(setB) difference1.allElements() // [2, 1] let difference2 = setB.difference(setA) difference2.allElements() // [5, 6] ================================================ FILE: Hash Set/HashSet.playground/Sources/HashSet.swift ================================================ //: Playground - noun: a place where people can play public struct HashSet { fileprivate var dictionary = Dictionary() public init() { } public mutating func insert(_ element: T) { dictionary[element] = true } public mutating func remove(_ element: T) { dictionary[element] = nil } public func contains(_ element: T) -> Bool { return dictionary[element] != nil } public func allElements() -> [T] { return Array(dictionary.keys) } public var count: Int { return dictionary.count } public var isEmpty: Bool { return dictionary.isEmpty } } /* Union */ extension HashSet { public func union(_ otherSet: HashSet) -> HashSet { var combined = HashSet() for obj in self.dictionary.keys { combined.insert(obj) } for obj in otherSet.dictionary.keys { combined.insert(obj) } return combined } } /* Intersection */ extension HashSet { public func intersect(_ otherSet: HashSet) -> HashSet { var common = HashSet() for obj in dictionary.keys { if otherSet.contains(obj) { common.insert(obj) } } return common } } /* Difference */ extension HashSet { public func difference(_ otherSet: HashSet) -> HashSet { var diff = HashSet() for obj in dictionary.keys { if !otherSet.contains(obj) { diff.insert(obj) } } return diff } } ================================================ FILE: Hash Set/HashSet.playground/contents.xcplayground ================================================ ================================================ FILE: Hash Set/HashSet.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Hash Set/HashSet.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Hash Set/HashSet.swift ================================================ public struct HashSet { private var dictionary = Dictionary() public mutating func insert(element: T) { dictionary[element] = true } public mutating func remove(element: T) { dictionary[element] = nil } public func contains(element: T) -> Bool { return dictionary[element] != nil } public func allElements() -> [T] { return Array(dictionary.keys) } public var count: Int { return dictionary.count } public var isEmpty: Bool { return dictionary.isEmpty } } extension HashSet { public func union(otherSet: HashSet) -> HashSet { var combined = HashSet() for obj in dictionary.keys { combined.insert(obj) } for obj in otherSet.dictionary.keys { combined.insert(obj) } return combined } public func intersect(otherSet: HashSet) -> HashSet { var common = HashSet() for obj in dictionary.keys { if otherSet.contains(obj) { common.insert(obj) } } return common } public func difference(otherSet: HashSet) -> HashSet { var diff = HashSet() for obj in dictionary.keys { if !otherSet.contains(obj) { diff.insert(obj) } } return diff } } ================================================ FILE: Hash Set/Images/CombineSets.graffle ================================================ ActiveLayerIndex 0 ApplicationVersion com.omnigroup.OmniGraffle6.MacAppStore 167.4 AutoAdjust BackgroundGraphic Bounds {{0, 0}, {559.28001499176025, 782.8900146484375}} Class SolidGraphic ID 2 Style stroke Draws NO BaseZoom 0 CanvasOrigin {0, 0} ColumnAlign 1 ColumnSpacing 36 CreationDate 2014-11-05 12:23:41 +0000 Creator Matthijs DisplayScale 1.0000 cm = 1.0000 cm ExportShapes InspectorGroup 255 ShapeImageRect {{2, 2}, {22, 22}} ShapeName 232885A2-A375-4FB4-BA43-24B390AE920A-34894-00030AD794E8A764 ShouldExport YES StrokePath elements element MOVETO point {-4.0305071813406812e-07, -0.49999985541807312} control1 {-0.66666664829673206, -0.2229760996015262} control2 {-0.66666653231640627, 0.22297630296069038} element CURVETO point {-5.5109742547188034e-08, 0.5} control1 {0.6666667137482456, 0.22297609960152798} control2 {0.66666659776791981, -0.2229763029606886} element CURVETO point {1.2056125342496671e-07, -0.5} element CLOSE element MOVETO point {-4.0305071813406812e-07, -0.49999985541807312} TextBounds {{0, 0}, {1, 1}} GraphDocumentVersion 12 GraphicsList Class Group Graphics Class Group Graphics Bounds {{363.44110091494207, 181.54080882304791}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 130 Shape Circle Style fill Draws NO shadow Draws NO Bounds {{403.13219679380046, 199.35715176273706}, {57.5, 14}} Class ShapedGraphic FitText Vertical Flow Resize FontInfo Font Helvetica Size 12 ID 131 Style fill Draws NO shadow Draws NO stroke Draws NO Text Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 \f0\b\fs24 \cf0 B} VerticalPad 0.0 Bounds {{357.5783973870204, 199.35712936151944}, {57.5, 14}} Class ShapedGraphic FitText Vertical Flow Resize FontInfo Font Helvetica Size 12 ID 132 Style fill Draws NO shadow Draws NO stroke Draws NO Text Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 \f0\b\fs24 \cf0 A} VerticalPad 0.0 Bounds {{399.76763169599639, 180.84693146069711}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 133 Shape Circle Style shadow Draws NO Bounds {{363.2138444645513, 180.33672333081441}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 134 Shape Circle Style fill Draws NO shadow Draws NO stroke Draws NO Bounds {{363.44110091494207, 181.54080882304791}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 135 Shape Circle Style fill FillType 2 GradientAngle 90 GradientColor w 0.666667 shadow Draws NO Bounds {{399.95130498664474, 180.52040782207135}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 136 Shape Circle Style fill FillType 2 GradientAngle 90 GradientColor w 0.666667 shadow Draws NO stroke Draws NO ID 129 Bounds {{362.10529709041043, 246.7831437431239}, {94, 19}} Class ShapedGraphic FitText YES Flow Resize ID 137 Style fill Draws NO shadow Draws NO stroke Draws NO Text Align 0 Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\froman\fcharset0 Times-Roman;\f2\fnil\fcharset0 LucidaGrande; \f3\ftech\fcharset77 Symbol;} {\colortbl;\red255\green255\blue255;} \deftab720 \pard\pardeftab720\sa240\partightenfactor0 \f0\fs24 \cf0 Difference \f1\fs30 A \f2 - \f3 \f1 B} VerticalPad 0.0 Wrap NO ID 128 Class Group Graphics Bounds {{216.5783973870204, 247.18110099700706}, {105, 18}} Class ShapedGraphic FitText YES Flow Resize ID 121 Style fill Draws NO shadow Draws NO stroke Draws NO Text Align 0 Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\froman\fcharset0 Times-Roman;\f2\ftech\fcharset77 Symbol; } {\colortbl;\red255\green255\blue255;} \deftab720 \pard\pardeftab720\sa240\partightenfactor0 \f0\fs24 \cf0 Intersection \f1\fs30 A \f2 \uc0\u8745 \f1 B} VerticalPad 0.0 Wrap NO Class Group Graphics Bounds {{263.55728311947803, 199.95919450885376}, {57.5, 14}} Class ShapedGraphic FitText Vertical Flow Resize FontInfo Font Helvetica Size 12 ID 123 Style fill Draws NO shadow Draws NO stroke Draws NO Text Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 \f0\b\fs24 \cf0 B} VerticalPad 0.0 Bounds {{217.09951165456278, 199.95917210763608}, {57.5, 14}} Class ShapedGraphic FitText Vertical Flow Resize FontInfo Font Helvetica Size 12 ID 124 Style fill Draws NO shadow Draws NO stroke Draws NO Text Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 \f0\b\fs24 \cf0 A} VerticalPad 0.0 Bounds {{260.70292209337657, 180.93877727753991}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 125 Shape Circle Style fill Draws NO shadow Draws NO Bounds {{224.14913486193149, 180.93876607693116}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 126 Shape Circle Style fill Draws NO shadow Draws NO Bounds {{260.88658255123266, 188.75053690631128}, {14.820989752243648, 36.580534988253419}} Class ShapedGraphic ID 127 Shape 232885A2-A375-4FB4-BA43-24B390AE920A-34894-00030AD794E8A764 Style fill FillType 2 GradientAngle 90 GradientColor w 0.666667 shadow Draws NO stroke Draws NO ID 122 ID 120 Class Group Graphics Bounds {{92.051497683630373, 247.18109539670272}, {74, 18}} Class ShapedGraphic FitText YES Flow Resize ID 112 Style fill Draws NO shadow Draws NO stroke Draws NO Text Align 0 Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\froman\fcharset0 Times-Roman;\f2\ftech\fcharset77 Symbol; } {\colortbl;\red255\green255\blue255;} \deftab720 \pard\pardeftab720\sa240\partightenfactor0 \f0\fs24 \cf0 Union \f1\fs30 A \f2 \uc0\u8746 \f1 B} VerticalPad 0.0 Wrap NO Class Group Graphics Bounds {{123.07839738702042, 199.95920010915816}, {57.5, 14}} Class ShapedGraphic FitText Vertical Flow Resize FontInfo Font Helvetica Size 12 ID 114 Style fill Draws NO shadow Draws NO stroke Draws NO Text Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 \f0\b\fs24 \cf0 B} VerticalPad 0.0 Bounds {{77.524597980240316, 199.95917770794046}, {57.5, 14}} Class ShapedGraphic FitText Vertical Flow Resize FontInfo Font Helvetica Size 12 ID 115 Style fill Draws NO shadow Draws NO stroke Draws NO Text Pad 0.0 Text {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 \f0\b\fs24 \cf0 A} VerticalPad 0.0 Bounds {{119.71383228921627, 181.44897980711818}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 116 Shape Circle Style fill Draws NO shadow Draws NO Bounds {{83.160045057771171, 180.93877167723554}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 117 Shape Circle Style fill Draws NO shadow Draws NO stroke Draws NO Bounds {{83.387301508161968, 182.14285716946898}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 118 Shape Circle Style fill FillType 2 GradientAngle 90 GradientColor w 0.666667 shadow Draws NO Bounds {{119.89750557986466, 181.12245616849242}, {51.331169128417969, 52.040813446044922}} Class ShapedGraphic ID 119 Shape Circle Style fill FillType 2 GradientAngle 90 GradientColor w 0.666667 shadow Draws NO stroke Draws NO ID 113 ID 111 GridInfo GuidesLocked NO GuidesVisible YES HPages 1 ImageCounter 1 KeepToScale Layers Lock NO Name Layer 1 Print YES View YES LayoutInfo Animate NO circoMinDist 18 circoSeparation 0.0 layoutEngine dot neatoLineLength 0.20000000298023224 neatoSeparation 0.0 twopiSeparation 0.0 LinksVisible NO MagnetsVisible NO MasterSheets ModificationDate 2016-01-31 10:15:40 +0000 Modifier Matthijs Hollemans NotesVisible NO Orientation 2 OriginVisible NO PageBreaks YES PrintInfo NSBottomMargin float 41 NSHorizonalPagination coded BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG NSLeftMargin float 18 NSPaperSize size {595.28001499176025, 841.8900146484375} NSPrintReverseOrientation coded BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG NSRightMargin float 18 NSTopMargin float 18 PrintOnePage ReadOnly NO RowAlign 1 RowSpacing 36 SheetTitle Canvas 1 SmartAlignmentGuidesActive YES SmartDistanceGuidesActive YES UniqueID 1 UseEntirePage VPages 1 WindowInfo CurrentSheet 0 Expanded_Canvases Frame {{525, 120}, {1703, 1293}} ShowInfo ShowRuler Sidebar SidebarWidth 200 TopSlabHeight 250 VisibleRegion {{0, 32.075473429597466}, {560.8490868792851, 535.37738739107533}} Zoom 2.119999885559082 ZoomValues Canvas 1 2.119999885559082 2.0699999332427979 ================================================ FILE: Hash Set/README.markdown ================================================ # Hash Set A set is a collection of elements that is kind of like an array but with two important differences: the order of the elements in the set is unimportant and each element can appear only once. If the following were arrays, they'd all be different. However, they all represent the same set: ```swift [1 ,2, 3] [2, 1, 3] [3, 2, 1] [1, 2, 2, 3, 1] ``` Because each element can appear only once, it doesn't matter how often you write the element down -- only one of them counts. > **Note:** I often prefer to use sets over arrays when I have a collection of objects but don't care what order they are in. Using a set communicates to the programmer that the order of the elements is unimportant. If you're using an array, then you can't assume the same thing. Typical operations on a set are: - insert an element - remove an element - check whether the set contains an element - take the union with another set - take the intersection with another set - calculate the difference with another set Union, intersection, and difference are ways to combine two sets into a single one: ![Union, intersection, difference](Images/CombineSets.png) As of Swift 1.2, the standard library includes a built-in `Set` type but here I'll show how you can make your own. You wouldn't use this in production code, but it's instructive to see how sets are implemented. It's possible to implement a set using a simple array but that's not the most efficient way. Instead, we'll use a dictionary. Since `Swift`'s dictionary is built using a hash table, our own set will be a hash set. ## The code Here are the beginnings of `HashSet` in Swift: ```swift public struct HashSet { fileprivate var dictionary = Dictionary() public init() { } public mutating func insert(_ element: T) { dictionary[element] = true } public mutating func remove(_ element: T) { dictionary[element] = nil } public func contains(_ element: T) -> Bool { return dictionary[element] != nil } public func allElements() -> [T] { return Array(dictionary.keys) } public var count: Int { return dictionary.count } public var isEmpty: Bool { return dictionary.isEmpty } } ``` The code is really very simple because we rely on Swift's built-in `Dictionary` to do all the hard work. The reason we use a dictionary is that dictionary keys must be unique, just like the elements from a set. In addition, a dictionary has **O(1)** time complexity for most of its operations, making this set implementation very fast. Because we're using a dictionary, the generic type `T` must conform to `Hashable`. You can put any type of object into our set, as long as it can be hashed. (This is true for Swift's own `Set` too.) Normally, you use a dictionary to associate keys with values, but for a set we only care about the keys. That's why we use `Bool` as the dictionary's value type, even though we only ever set it to `true`, never to `false`. (We could have picked anything here but booleans take up the least space.) Copy the code to a playground and add some tests: ```swift var set = HashSet() set.insert("one") set.insert("two") set.insert("three") set.allElements() // ["one, "three", "two"] set.insert("two") set.allElements() // still ["one, "three", "two"] set.contains("one") // true set.remove("one") set.contains("one") // false ``` The `allElements()` function converts the contents of the set into an array. Note that the order of the elements in that array can be different than the order in which you added the items. As I said, a set doesn't care about the order of the elements (and neither does a dictionary). ## Combining sets A lot of the usefulness of sets is in how you can combine them. (If you've ever used a vector drawing program like Sketch or Illustrator, you'll have seen the Union, Subtract, Intersect options to combine shapes. Same thing.) Here is the code for the union operation: ```swift extension HashSet { public func union(_ otherSet: HashSet) -> HashSet { var combined = HashSet() for obj in self.dictionary.keys { combined.insert(obj) } for obj in otherSet.dictionary.keys { combined.insert(obj) } return combined } } ``` The *union* of two sets creates a new set that consists of all the elements in set A plus all the elements in set B. Of course, if there are duplicate elements they count only once. Example: ```swift var setA = HashSet() setA.insert(1) setA.insert(2) setA.insert(3) setA.insert(4) var setB = HashSet() setB.insert(3) setB.insert(4) setB.insert(5) setB.insert(6) let union = setA.union(setB) union.allElements() // [5, 6, 2, 3, 1, 4] ``` As you can see, the union of the two sets contains all of the elements now. The values `3` and `4` still appear only once, even though they were in both sets. The *intersection* of two sets contains only the elements that they have in common. Here is the code: ```swift extension HashSet { public func intersect(_ otherSet: HashSet) -> HashSet { var common = HashSet() for obj in dictionary.keys { if otherSet.contains(obj) { common.insert(obj) } } return common } } ``` To test it: ```swift let intersection = setA.intersect(setB) intersection.allElements() ``` This prints `[3, 4]` because those are the only objects from set A that are also in set B. Finally, the *difference* between two sets removes the elements they have in common. The code is as follows: ```swift extension HashSet { public func difference(_ otherSet: HashSet) -> HashSet { var diff = HashSet() for obj in dictionary.keys { if !otherSet.contains(obj) { diff.insert(obj) } } return diff } } ``` It's really the opposite of `intersect()`. Try it out: ```swift let difference1 = setA.difference(setB) difference1.allElements() // [2, 1] let difference2 = setB.difference(setA) difference2.allElements() // [5, 6] ``` ## Where to go from here? If you look at the [documentation](http://swiftdoc.org/v2.1/type/Set/) for Swift's own `Set`, you'll notice it has tons more functionality. An obvious extension would be to make `HashSet` conform to `SequenceType` so that you can iterate it with a `for`...`in` loop. Another thing you could do is replace the `Dictionary` with an actual [hash table](../Hash%20Table), but one that just stores the keys and doesn't associate them with anything. So you wouldn't need the `Bool` values anymore. If you often need to look up whether an element belongs to a set and perform unions, then the [union-find](../Union-Find/) data structure may be more suitable. It uses a tree structure instead of a dictionary to make the find and union operations very efficient. > **Note:** I'd like to make `HashSet` conform to `ArrayLiteralConvertible` so you can write `let setA: HashSet = [1, 2, 3, 4]` but currently this crashes the compiler. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Hash Table/HashTable.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // Playing with hash values "firstName".hashValue abs("firstName".hashValue) % 5 "lastName".hashValue abs("lastName".hashValue) % 5 "hobbies".hashValue abs("hobbies".hashValue) % 5 // Playing with the hash table var hashTable = HashTable(capacity: 5) hashTable["firstName"] = "Steve" hashTable["lastName"] = "Jobs" hashTable["hobbies"] = "Programming Swift" print(hashTable) print(hashTable.debugDescription) let x = hashTable["firstName"] hashTable["firstName"] = "Tim" let y = hashTable["firstName"] hashTable["firstName"] = nil let z = hashTable["firstName"] print(hashTable) print(hashTable.debugDescription) ================================================ FILE: Hash Table/HashTable.playground/Sources/HashTable.swift ================================================ /* Hash Table: A symbol table of generic key-value pairs. The key must be `Hashable`, which means it can be transformed into a fairly unique integer value. The more unique the hash value, the better. Hash tables use an internal array of buckets to store key-value pairs. The hash table's capacity is determined by the number of buckets. This implementation has a fixed capacity--it does not resize the array as more key-value pairs are inserted. To insert or locate a particular key-value pair, a hash function transforms the key into an array index. An ideal hash function would guarantee that different keys map to different indices. In practice, however, this is difficult to achieve. Since different keys can map to the same array index, all hash tables implement a collision resolution strategy. This implementation uses a strategy called separate chaining, where key-value pairs that hash to the same index are "chained together" in a list. For good performance, the capacity of the hash table should be sufficiently large so that the lists are small. A well-sized hash table provides very good average performance. In the worst-case, however, all keys map to the same bucket, resulting in a list that that requires O(n) time to traverse. Average Worst-Case Space: O(n) O(n) Search: O(1) O(n) Insert: O(1) O(n) Delete: O(1) O(n) */ public struct HashTable { private typealias Element = (key: Key, value: Value) private typealias Bucket = [Element] private var buckets: [Bucket] /// The number of key-value pairs in the hash table. private(set) public var count = 0 /// A Boolean value that indicates whether the hash table is empty. public var isEmpty: Bool { return count == 0 } /** Create a hash table with the given capacity. */ public init(capacity: Int) { assert(capacity > 0) buckets = Array(repeatElement([], count: capacity)) } /** Accesses the value associated with the given key for reading and writing. */ public subscript(key: Key) -> Value? { get { return value(forKey: key) } set { if let value = newValue { updateValue(value, forKey: key) } else { removeValue(forKey: key) } } } /** Returns the value for the given key. */ public func value(forKey key: Key) -> Value? { let index = self.index(forKey: key) for element in buckets[index] { if element.key == key { return element.value } } return nil // key not in hash table } /** Updates the value stored in the hash table for the given key, or adds a new key-value pair if the key does not exist. */ @discardableResult public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { let index = self.index(forKey: key) // Do we already have this key in the bucket? for (i, element) in buckets[index].enumerated() { if element.key == key { let oldValue = element.value buckets[index][i].value = value return oldValue } } // This key isn't in the bucket yet; add it to the chain. buckets[index].append((key: key, value: value)) count += 1 return nil } /** Removes the given key and its associated value from the hash table. */ @discardableResult public mutating func removeValue(forKey key: Key) -> Value? { let index = self.index(forKey: key) // Find the element in the bucket's chain and remove it. for (i, element) in buckets[index].enumerated() { if element.key == key { buckets[index].remove(at: i) count -= 1 return element.value } } return nil // key not in hash table } /** Removes all key-value pairs from the hash table. */ public mutating func removeAll() { buckets = Array(repeatElement([], count: buckets.count)) count = 0 } /** Returns the given key's array index. */ private func index(forKey key: Key) -> Int { return abs(key.hashValue % buckets.count) } } extension HashTable: CustomStringConvertible { /// A string that represents the contents of the hash table. public var description: String { let pairs = buckets.flatMap { b in b.map { e in "\(e.key) = \(e.value)" } } return pairs.joined(separator: ", ") } /// A string that represents the contents of /// the hash table, suitable for debugging. public var debugDescription: String { var str = "" for (i, bucket) in buckets.enumerated() { let pairs = bucket.map { e in "\(e.key) = \(e.value)" } str += "bucket \(i): " + pairs.joined(separator: ", ") + "\n" } return str } } ================================================ FILE: Hash Table/HashTable.playground/contents.xcplayground ================================================ ================================================ FILE: Hash Table/HashTable.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Hash Table/HashTable.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Hash Table/README.markdown ================================================ # Hash Table A hash table allows you to store and retrieve objects by a "key". A hash table is used to implement structures, such as a dictionary, a map, and an associative array. These structures can be implemented by a tree or a plain array, but it is efficient to use a hash table. This should explain why Swift's built-in `Dictionary` type requires that keys conform to the `Hashable` protocol: internally it uses a hash table, like the one you will learn about here. ## How it works A hash table is nothing more than an array. Initially, this array is empty. When you put a value into the hash table under a certain key, it uses that key to calculate an index in the array. Here is an example: ```swift hashTable["firstName"] = "Steve" The hashTable array: +--------------+ | 0: | +--------------+ | 1: | +--------------+ | 2: | +--------------+ | 3: firstName |---> Steve +--------------+ | 4: | +--------------+ ``` In this example, the key `"firstName"` maps to array index 3. Adding a value under a different key puts it at another array index: ```swift hashTable["hobbies"] = "Programming Swift" The hashTable array: +--------------+ | 0: | +--------------+ | 1: hobbies |---> Programming Swift +--------------+ | 2: | +--------------+ | 3: firstName |---> Steve +--------------+ | 4: | +--------------+ ``` The trick is how the hash table calculates those array indices. That is where the hashing comes in. When you write the following statement, ```swift hashTable["firstName"] = "Steve" ``` the hash table takes the key `"firstName"` and asks it for its `hashValue` property. Hence, keys must be `Hashable`. When you write `"firstName".hashValue`, it returns a big integer: -4799450059917011053. Likewise, `"hobbies".hashValue` has the hash value 4799450060928805186. (The values you see may vary.) These numbers are big to be used as indices into our array, and one of them is even negative! A common way to make these big numbers suitable is to first make the hash positive and then take the modulo with the array size. Our array has size 5, so the index for the `"firstName"` key becomes `abs(-4799450059917011053) % 5 = 3`. You can calculate that the array index for `"hobbies"` is 1. Using hashes in this manner is what makes the dictionary efficient: to find an element in the hash table, you must hash the key to get an array index and then look up the element in the underlying array. All these operations take a constant amount of time, so inserting, retrieving, and removing are all **O(1)**. > **Note:** It is difficult to predict where in the array your objects end up. Hence, dictionaries do not guarantee any particular order of the elements in the hash table. ## Avoiding collisions There is one problem: because we take the modulo of the hash value with the size of the array, it can happen that two or more keys get assigned the same array index. This is called a collision. One way to avoid collisions is to have a large array which reduces the likelihood of two keys mapping to the same index. Another trick is to use a prime number for the array size. However, collisions are bound to occur, so you need to find a way to handle them. Because our table is small, it is easy to show a collision. For example, the array index for the key `"lastName"` is also 3, but we do not want to overwrite the value that is already at this array index. A common way to handle collisions is to use chaining. The array looks as follows: ```swift buckets: +-----+ | 0 | +-----+ +----------------------------+ | 1 |---> | hobbies: Programming Swift | +-----+ +----------------------------+ | 2 | +-----+ +------------------+ +----------------+ | 3 |---> | firstName: Steve |---> | lastName: Jobs | +-----+ +------------------+ +----------------+ | 4 | +-----+ ``` With chaining, keys and their values are not stored directly in the array. Instead, each array element is a list of zero or more key/value pairs. The array elements are usually called the *buckets* and the lists are called the *chains*. Here we have 5 buckets, and two of these buckets have chains. The other three buckets are empty. If we write the following statement to retrieve an item from the hash table, ```swift let x = hashTable["lastName"] ``` it first hashes the key `"lastName"` to calculate the array index, which is 3. Since bucket 3 has a chain, we step through the list to find the value with the key `"lastName"`. This is done by comparing the keys using a string comparison. The hash table checks that the key belongs to the last item in the chain and returns the corresponding value, `"Jobs"`. Common ways to implement this chaining mechanism are to use a linked list or another array. Since the order of the items in the chain does not matter, you can think of it as a set instead of a list. (Now you can also imagine where the term "bucket" comes from; we just dump all the objects together into the bucket.) Chains should not become long because looking up items in the hash table would become a slow process. Ideally, we would have no chains at all, but in practice it is impossible to avoid collisions. You can improve the odds by giving the hash table enough buckets using high-quality hash functions. > **Note:** An alternative to chaining is "open addressing". The idea is this: if an array index is already taken, we put the element in the next unused bucket. This approach has its own upsides and downsides. ## The code Let's look at a basic implementation of a hash table in Swift. We will build it up step-by-step. ```swift public struct HashTable { private typealias Element = (key: Key, value: Value) private typealias Bucket = [Element] private var buckets: [Bucket] private(set) public var count = 0 public var isEmpty: Bool { return count == 0 } public init(capacity: Int) { assert(capacity > 0) buckets = Array(repeatElement([], count: capacity)) } ``` The `HashTable` is a generic container, and the two generic types are named `Key` (which must be `Hashable`) and `Value`. We also define two other types: `Element` is a key/value pair for using in a chain, and `Bucket` is an array of such `Elements`. The main array is named `buckets`. It has a fixed size, the so-called capacity, provided by the `init(capacity)` method. We are also keeping track of how many items have been added to the hash table using the `count` variable. An example of how to create a new hash table object: ```swift var hashTable = HashTable(capacity: 5) ``` The hash table does not do anything yet, so let's add the remaining functionality. First, add a helper method that calculates the array index for a given key: ```swift private func index(forKey key: Key) -> Int { return abs(key.hashValue % buckets.count) } ``` This performs the calculation you saw earlier: it takes the absolute value of the key's `hashValue` modulo the size of the buckets array. We have put this in a function of its own because it gets used in a few different places. There are four common things you will do with a hash table or dictionary: - insert a new element - look up an element - update an existing element - remove an element The syntax for these is: ```swift hashTable["firstName"] = "Steve" // insert let x = hashTable["firstName"] // lookup hashTable["firstName"] = "Tim" // update hashTable["firstName"] = nil // delete ``` We can do all these things with a `subscript` function: ```swift public subscript(key: Key) -> Value? { get { return value(forKey: key) } set { if let value = newValue { updateValue(value, forKey: key) } else { removeValue(forKey: key) } } } ``` This calls three helper functions to do the actual work. Let's take a look at `value(forKey:)`which retrieves an object from the hash table. ```swift public func value(forKey key: Key) -> Value? { let index = self.index(forKey: key) for element in buckets[index] { if element.key == key { return element.value } } return nil // key not in hash table } ``` First it calls `index(forKey:)` to convert the key into an array index. That gives us the bucket number, but this bucket may be used by more than one key if there were collisions. The `value(forKey:)` loops through the chain from that bucket and compares the keys one-by-one. If found, it returns the corresponding value, otherwise it returns `nil`. The code to insert a new element or update an existing element lives in `updateValue(_:forKey:)`. This is more complicated: ```swift public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { let index = self.index(forKey: key) // Do we already have this key in the bucket? for (i, element) in buckets[index].enumerated() { if element.key == key { let oldValue = element.value buckets[index][i].value = value return oldValue } } // This key isn't in the bucket yet; add it to the chain. buckets[index].append((key: key, value: value)) count += 1 return nil } ``` Again, the first step is to convert the key into an array index to find the bucket. Then we loop through the chain for that bucket. If we find the key in the chain, we must update it with the new value. If the key is not in the chain, we insert the new key/value pair to the end of the chain. As you can see, it is important to keep the chains short (by making the hash table large enough). Otherwise, you spend excessive time in these `for`...`in` loops and the performance of the hash table will no longer be **O(1)** but more like **O(n)**. Removing is similar in that again it loops through the chain: ```swift public mutating func removeValue(forKey key: Key) -> Value? { let index = self.index(forKey: key) // Find the element in the bucket's chain and remove it. for (i, element) in buckets[index].enumerated() { if element.key == key { buckets[index].remove(at: i) count -= 1 return element.value } } return nil // key not in hash table } ``` These are the basic functions of the hash table. They all work the same way: convert the key into an array index using its hash value, find the bucket, then loop through that bucket's chain and perform the desired operation. Try this stuff out in a playground. It should work just like a standard Swift `Dictionary`. ## Resizing the hash table This version of `HashTable` always uses an array of a fixed size or capacity. If you have many items to store in the hash table, for the capacity, choose a prime number greater than the maximum number of items. The *load factor* of a hash table is the percentage of the capacity that is currently used. If there are 3 items in a hash table with 5 buckets, then the load factor is `3/5 = 60%`. If the hash table is small, and the chains are long, the load factor can become greater than 1, that is not a good idea. If the load factor becomes high, greater than 75%, you can resize the hash table. Adding the code for this condition is left as an exercise for the reader. Keep in mind that making the buckets array larger will change the array indices that the keys map to! This requires you to insert all the elements again after resizing the array. ## Where to go from here? `HashTable` is quite basic. It might be efficient to integrate it with the Swift standard library by making it a `SequenceType`. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Hashed Heap/HashedHeap.swift ================================================ // Written by Alejandro Isaza. Adapted from heap implementation written by Kevin Randrup and Matthijs Hollemans. /// Heap with an index hash map (dictionary) to speed up lookups by value. /// /// A heap keeps elements ordered in a binary tree without the use of pointers. A hashed heap does that as well as /// having amortized constant lookups by value. This is used in the A* and other heuristic search algorithms to achieve /// optimal performance. public struct HashedHeap { /// The array that stores the heap's nodes. private(set) var elements = [T]() /// Hash mapping from elements to indices in the `elements` array. private(set) var indices = [T: Int]() /// Determines whether this is a max-heap (>) or min-heap (<). fileprivate var isOrderedBefore: (T, T) -> Bool /// Creates an empty hashed heap. /// /// The sort function determines whether this is a min-heap or max-heap. For integers, > makes a max-heap, < makes /// a min-heap. public init(sort: @escaping (T, T) -> Bool) { isOrderedBefore = sort } /// Creates a hashed heap from an array. /// /// The order of the array does not matter; the elements are inserted into the heap in the order determined by the /// sort function. /// /// - Complexity: O(n) public init(array: [T], sort: @escaping (T, T) -> Bool) { isOrderedBefore = sort build(from: array) } /// Converts an array to a max-heap or min-heap in a bottom-up manner. /// /// - Complexity: O(n) private mutating func build(from array: [T]) { elements = array for index in elements.indices { indices[elements[index]] = index } for i in stride(from: (elements.count/2 - 1), through: 0, by: -1) { shiftDown(i, heapSize: elements.count) } } /// Whether the heap is empty. public var isEmpty: Bool { return elements.isEmpty } /// The number of elements in the heap. public var count: Int { return elements.count } /// Accesses an element by its index. public subscript(index: Int) -> T { return elements[index] } /// Returns the index of the given element. /// /// This is the operation that a hashed heap optimizes in compassion with a normal heap. In a normal heap this /// would take O(n), but for the hashed heap this takes amortized constatn time. /// /// - Complexity: Amortized constant public func index(of element: T) -> Int? { return indices[element] } /// Returns the maximum value in the heap (for a max-heap) or the minimum value (for a min-heap). /// /// - Complexity: O(1) public func peek() -> T? { return elements.first } /// Adds a new value to the heap. /// /// This reorders the heap so that the max-heap or min-heap property still holds. /// /// - Complexity: O(log n) public mutating func insert(_ value: T) { elements.append(value) indices[value] = elements.count - 1 shiftUp(elements.count - 1) } /// Adds new values to the heap. public mutating func insert(_ sequence: S) where S.Iterator.Element == T { for value in sequence { insert(value) } } /// Replaces an element in the hash. /// /// In a max-heap, the new element should be larger than the old one; in a min-heap it should be smaller. public mutating func replace(_ value: T, at index: Int) { guard index < elements.count else { return } assert(isOrderedBefore(value, elements[index])) set(value, at: index) shiftUp(index) } /// Removes the root node from the heap. /// /// For a max-heap, this is the maximum value; for a min-heap it is the minimum value. /// /// - Complexity: O(log n) @discardableResult public mutating func remove() -> T? { if elements.isEmpty { return nil } else if elements.count == 1 { return removeLast() } else { // Use the last node to replace the first one, then fix the heap by // shifting this new first node into its proper position. let value = elements[0] set(removeLast(), at: 0) shiftDown() return value } } /// Removes an arbitrary node from the heap. /// /// You need to know the node's index, which may actually take O(n) steps to find. /// /// - Complexity: O(log n). public mutating func remove(at index: Int) -> T? { guard index < elements.count else { return nil } let size = elements.count - 1 if index != size { swapAt(index, size) shiftDown(index, heapSize: size) shiftUp(index) } return removeLast() } /// Removes all elements from the heap. public mutating func removeAll() { elements.removeAll() indices.removeAll() } /// Removes the last element from the heap. /// /// - Complexity: O(1) public mutating func removeLast() -> T { guard let value = elements.last else { preconditionFailure("Trying to remove element from empty heap") } indices[value] = nil return elements.removeLast() } /// Takes a child node and looks at its parents; if a parent is not larger (max-heap) or not smaller (min-heap) /// than the child, we exchange them. mutating func shiftUp(_ index: Int) { var childIndex = index let child = elements[childIndex] var parentIndex = self.parentIndex(of: childIndex) while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { set(elements[parentIndex], at: childIndex) childIndex = parentIndex parentIndex = self.parentIndex(of: childIndex) } set(child, at: childIndex) } mutating func shiftDown() { shiftDown(0, heapSize: elements.count) } /// Looks at a parent node and makes sure it is still larger (max-heap) or smaller (min-heap) than its childeren. mutating func shiftDown(_ index: Int, heapSize: Int) { var parentIndex = index while true { let leftChildIndex = self.leftChildIndex(of: parentIndex) let rightChildIndex = leftChildIndex + 1 // Figure out which comes first if we order them by the sort function: // the parent, the left child, or the right child. If the parent comes // first, we're done. If not, that element is out-of-place and we make // it "float down" the tree until the heap property is restored. var first = parentIndex if leftChildIndex < heapSize && isOrderedBefore(elements[leftChildIndex], elements[first]) { first = leftChildIndex } if rightChildIndex < heapSize && isOrderedBefore(elements[rightChildIndex], elements[first]) { first = rightChildIndex } if first == parentIndex { return } swapAt(parentIndex, first) parentIndex = first } } /// Replaces an element in the heap and updates the indices hash. private mutating func set(_ newValue: T, at index: Int) { indices[elements[index]] = nil elements[index] = newValue indices[newValue] = index } /// Swap two elements in the heap and update the indices hash. private mutating func swapAt(_ i: Int, _ j: Int) { elements.swapAt(i, j) indices[elements[i]] = i indices[elements[j]] = j } /// Returns the index of the parent of the element at index i. /// /// - Note: The element at index 0 is the root of the tree and has no parent. @inline(__always) func parentIndex(of index: Int) -> Int { return (index - 1) / 2 } /// Returns the index of the left child of the element at index i. /// /// - Note: this index can be greater than the heap size, in which case there is no left child. @inline(__always) func leftChildIndex(of index: Int) -> Int { return 2*index + 1 } /// Returns the index of the right child of the element at index i. /// /// - Note: this index can be greater than the heap size, in which case there is no right child. @inline(__always) func rightChildIndex(of index: Int) -> Int { return 2*index + 2 } } ================================================ FILE: Hashed Heap/README.markdown ================================================ # Hashed Heap A hashed heap is a [heap](../Heap/) with a hash map (also known as a dictionary) to speed up lookup of elements by value. This combination doesn't compromize on time performance but requires extra storage for the hash map. This is mainly used for heuristic search algorihms, in particular A*. ## The code See [HashedHeap.swift](HashedHeap.swift) for the implementation. See [Heap](../Heap/) for a detailed explanation of the basic heap implementation. ## See also [Heap on Wikipedia](https://en.wikipedia.org/wiki/Heap_%28data_structure%29) *Written for the Swift Algorithm Club by [Alejandro Isaza](https://github.com/aleph7)* ================================================ FILE: Hashed Heap/Tests/Hashed Heap Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3FC1C77A658003CECC7 /* HashedHeap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3FB1C77A658003CECC7 /* HashedHeap.swift */; }; 7B80C3FE1C77A65E003CECC7 /* HashedHeapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3FD1C77A65E003CECC7 /* HashedHeapTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Hashed Heap Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Hashed Heap Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3FB1C77A658003CECC7 /* HashedHeap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HashedHeap.swift; path = ../HashedHeap.swift; sourceTree = SOURCE_ROOT; }; 7B80C3FD1C77A65E003CECC7 /* HashedHeapTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HashedHeapTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Hashed Heap Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3FB1C77A658003CECC7 /* HashedHeap.swift */, 7B80C3FD1C77A65E003CECC7 /* HashedHeapTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Hashed Heap Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Hashed Heap Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Hashed Heap Tests"; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Hashed Heap Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0900; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Hashed Heap Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Hashed Heap Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3FE1C77A65E003CECC7 /* HashedHeapTests.swift in Sources */, 7B80C3FC1C77A658003CECC7 /* HashedHeap.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Hashed Heap Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Hashed Heap Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Hashed Heap/Tests/Hashed Heap Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Hashed Heap/Tests/Hashed Heap Tests.xcodeproj/xcshareddata/xcschemes/Hashed Heap Tests.xcscheme ================================================ ================================================ FILE: Hashed Heap/Tests/HashedHeapTests.swift ================================================ import Foundation import XCTest private struct Message: Hashable { let text: String let priority: Int var hashValue: Int { return text.hashValue } static func == (lhs: Message, rhs: Message) -> Bool { return lhs.text == rhs.text } static func < (m1: Message, m2: Message) -> Bool { return m1.priority < m2.priority } } class HashedHeapTest: XCTestCase { override func setUp() { super.setUp() // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testEmpty() { var queue = HashedHeap(sort: <) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.peek()) XCTAssertNil(queue.remove()) } func testOneElement() { var queue = HashedHeap(sort: <) queue.insert(Message(text: "hello", priority: 100)) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.peek()!.priority, 100) let result = queue.remove() XCTAssertEqual(result!.priority, 100) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.peek()) } func testTwoElementsInOrder() { var queue = HashedHeap(sort: <) queue.insert(Message(text: "hello", priority: 100)) queue.insert(Message(text: "world", priority: 200)) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 2) XCTAssertEqual(queue.peek()!.priority, 100) let result1 = queue.remove() XCTAssertEqual(result1!.priority, 100) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.peek()!.priority, 200) let result2 = queue.remove() XCTAssertEqual(result2!.priority, 200) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.peek()) } func testTwoElementsOutOfOrder() { var queue = HashedHeap(sort: <) queue.insert(Message(text: "world", priority: 200)) queue.insert(Message(text: "hello", priority: 100)) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 2) XCTAssertEqual(queue.peek()!.priority, 100) let result1 = queue.remove() XCTAssertEqual(result1!.priority, 100) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.peek()!.priority, 200) let result2 = queue.remove() XCTAssertEqual(result2!.priority, 200) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.peek()) } } ================================================ FILE: Hashed Heap/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: HaversineDistance/HaversineDistance.playground/Contents.swift ================================================ import UIKit func haversineDistance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double { let haversin = { (angle: Double) -> Double in return (1 - cos(angle))/2 } let ahaversin = { (angle: Double) -> Double in return 2*asin(sqrt(angle)) } // Converts from degrees to radians let dToR = { (angle: Double) -> Double in return (angle / 360) * 2 * .pi } let lat1 = dToR(la1) let lon1 = dToR(lo1) let lat2 = dToR(la2) let lon2 = dToR(lo2) return radius * ahaversin(haversin(lat2 - lat1) + cos(lat1) * cos(lat2) * haversin(lon2 - lon1)) } let amsterdam = (52.3702, 4.8952) let newYork = (40.7128, -74.0059) // Google says it's 5857 km so our result is only off by 2km which could be due to all kinds of things, not sure how google calculates the distance or which latitude and longitude google uses to calculate the distance. haversineDistance(la1: amsterdam.0, lo1: amsterdam.1, la2: newYork.0, lo2: newYork.1) ================================================ FILE: HaversineDistance/HaversineDistance.playground/contents.xcplayground ================================================ ================================================ FILE: HaversineDistance/HaversineDistance.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: HaversineDistance/README.md ================================================ # Haversine Distance Calculates the distance on a sphere between two points given in latitude and longitude using the haversine formula. The haversine formula can be found on [Wikipedia](https://en.wikipedia.org/wiki/Haversine_formula) The Haversine Distance is implemented as a function as a class would be kind of overkill. `haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double` - `la1` is the latitude of point 1 in degrees. - `lo1` is the longitude of point 1 in degrees. - `la2` is the latitude of point 2 in degrees. - `lo2` is the longitude of point 2 in degrees. - `radius` is the radius of the sphere considered in meters, which defaults to the mean radius of the earth (from [WolframAlpha](http://www.wolframalpha.com/input/?i=earth+radius)). The function contains 3 closures in order to make the code more readable and comparable to the Haversine formula given by the Wikipedia page mentioned above. 1. `haversine` implements the haversine, a trigonometric function. 2. `ahaversine` the inverse function of the haversine. 3. `dToR` a closure converting degrees to radians. The result of `haversineDistance` is returned in meters. *Written for Swift Algorithm Club by Jaap Wijnen.* ================================================ FILE: Heap/Heap.swift ================================================ // // Heap.swift // Written for the Swift Algorithm Club by Kevin Randrup and Matthijs Hollemans // public struct Heap { /** The array that stores the heap's nodes. */ var nodes = [T]() /** * Determines how to compare two nodes in the heap. * Use '>' for a max-heap or '<' for a min-heap, * or provide a comparing method if the heap is made * of custom elements, for example tuples. */ private var orderCriteria: (T, T) -> Bool /** * Creates an empty heap. * The sort function determines whether this is a min-heap or max-heap. * For comparable data types, > makes a max-heap, < makes a min-heap. */ public init(sort: @escaping (T, T) -> Bool) { self.orderCriteria = sort } /** * Creates a heap from an array. The order of the array does not matter; * the elements are inserted into the heap in the order determined by the * sort function. For comparable data types, '>' makes a max-heap, * '<' makes a min-heap. */ public init(array: [T], sort: @escaping (T, T) -> Bool) { self.orderCriteria = sort configureHeap(from: array) } /** * Configures the max-heap or min-heap from an array, in a bottom-up manner. * Performance: This runs pretty much in O(n). */ private mutating func configureHeap(from array: [T]) { nodes = array for i in stride(from: (nodes.count/2-1), through: 0, by: -1) { shiftDown(i) } } public var isEmpty: Bool { return nodes.isEmpty } public var count: Int { return nodes.count } /** * Returns the index of the parent of the element at index i. * The element at index 0 is the root of the tree and has no parent. */ @inline(__always) internal func parentIndex(ofIndex i: Int) -> Int { return (i - 1) / 2 } /** * Returns the index of the left child of the element at index i. * Note that this index can be greater than the heap size, in which case * there is no left child. */ @inline(__always) internal func leftChildIndex(ofIndex i: Int) -> Int { return 2*i + 1 } /** * Returns the index of the right child of the element at index i. * Note that this index can be greater than the heap size, in which case * there is no right child. */ @inline(__always) internal func rightChildIndex(ofIndex i: Int) -> Int { return 2*i + 2 } /** * Returns the maximum value in the heap (for a max-heap) or the minimum * value (for a min-heap). */ public func peek() -> T? { return nodes.first } /** * Adds a new value to the heap. This reorders the heap so that the max-heap * or min-heap property still holds. Performance: O(log n). */ public mutating func insert(_ value: T) { nodes.append(value) shiftUp(nodes.count - 1) } /** * Adds a sequence of values to the heap. This reorders the heap so that * the max-heap or min-heap property still holds. Performance: O(log n). */ public mutating func insert(_ sequence: S) where S.Iterator.Element == T { for value in sequence { insert(value) } } /** * Allows you to change an element. This reorders the heap so that * the max-heap or min-heap property still holds. */ public mutating func replace(index i: Int, value: T) { guard i < nodes.count else { return } remove(at: i) insert(value) } /** * Removes the root node from the heap. For a max-heap, this is the maximum * value; for a min-heap it is the minimum value. Performance: O(log n). */ @discardableResult public mutating func remove() -> T? { guard !nodes.isEmpty else { return nil } if nodes.count == 1 { return nodes.removeLast() } else { // Use the last node to replace the first one, then fix the heap by // shifting this new first node into its proper position. let value = nodes[0] nodes[0] = nodes.removeLast() shiftDown(0) return value } } /** * Removes an arbitrary node from the heap. Performance: O(log n). * Note that you need to know the node's index. */ @discardableResult public mutating func remove(at index: Int) -> T? { guard index < nodes.count else { return nil } let size = nodes.count - 1 if index != size { nodes.swapAt(index, size) shiftDown(from: index, until: size) shiftUp(index) } return nodes.removeLast() } /** * Takes a child node and looks at its parents; if a parent is not larger * (max-heap) or not smaller (min-heap) than the child, we exchange them. */ internal mutating func shiftUp(_ index: Int) { var childIndex = index let child = nodes[childIndex] var parentIndex = self.parentIndex(ofIndex: childIndex) while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) { nodes[childIndex] = nodes[parentIndex] childIndex = parentIndex parentIndex = self.parentIndex(ofIndex: childIndex) } nodes[childIndex] = child } /** * Looks at a parent node and makes sure it is still larger (max-heap) or * smaller (min-heap) than its childeren. */ internal mutating func shiftDown(from index: Int, until endIndex: Int) { let leftChildIndex = self.leftChildIndex(ofIndex: index) let rightChildIndex = leftChildIndex + 1 // Figure out which comes first if we order them by the sort function: // the parent, the left child, or the right child. If the parent comes // first, we're done. If not, that element is out-of-place and we make // it "float down" the tree until the heap property is restored. var first = index if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) { first = leftChildIndex } if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) { first = rightChildIndex } if first == index { return } nodes.swapAt(index, first) shiftDown(from: first, until: endIndex) } internal mutating func shiftDown(_ index: Int) { shiftDown(from: index, until: nodes.count) } } // MARK: - Searching extension Heap where T: Equatable { /** Get the index of a node in the heap. Performance: O(n). */ public func index(of node: T) -> Int? { return nodes.index(where: { $0 == node }) } /** Removes the first occurrence of a node from the heap. Performance: O(n). */ @discardableResult public mutating func remove(node: T) -> T? { if let index = index(of: node) { return remove(at: index) } return nil } } ================================================ FILE: Heap/README.markdown ================================================ # Heap > This topic has been tutorialized [here](https://www.raywenderlich.com/160631/swift-algorithm-club-heap-and-priority-queue-data-structure) A heap is a [binary tree](../Binary%20Tree/) inside an array, so it does not use parent/child pointers. A heap is sorted based on the "heap property" that determines the order of the nodes in the tree. Common uses for heap: - To build [priority queues](../Priority%20Queue/). - To support [heap sorts](../Heap%20Sort/). - To compute the minimum (or maximum) element of a collection quickly. - To impress your non-programmer friends. ## The heap property There are two kinds of heaps: a *max-heap* and a *min-heap* which are different by the order in which they store the tree nodes. In a max-heap, parent nodes have a greater value than each of their children. In a min-heap, every parent node has a smaller value than its child nodes. This is called the "heap property", and it is true for every single node in the tree. An example: ![A max-heap](Images/Heap1.png) This is a max-heap because every parent node is greater than its children. `(10)` is greater than `(7)` and `(2)`. `(7)` is greater than `(5)` and `(1)`. As a result of this heap property, a max-heap always stores its largest item at the root of the tree. For a min-heap, the root is always the smallest item in the tree. The heap property is useful because heaps are often used as a [priority queue](../Priority%20Queue/) to access the "most important" element quickly. > **Note:** The root of the heap has the maximum or minimum element, but the sort order of other elements are not predictable. For example, the maximum element is always at index 0 in a max-heap, but the minimum element isn’t necessarily the last one. -- the only guarantee you have is that it is one of the leaf nodes, but not which one. ## How does a heap compare to regular trees? A heap is not a replacement for a binary search tree, and there are similarities and differences between them. Here are some main differences: **Order of the nodes.** In a [binary search tree (BST)](../Binary%20Search%20Tree/), the left child must be smaller than its parent, and the right child must be greater. This is not true for a heap. In a max-heap both children must be smaller than the parent, while in a min-heap they both must be greater. **Memory.** Traditional trees take up more memory than just the data they store. You need to allocate additional storage for the node objects and pointers to the left/right child nodes. A heap only uses a plain array for storage and uses no pointers. **Balancing.** A binary search tree must be "balanced" so that most operations have **O(log n)** performance. You can either insert and delete your data in a random order or use something like an [AVL tree](../AVL%20Tree/) or [red-black tree](../Red-Black%20Tree/), but with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. **Searching.** Whereas searching is fast in a binary tree, it is slow in a heap. Searching isn't a top priority in a heap since the purpose of a heap is to put the largest (or smallest) node at the front and to allow relatively fast inserts and deletes. ## The tree inside an array An array may seem like an odd way to implement a tree-like structure, but it is efficient in both time and space. This is how we are going to store the tree from the above example: [ 10, 7, 2, 5, 1 ] That's all there is to it! We don't need any more storage than just this simple array. So how do we know which nodes are the parents and which are the children if we are not allowed to use any pointers? Good question! There is a well-defined relationship between the array index of a tree node and the array indices of its parent and children. If `i` is the index of a node, then the following formulas give the array indices of its parent and child nodes: parent(i) = floor((i - 1)/2) left(i) = 2i + 1 right(i) = 2i + 2 Note that `right(i)` is simply `left(i) + 1`. The left and right nodes are always stored right next to each other. Let's use these formulas on the example. Fill in the array index and we should get the positions of the parent and child nodes in the array: | Node | Array index (`i`) | Parent index | Left child | Right child | |------|-------------|--------------|------------|-------------| | 10 | 0 | -1 | 1 | 2 | | 7 | 1 | 0 | 3 | 4 | | 2 | 2 | 0 | 5 | 6 | | 5 | 3 | 1 | 7 | 8 | | 1 | 4 | 1 | 9 | 10 | Verify for yourself that these array indices indeed correspond to the picture of the tree. > **Note:** The root node `(10)` does not have a parent because `-1` is not a valid array index. Likewise, nodes `(2)`, `(5)`, and `(1)` do not have children because those indices are greater than the array size, so we always have to make sure the indices we calculate are actually valid before we use them. Recall that in a max-heap, the parent's value is always greater than (or equal to) the values of its children. This means the following must be true for all array indices `i`: ```swift array[parent(i)] >= array[i] ``` Verify that this heap property holds for the array from the example heap. As you can see, these equations allow us to find the parent or child index for any node without the need for pointers. It is more complicated than just dereferencing a pointer, but that is the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. It is important to understand this relationship between array index and position in the tree. Here is a larger heap which has 15 nodes divided over four levels: ![Large heap](Images/LargeHeap.png) The numbers in this picture are not the values of the nodes but the array indices that store the nodes! Here is the array indices correspond to the different levels of the tree: ![The heap array](Images/Array.png) For the formulas to work, parent nodes must appear before child nodes in the array. You can see that in the above picture. Note that this scheme has limitations. You can do the following with a regular binary tree but not with a heap: ![Impossible with a heap](Images/RegularTree.png) You can not start a new level unless the current lowest level is completely full, so heaps always have this kind of shape: ![The shape of a heap](Images/HeapShape.png) > **Note:** You *could* emulate a regular binary tree with a heap, but it would be a waste of space, and you would need to mark array indices as being empty. Pop quiz! Let's say we have the array: [ 10, 14, 25, 33, 81, 82, 99 ] Is this a valid heap? The answer is yes! A sorted array from low-to-high is a valid min-heap. We can draw this heap as follows: ![A sorted array is a valid heap](Images/SortedArray.png) The heap property holds for each node because a parent is always smaller than its children. (Verify for yourself that an array sorted from high-to-low is always a valid max-heap.) > **Note:** But not every min-heap is necessarily a sorted array! It only works one way. To turn a heap back into a sorted array, you need to use [heap sort](../Heap%20Sort/). ## More math! In case you are curious, here are a few more formulas that describe certain properties of a heap. You do not need to know these by heart, but they come in handy sometimes. Feel free to skip this section! The *height* of a tree is defined as the number of steps it takes to go from the root node to the lowest leaf node, or more formally: the height is the maximum number of edges between the nodes. A heap of height *h* has *h + 1* levels. This heap has height 3, so it has 4 levels: ![Large heap](Images/LargeHeap.png) A heap with *n* nodes has height *h = floor(log2(n))*. This is because we always fill up the lowest level completely before we add a new level. The example has 15 nodes, so the height is `floor(log2(15)) = floor(3.91) = 3`. If the lowest level is completely full, then that level contains *2^h* nodes. The rest of the tree above it contains *2^h - 1* nodes. Fill in the numbers from the example: the lowest level has 8 nodes, which indeed is `2^3 = 8`. The first three levels contain a total of 7 nodes, i.e. `2^3 - 1 = 8 - 1 = 7`. The total number of nodes *n* in the entire heap is therefore *2^(h+1) - 1*. In the example, `2^4 - 1 = 16 - 1 = 15`. There are at most *ceil(n/2^(h+1))* nodes of height *h* in an *n*-element heap. The leaf nodes are always located at array indices *floor(n/2)* to *n-1*. We will make use of this fact to quickly build up the heap from an array. Verify this for the example if you don't believe it. ;-) Just a few math facts to brighten your day. ## What can you do with a heap? There are two primitive operations necessary to make sure the heap is a valid max-heap or min-heap after you insert or remove an element: - `shiftUp()`: If the element is greater (max-heap) or smaller (min-heap) than its parent, it needs to be swapped with the parent. This makes it move up the tree. - `shiftDown()`. If the element is smaller (max-heap) or greater (min-heap) than its children, it needs to move down the tree. This operation is also called "heapify". Shifting up or down is a recursive procedure that takes **O(log n)** time. Here are other operations that are built on primitive operations: - `insert(value)`: Adds the new element to the end of the heap and then uses `shiftUp()` to fix the heap. - `remove()`: Removes and returns the maximum value (max-heap) or the minimum value (min-heap). To fill up the hole left by removing the element, the very last element is moved to the root position and then `shiftDown()` fixes up the heap. (This is sometimes called "extract min" or "extract max".) - `removeAtIndex(index)`: Just like `remove()` with the exception that it allows you to remove any item from the heap, not just the root. This calls both `shiftDown()`, in case the new element is out-of-order with its children, and `shiftUp()`, in case the element is out-of-order with its parents. - `replace(index, value)`: Assigns a smaller (min-heap) or larger (max-heap) value to a node. Because this invalidates the heap property, it uses `shiftUp()` to patch things up. (Also called "decrease key" and "increase key".) All of the above take time **O(log n)** because shifting up or down is expensive. There are also a few operations that take more time: - `search(value)`. Heaps are not built for efficient searches, but the `replace()` and `removeAtIndex()` operations require the array index of the node, so you need to find that index. Time: **O(n)**. - `buildHeap(array)`: Converts an (unsorted) array into a heap by repeatedly calling `insert()`. If you are smart about this, it can be done in **O(n)** time. - [Heap sort](../Heap%20Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n log n).** The heap also has a `peek()` function that returns the maximum (max-heap) or minimum (min-heap) element, without removing it from the heap. Time: **O(1)**. > **Note:** By far the most common things you will do with a heap are inserting new values with `insert()` and removing the maximum or minimum value with `remove()`. Both take **O(log n)** time. The other operations exist to support more advanced usage, such as building a priority queue where the "importance" of items can change after they have been added to the queue. ## Inserting into the heap Let's go through an example of insertion to see in details how this works. We will insert the value `16` into this heap: ![The heap before insertion](Images/Heap1.png) The array for this heap is `[ 10, 7, 2, 5, 1 ]`. The first step when inserting a new item is to append it to the end of the array. The array becomes: [ 10, 7, 2, 5, 1, 16 ] This corresponds to the following tree: ![The heap before insertion](Images/Insert1.png) The `(16)` was added to the first available space on the last row. Unfortunately, the heap property is no longer satisfied because `(2)` is above `(16)`, and we want higher numbers above lower numbers. (This is a max-heap.) To restore the heap property, we swap `(16)` and `(2)`. ![The heap before insertion](Images/Insert2.png) We are not done yet because `(10)` is also smaller than `(16)`. We keep swapping our inserted value with its parent, until the parent is larger or we reach the top of the tree. This is called **shift-up** or **sifting** and is done after every insertion. It makes a number that is too large or too small "float up" the tree. Finally, we get: ![The heap before insertion](Images/Insert3.png) And now every parent is greater than its children again. The time required for shifting up is proportional to the height of the tree, so it takes **O(log n)** time. (The time it takes to append the node to the end of the array is only **O(1)**, so that does not slow it down.) ## Removing the root Let's remove `(10)` from this tree: ![The heap before removal](Images/Heap1.png) What happens to the empty spot at the top? ![The root is gone](Images/Remove1.png) When inserting, we put the new value at the end of the array. Here, we do the opposite: we take the last object we have, stick it up on top of the tree, and restore the heap property. ![The last node goes to the root](Images/Remove2.png) Let's look at how to **shift-down** `(1)`. To maintain the heap property for this max-heap, we want to the highest number of top. We have two candidates for swapping places with: `(7)` and `(2)`. We choose the highest number between these three nodes to be on top. That is `(7)`, so swapping `(1)` and `(7)` gives us the following tree. ![The last node goes to the root](Images/Remove3.png) Keep shifting down until the node does not have any children or it is larger than both its children. For our heap, we only need one more swap to restore the heap property: ![The last node goes to the root](Images/Remove4.png) The time required for shifting all the way down is proportional to the height of the tree which takes **O(log n)** time. > **Note:** `shiftUp()` and `shiftDown()` can only fix one out-of-place element at a time. If there are multiple elements in the wrong place, you need to call these functions once for each of those elements. ## Removing any node The vast majority of the time you will be removing the object at the root of the heap because that is what heaps are designed for. However, it can be useful to remove an arbitrary element. This is a general version of `remove()` and may involve either `shiftDown()` or `shiftUp()`. Let's take the example tree again and remove `(7)`: ![The heap before removal](Images/Heap1.png) As a reminder, the array is: [ 10, 7, 2, 5, 1 ] As you know, removing an element could potentially invalidate the max-heap or min-heap property. To fix this, we swap the node that we are removing with the last element: [ 10, 1, 2, 5, 7 ] The last element is the one that we will return; we will call `removeLast()` to remove it from the heap. The `(1)` is now out-of-order because it is smaller than its child, `(5)` but sits higher in the tree. We call `shiftDown()` to repair this. However, shifting down is not the only situation we need to handle. It may also happen that the new element must be shifted up. Consider what happens if you remove `(5)` from the following heap: ![We need to shift up](Images/Remove5.png) Now `(5)` gets swapped with `(8)`. Because `(8)` is larger than its parent, we need to call `shiftUp()`. ## Creating a heap from an array It can be convenient to convert an array into a heap. This just shuffles the array elements around until the heap property is satisfied. In code it would look like this: ```swift private mutating func buildHeap(fromArray array: [T]) { for value in array { insert(value) } } ``` We simply call `insert()` for each of the values in the array. Simple enough but not very efficient. This takes **O(n log n)** time in total because there are **n** elements and each insertion takes **log n** time. If you didn't gloss over the math section, you'd have seen that for any heap the elements at array indices *n/2* to *n-1* are the leaves of the tree. We can simply skip those leaves. We only have to process the other nodes, since they are parents with one or more children and therefore may be in the wrong order. In code: ```swift private mutating func buildHeap(fromArray array: [T]) { elements = array for i in stride(from: (nodes.count/2-1), through: 0, by: -1) { shiftDown(index: i, heapSize: elements.count) } } ``` Here, `elements` is the heap's own array. We walk backwards through this array, starting at the first non-leaf node, and call `shiftDown()`. This simple loop puts these nodes, as well as the leaves that we skipped, in the correct order. This is known as Floyd's algorithm and only takes **O(n)** time. Win! ## Searching the heap Heaps are not made for fast searches, but if you want to remove an arbitrary element using `removeAtIndex()` or change the value of an element with `replace()`, then you need to obtain the index of that element. Searching is one way to do this, but it is slow. In a [binary search tree](../Binary%20Search%20Tree/), depending on the order of the nodes, a fast search can be guaranteed. Since a heap orders its nodes differently, a binary search will not work, and you need to check every node in the tree. Let's take our example heap again: ![The heap](Images/Heap1.png) If we want to search for the index of node `(1)`, we could just step through the array `[ 10, 7, 2, 5, 1 ]` with a linear search. Even though the heap property was not conceived with searching in mind, we can still take advantage of it. We know that in a max-heap a parent node is always larger than its children, so we can ignore those children (and their children, and so on...) if the parent is already smaller than the value we are looking for. Let's say we want to see if the heap contains the value `8` (it doesn't). We start at the root `(10)`. This is not what we are looking for, so we recursively look at its left and right child. The left child is `(7)`. That is also not what we want, but since this is a max-heap, we know there is no point in looking at the children of `(7)`. They will always be smaller than `7` and are therefore never equal to `8`; likewise, for the right child, `(2)`. Despite this small optimization, searching is still an **O(n)** operation. > **Note:** There is a way to turn lookups into a **O(1)** operation by keeping an additional dictionary that maps node values to indices. This may be worth doing if you often need to call `replace()` to change the "priority" of objects in a [priority queue](../Priority%20Queue/) that's built on a heap. ## The code See [Heap.swift](Heap.swift) for the implementation of these concepts in Swift. Most of the code is quite straightforward. The only tricky bits are in `shiftUp()` and `shiftDown()`. You have seen that there are two types of heaps: a max-heap and a min-heap. The only difference between them is in how they order their nodes: largest value first or smallest value first. Rather than create two different versions, `MaxHeap` and `MinHeap`, there is just one `Heap` object and it takes an `isOrderedBefore` closure. This closure contains the logic that determines the order of two values. You have probably seen this before because it is also how Swift's `sort()` works. To make a max-heap of integers, you write: ```swift var maxHeap = Heap(sort: >) ``` And to create a min-heap you write: ```swift var minHeap = Heap(sort: <) ``` I just wanted to point this out, because where most heap implementations use the `<` and `>` operators to compare values, this one uses the `isOrderedBefore()` closure. ## See also [Heap on Wikipedia](https://en.wikipedia.org/wiki/Heap_%28data_structure%29) *Written for the Swift Algorithm Club by [Kevin Randrup](http://www.github.com/kevinrandrup) and Matthijs Hollemans* ================================================ FILE: Heap/Tests/HeapTests.swift ================================================ // // HeapTests.swift // Written for the Swift Algorithm Club by Kevin Randrup and Matthijs Hollemans // import XCTest class HeapTests: XCTestCase { fileprivate func verifyMaxHeap(_ h: Heap) -> Bool { for i in 0.. 0 && h.nodes[parent] < h.nodes[i] { return false } } return true } fileprivate func verifyMinHeap(_ h: Heap) -> Bool { for i in 0.. h.nodes[left] { return false } if right < h.count && h.nodes[i] > h.nodes[right] { return false } if i > 0 && h.nodes[parent] > h.nodes[i] { return false } } return true } fileprivate func isPermutation(_ array1: [Int], _ array2: [Int]) -> Bool { var a1 = array1 var a2 = array2 if a1.count != a2.count { return false } while a1.count > 0 { if let i = a2.index(of: a1[0]) { a1.remove(at: 0) a2.remove(at: i) } else { return false } } return a2.count == 0 } func testEmptyHeap() { var heap = Heap(sort: <) XCTAssertTrue(heap.isEmpty) XCTAssertEqual(heap.count, 0) XCTAssertNil(heap.peek()) XCTAssertNil(heap.remove()) } func testIsEmpty() { var heap = Heap(sort: >) XCTAssertTrue(heap.isEmpty) heap.insert(1) XCTAssertFalse(heap.isEmpty) heap.remove() XCTAssertTrue(heap.isEmpty) } func testCount() { var heap = Heap(sort: >) XCTAssertEqual(0, heap.count) heap.insert(1) XCTAssertEqual(1, heap.count) } func testMaxHeapOneElement() { let heap = Heap(array: [10], sort: >) XCTAssertTrue(verifyMaxHeap(heap)) XCTAssertTrue(verifyMinHeap(heap)) XCTAssertFalse(heap.isEmpty) XCTAssertEqual(heap.count, 1) XCTAssertEqual(heap.peek()!, 10) } func testCreateMaxHeap() { let h1 = Heap(array: [1, 2, 3, 4, 5, 6, 7], sort: >) XCTAssertTrue(verifyMaxHeap(h1)) XCTAssertFalse(verifyMinHeap(h1)) XCTAssertEqual(h1.nodes, [7, 5, 6, 4, 2, 1, 3]) XCTAssertFalse(h1.isEmpty) XCTAssertEqual(h1.count, 7) XCTAssertEqual(h1.peek()!, 7) let h2 = Heap(array: [7, 6, 5, 4, 3, 2, 1], sort: >) XCTAssertTrue(verifyMaxHeap(h2)) XCTAssertFalse(verifyMinHeap(h2)) XCTAssertEqual(h2.nodes, [7, 6, 5, 4, 3, 2, 1]) XCTAssertFalse(h2.isEmpty) XCTAssertEqual(h2.count, 7) XCTAssertEqual(h2.peek()!, 7) let h3 = Heap(array: [4, 1, 3, 2, 16, 9, 10, 14, 8, 7], sort: >) XCTAssertTrue(verifyMaxHeap(h3)) XCTAssertFalse(verifyMinHeap(h3)) XCTAssertEqual(h3.nodes, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) XCTAssertFalse(h3.isEmpty) XCTAssertEqual(h3.count, 10) XCTAssertEqual(h3.peek()!, 16) let h4 = Heap(array: [27, 17, 3, 16, 13, 10, 1, 5, 7, 12, 4, 8, 9, 0], sort: >) XCTAssertTrue(verifyMaxHeap(h4)) XCTAssertFalse(verifyMinHeap(h4)) XCTAssertEqual(h4.nodes, [27, 17, 10, 16, 13, 9, 1, 5, 7, 12, 4, 8, 3, 0]) XCTAssertFalse(h4.isEmpty) XCTAssertEqual(h4.count, 14) XCTAssertEqual(h4.peek()!, 27) } func testCreateMinHeap() { let h1 = Heap(array: [1, 2, 3, 4, 5, 6, 7], sort: <) XCTAssertTrue(verifyMinHeap(h1)) XCTAssertFalse(verifyMaxHeap(h1)) XCTAssertEqual(h1.nodes, [1, 2, 3, 4, 5, 6, 7]) XCTAssertFalse(h1.isEmpty) XCTAssertEqual(h1.count, 7) XCTAssertEqual(h1.peek()!, 1) let h2 = Heap(array: [7, 6, 5, 4, 3, 2, 1], sort: <) XCTAssertTrue(verifyMinHeap(h2)) XCTAssertFalse(verifyMaxHeap(h2)) XCTAssertEqual(h2.nodes, [1, 3, 2, 4, 6, 7, 5]) XCTAssertFalse(h2.isEmpty) XCTAssertEqual(h2.count, 7) XCTAssertEqual(h2.peek()!, 1) let h3 = Heap(array: [4, 1, 3, 2, 16, 9, 10, 14, 8, 7], sort: <) XCTAssertTrue(verifyMinHeap(h3)) XCTAssertFalse(verifyMaxHeap(h3)) XCTAssertEqual(h3.nodes, [1, 2, 3, 4, 7, 9, 10, 14, 8, 16]) XCTAssertFalse(h3.isEmpty) XCTAssertEqual(h3.count, 10) XCTAssertEqual(h3.peek()!, 1) let h4 = Heap(array: [27, 17, 3, 16, 13, 10, 1, 5, 7, 12, 4, 8, 9, 0], sort: <) XCTAssertTrue(verifyMinHeap(h4)) XCTAssertFalse(verifyMaxHeap(h4)) XCTAssertEqual(h4.nodes, [0, 4, 1, 5, 12, 8, 3, 16, 7, 17, 13, 10, 9, 27]) XCTAssertFalse(h4.isEmpty) XCTAssertEqual(h4.count, 14) XCTAssertEqual(h4.peek()!, 0) } func testCreateMaxHeapEqualnodes() { let heap = Heap(array: [1, 1, 1, 1, 1], sort: >) XCTAssertTrue(verifyMaxHeap(heap)) XCTAssertTrue(verifyMinHeap(heap)) XCTAssertEqual(heap.nodes, [1, 1, 1, 1, 1]) } func testCreateMinHeapEqualnodes() { let heap = Heap(array: [1, 1, 1, 1, 1], sort: <) XCTAssertTrue(verifyMinHeap(heap)) XCTAssertTrue(verifyMaxHeap(heap)) XCTAssertEqual(heap.nodes, [1, 1, 1, 1, 1]) } fileprivate func randomArray(_ n: Int) -> [Int] { var a = [Int]() for _ in 0..) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertFalse(h.isEmpty) XCTAssertEqual(h.count, n) XCTAssertTrue(isPermutation(a, h.nodes)) } } func testCreateRandomMinHeap() { for n in 1...40 { let a = randomArray(n) let h = Heap(array: a, sort: <) XCTAssertTrue(verifyMinHeap(h)) XCTAssertFalse(h.isEmpty) XCTAssertEqual(h.count, n) XCTAssertTrue(isPermutation(a, h.nodes)) } } func testRemoving() { var h = Heap(array: [100, 50, 70, 10, 20, 60, 65], sort: >) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [100, 50, 70, 10, 20, 60, 65]) //test index out of bounds let v = h.remove(at: 10) XCTAssertEqual(v, nil) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [100, 50, 70, 10, 20, 60, 65]) let v1 = h.remove(at: 5) XCTAssertEqual(v1, 60) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [100, 50, 70, 10, 20, 65]) let v2 = h.remove(at: 4) XCTAssertEqual(v2, 20) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [100, 65, 70, 10, 50]) let v3 = h.remove(at: 4) XCTAssertEqual(v3, 50) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [100, 65, 70, 10]) let v4 = h.remove(at: 0) XCTAssertEqual(v4, 100) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [70, 65, 10]) XCTAssertEqual(h.peek()!, 70) let v5 = h.remove() XCTAssertEqual(v5, 70) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [65, 10]) XCTAssertEqual(h.peek()!, 65) let v6 = h.remove() XCTAssertEqual(v6, 65) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [10]) XCTAssertEqual(h.peek()!, 10) let v7 = h.remove() XCTAssertEqual(v7, 10) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, []) XCTAssertNil(h.peek()) } func testRemoveEmpty() { var heap = Heap(sort: >) let removed = heap.remove() XCTAssertNil(removed) } func testRemoveRoot() { var h = Heap(array: [15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1], sort: >) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1]) XCTAssertEqual(h.peek()!, 15) let v = h.remove() XCTAssertEqual(v, 15) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [13, 12, 9, 5, 6, 8, 7, 4, 0, 1, 2]) } func testRemoveRandomItems() { for n in 1...40 { var a = randomArray(n) var h = Heap(array: a, sort: >) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertTrue(isPermutation(a, h.nodes)) let m = (n + 1)/2 for k in 1...m { let i = Int(arc4random_uniform(UInt32(n - k + 1))) let v = h.remove(at: i)! let j = a.index(of: v)! a.remove(at: j) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.count, a.count) XCTAssertEqual(h.count, n - k) XCTAssertTrue(isPermutation(a, h.nodes)) } } } func testInsert() { var h = Heap(array: [15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1], sort: >) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1]) h.insert(10) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.nodes, [15, 13, 10, 5, 12, 9, 7, 4, 0, 6, 2, 1, 8]) } func testInsertArrayAndRemove() { var heap = Heap(sort: >) heap.insert([1, 3, 2, 7, 5, 9]) XCTAssertEqual(heap.nodes, [9, 5, 7, 1, 3, 2]) XCTAssertEqual(9, heap.remove()) XCTAssertEqual(7, heap.remove()) XCTAssertEqual(5, heap.remove()) XCTAssertEqual(3, heap.remove()) XCTAssertEqual(2, heap.remove()) XCTAssertEqual(1, heap.remove()) XCTAssertNil(heap.remove()) } func testReplace() { var h = Heap(array: [16, 14, 10, 8, 7, 9, 3, 2, 4, 1], sort: >) XCTAssertTrue(verifyMaxHeap(h)) h.replace(index: 5, value: 13) XCTAssertTrue(verifyMaxHeap(h)) //test index out of bounds h.replace(index: 20, value: 2) XCTAssertTrue(verifyMaxHeap(h)) } } ================================================ FILE: Heap/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Heap/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 51; objects = { /* Begin PBXBuildFile section */ 7B80C3DC1C77A38C003CECC7 /* HeapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3DB1C77A38C003CECC7 /* HeapTests.swift */; }; 7B80C3DE1C77A393003CECC7 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3DD1C77A393003CECC7 /* Heap.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3DB1C77A38C003CECC7 /* HeapTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeapTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3DD1C77A393003CECC7 /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../Heap.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3DD1C77A393003CECC7 /* Heap.swift */, 7B80C3DB1C77A38C003CECC7 /* HeapTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1010; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 1010; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 10.0"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3DC1C77A38C003CECC7 /* HeapTests.swift in Sources */, 7B80C3DE1C77A393003CECC7 /* Heap.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Heap/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Heap/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Heap/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Heap Sort/HeapSort.swift ================================================ extension Heap { public mutating func sort() -> [T] { for i in stride(from: (nodes.count - 1), through: 1, by: -1) { nodes.swapAt(0, i) shiftDown(from: 0, until: i) } return nodes } } /* Sorts an array using a heap. Heapsort can be performed in-place, but it is not a stable sort. */ public func heapsort(_ a: [T], _ sort: @escaping (T, T) -> Bool) -> [T] { let reverseOrder = { i1, i2 in sort(i2, i1) } var h = Heap(array: a, sort: reverseOrder) return h.sort() } ================================================ FILE: Heap Sort/README.markdown ================================================ # Heap Sort Sorts an array from low to high using a heap. A [heap](../Heap/) is a partially sorted binary tree that is stored inside an array. The heap sort algorithm takes advantage of the structure of the heap to perform a fast sort. To sort from lowest to highest, heap sort first converts the unsorted array to a max-heap, so that the first element in the array is the largest. Let's say the array to sort is: [ 5, 13, 2, 25, 7, 17, 20, 8, 4 ] This is first turned into a max-heap that looks like this: ![The max-heap](Images/MaxHeap.png) The heap's internal array is then: [ 25, 13, 20, 8, 7, 17, 2, 5, 4 ] That's hardly what you'd call sorted! But now the sorting process starts: we swap the first element (index *0*) with the last one at index *n-1*, to get: [ 4, 13, 20, 8, 7, 17, 2, 5, 25 ] * * Now the new root node, `4`, will be smaller than its children, so we fix up the max-heap up to element *n-2* using the *shift down* or "heapify" procedure. After repairing the heap, the new root is now the second-largest item in the array: [20, 13, 17, 8, 7, 4, 2, 5 | 25] Important: When we fix the heap, we ignore the last item at index *n-1*. That now contains the array's maximum value, so it is in its final sorted place already. The `|` bar indicates where the sorted portion of the array begins. We'll leave that part of the array alone from now on. Again, we swap the first element with the last one (this time at index *n-2*): [5, 13, 17, 8, 7, 4, 2, 20 | 25] * * And fix up the heap to make it valid max-heap again: [17, 13, 5, 8, 7, 4, 2 | 20, 25] As you can see, the largest items are making their way to the back. We repeat this process until we arrive at the root node and then the whole array is sorted. > **Note:** This process is very similar to [selection sort](../Selection%20Sort/), which repeatedly looks for the minimum item in the remainder of the array. Extracting the minimum or maximum value is what heaps are good at. Performance of heap sort is **O(n log n)** in best, worst, and average case. Because we modify the array directly, heap sort can be performed in-place. But it is not a stable sort: the relative order of identical elements is not preserved. Here's how you can implement heap sort in Swift: ```swift extension Heap { public mutating func sort() -> [T] { for i in stride(from: (elements.count - 1), through: 1, by: -1) { swap(&elements[0], &elements[i]) shiftDown(0, heapSize: i) } return elements } } ``` This adds a `sort()` function to our [heap](../Heap/) implementation. To use it, you would do something like this: ```swift var h1 = Heap(array: [5, 13, 2, 25, 7, 17, 20, 8, 4], sort: >) let a1 = h1.sort() ``` Because we need a max-heap to sort from low-to-high, you need to give `Heap` the reverse of the sort function. To sort `<`, the `Heap` object must be created with `>` as the sort function. In other words, sorting from low-to-high creates a max-heap and turns it into a min-heap. We can write a handy helper function for that: ```swift public func heapsort(_ a: [T], _ sort: @escaping (T, T) -> Bool) -> [T] { let reverseOrder = { i1, i2 in sort(i2, i1) } var h = Heap(array: a, sort: reverseOrder) return h.sort() } ``` *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Heap Sort/Tests/HeapSortTests.swift ================================================ import XCTest class HeapSortTests: XCTestCase { func testSort() { var h1 = Heap(array: [5, 13, 2, 25, 7, 17, 20, 8, 4], sort: >) let a1 = h1.sort() XCTAssertEqual(a1, [2, 4, 5, 7, 8, 13, 17, 20, 25]) let a1_ = heapsort([5, 13, 2, 25, 7, 17, 20, 8, 4], <) XCTAssertEqual(a1_, [2, 4, 5, 7, 8, 13, 17, 20, 25]) var h2 = Heap(array: [16, 14, 10, 8, 7, 8, 3, 2, 4, 1], sort: >) let a2 = h2.sort() XCTAssertEqual(a2, [1, 2, 3, 4, 7, 8, 8, 10, 14, 16]) let a2_ = heapsort([16, 14, 10, 8, 7, 8, 3, 2, 4, 1], <) XCTAssertEqual(a2_, [1, 2, 3, 4, 7, 8, 8, 10, 14, 16]) var h3 = Heap(array: [1, 2, 3, 4, 5, 6], sort: <) let a3 = h3.sort() XCTAssertEqual(a3, [6, 5, 4, 3, 2, 1]) let a3_ = heapsort([1, 2, 3, 4, 5, 6], >) XCTAssertEqual(a3_, [6, 5, 4, 3, 2, 1]) } } ================================================ FILE: Heap Sort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Heap Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 51; objects = { /* Begin PBXBuildFile section */ 7B80C3E01C77A3DB003CECC7 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3DF1C77A3DB003CECC7 /* Heap.swift */; }; 7B80C3E21C77A3E5003CECC7 /* HeapSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E11C77A3E5003CECC7 /* HeapSort.swift */; }; 7B80C3E41C77A3EB003CECC7 /* HeapSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E31C77A3EB003CECC7 /* HeapSortTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3DF1C77A3DB003CECC7 /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../../Heap/Heap.swift; sourceTree = SOURCE_ROOT; }; 7B80C3E11C77A3E5003CECC7 /* HeapSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HeapSort.swift; path = ../HeapSort.swift; sourceTree = SOURCE_ROOT; }; 7B80C3E31C77A3EB003CECC7 /* HeapSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeapSortTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3DF1C77A3DB003CECC7 /* Heap.swift */, 7B80C3E11C77A3E5003CECC7 /* HeapSort.swift */, 7B80C3E31C77A3EB003CECC7 /* HeapSortTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1010; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 1010; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 10.0"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3E01C77A3DB003CECC7 /* Heap.swift in Sources */, 7B80C3E41C77A3EB003CECC7 /* HeapSortTests.swift in Sources */, 7B80C3E21C77A3E5003CECC7 /* HeapSort.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Heap Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Heap Sort/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Huffman Coding/Huffman.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation let s1 = "so much words wow many compression" if let originalData = s1.data(using: .utf8) { print(originalData.count) let huffman1 = Huffman() let compressedData = huffman1.compressData(data: originalData as NSData) print(compressedData.length) let frequencyTable = huffman1.frequencyTable() //print(frequencyTable) let huffman2 = Huffman() let decompressedData = huffman2.decompressData(data: compressedData, frequencyTable: frequencyTable) print(decompressedData.length) let s2 = String(data: decompressedData as Data, encoding: .utf8)! print(s2) assert(s1 == s2) } ================================================ FILE: Huffman Coding/Huffman.playground/Sources/Heap.swift ================================================ // // Heap.swift // Written for the Swift Algorithm Club by Kevin Randrup and Matthijs Hollemans // public struct Heap { /** The array that stores the heap's nodes. */ var elements = [T]() /** Determines whether this is a max-heap (>) or min-heap (<). */ fileprivate var isOrderedBefore: (T, T) -> Bool /** * Creates an empty heap. * The sort function determines whether this is a min-heap or max-heap. * For integers, > makes a max-heap, < makes a min-heap. */ public init(sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort } /** * Creates a heap from an array. The order of the array does not matter; * the elements are inserted into the heap in the order determined by the * sort function. */ public init(array: [T], sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort buildHeap(array: array) } /* // This version has O(n log n) performance. private mutating func buildHeap(array: [T]) { elements.reserveCapacity(array.count) for value in array { insert(value) } } */ /** * Converts an array to a max-heap or min-heap in a bottom-up manner. * Performance: This runs pretty much in O(n). */ private mutating func buildHeap(array: [T]) { elements = array for i in stride(from: elements.count/2 - 1, to: 0, by: -1) { shiftDown(index: i, heapSize: elements.count) } } public var isEmpty: Bool { return elements.isEmpty } public var count: Int { return elements.count } /** * Returns the index of the parent of the element at index i. * The element at index 0 is the root of the tree and has no parent. */ @inline(__always) func indexOfParent(i: Int) -> Int { return (i - 1) / 2 } /** * Returns the index of the left child of the element at index i. * Note that this index can be greater than the heap size, in which case * there is no left child. */ @inline(__always) func indexOfLeftChild(i: Int) -> Int { return 2*i + 1 } /** * Returns the index of the right child of the element at index i. * Note that this index can be greater than the heap size, in which case * there is no right child. */ @inline(__always) func indexOfRightChild(i: Int) -> Int { return 2*i + 2 } /** * Returns the maximum value in the heap (for a max-heap) or the minimum * value (for a min-heap). */ public func peek() -> T? { return elements.first } /** * Adds a new value to the heap. This reorders the heap so that the max-heap * or min-heap property still holds. Performance: O(log n). */ public mutating func insert(_ value: T) { elements.append(value) shiftUp(index: elements.count - 1) } public mutating func insert(sequence: S) where S.Iterator.Element == T { for value in sequence { insert(value) } } /** * Allows you to change an element. In a max-heap, the new element should be * larger than the old one; in a min-heap it should be smaller. */ public mutating func replace(index i: Int, value: T) { assert(isOrderedBefore(value, elements[i])) elements[i] = value shiftUp(index: i) } /** * Removes the root node from the heap. For a max-heap, this is the maximum * value; for a min-heap it is the minimum value. Performance: O(log n). */ public mutating func remove() -> T? { if elements.isEmpty { return nil } else if elements.count == 1 { return elements.removeLast() } else { // Use the last node to replace the first one, then fix the heap by // shifting this new first node into its proper position. let value = elements[0] elements[0] = elements.removeLast() shiftDown() return value } } /** * Removes an arbitrary node from the heap. Performance: O(log n). You need * to know the node's index, which may actually take O(n) steps to find. */ public mutating func removeAtIndex(i: Int) -> T? { let size = elements.count - 1 if i != size { elements.swapAt(i, size) shiftDown(index: i, heapSize: size) shiftUp(index: i) } return elements.removeLast() } /** * Takes a child node and looks at its parents; if a parent is not larger * (max-heap) or not smaller (min-heap) than the child, we exchange them. */ mutating func shiftUp(index: Int) { var childIndex = index let child = elements[childIndex] var parentIndex = indexOfParent(i: childIndex) while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { elements[childIndex] = elements[parentIndex] childIndex = parentIndex parentIndex = indexOfParent(i: childIndex) } elements[childIndex] = child } mutating func shiftDown() { shiftDown(index: 0, heapSize: elements.count) } /** * Looks at a parent node and makes sure it is still larger (max-heap) or * smaller (min-heap) than its childeren. */ mutating func shiftDown(index: Int, heapSize: Int) { var parentIndex = index while true { let leftChildIndex = indexOfLeftChild(i: parentIndex) let rightChildIndex = leftChildIndex + 1 // Figure out which comes first if we order them by the sort function: // the parent, the left child, or the right child. If the parent comes // first, we're done. If not, that element is out-of-place and we make // it "float down" the tree until the heap property is restored. var first = parentIndex if leftChildIndex < heapSize && isOrderedBefore(elements[leftChildIndex], elements[first]) { first = leftChildIndex } if rightChildIndex < heapSize && isOrderedBefore(elements[rightChildIndex], elements[first]) { first = rightChildIndex } if first == parentIndex { return } elements.swapAt(parentIndex, first) parentIndex = first } } } // MARK: - Searching extension Heap where T: Equatable { /** * Searches the heap for the given element. Performance: O(n). */ public func index(of element: T) -> Int? { return index(of: element, 0) } private func index(of element: T, _ i: Int) -> Int? { if i >= count { return nil } if isOrderedBefore(element, elements[i]) { return nil } if element == elements[i] { return i } if let j = index(of: element, indexOfLeftChild(i: i)) { return j } if let j = index(of: element, indexOfRightChild(i: i)) { return j } return nil } } ================================================ FILE: Huffman Coding/Huffman.playground/Sources/Huffman.swift ================================================ import Foundation /* Basic implementation of Huffman encoding. It encodes bytes that occur often with a smaller number of bits than bytes that occur less frequently. Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February 1991 and October 1992. Note: This code is not optimized for speed but explanation. */ public class Huffman { /* Tree nodes don't use pointers to refer to each other, but simple integer indices. That allows us to use structs for the nodes. */ typealias NodeIndex = Int /* A node in the compression tree. Leaf nodes represent the actual bytes that are present in the input data. The count of an intermediary node is the sum of the counts of all nodes below it. The root node's count is the number of bytes in the original, uncompressed input data. */ struct Node { var count = 0 var index: NodeIndex = -1 var parent: NodeIndex = -1 var left: NodeIndex = -1 var right: NodeIndex = -1 } /* The tree structure. The first 256 entries are for the leaf nodes (not all of those may be used, depending on the input). We add additional nodes as we build the tree. */ var tree = [Node](repeating: Node(), count: 256) /* This is the last node we add to the tree. */ var root: NodeIndex = -1 /* The frequency table describes how often a byte occurs in the input data. You need it to decompress the Huffman-encoded data. The frequency table should be serialized along with the compressed data. */ public struct Freq { var byte: UInt8 = 0 var count = 0 } public init() { } } extension Huffman { /* To compress a block of data, first we need to count how often each byte occurs. These counts are stored in the first 256 nodes in the tree, i.e. the leaf nodes. The frequency table used by decompression is derived from this. */ fileprivate func countByteFrequency(inData data: NSData) { var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. [Freq] { var a = [Freq]() for i in 0..<256 where tree[i].count > 0 { a.append(Freq(byte: UInt8(i), count: tree[i].count)) } return a } } extension Huffman { /* Builds a Huffman tree from a frequency table. */ fileprivate func buildTree() { // Create a min-priority queue and enqueue all used nodes. var queue = PriorityQueue(sort: { $0.count < $1.count }) for node in tree where node.count > 0 { queue.enqueue(node) } while queue.count > 1 { // Find the two nodes with the smallest frequencies that do not have // a parent node yet. let node1 = queue.dequeue()! let node2 = queue.dequeue()! // Create a new intermediate node. var parentNode = Node() parentNode.count = node1.count + node2.count parentNode.left = node1.index parentNode.right = node2.index parentNode.index = tree.count tree.append(parentNode) // Link the two nodes into their new parent node. tree[node1.index].parent = parentNode.index tree[node2.index].parent = parentNode.index // Put the intermediate node back into the queue. queue.enqueue(parentNode) } // The final remaining node in the queue becomes the root of the tree. let rootNode = queue.dequeue()! root = rootNode.index } } extension Huffman { /* Compresses the contents of an NSData object. */ public func compressData(data: NSData) -> NSData { countByteFrequency(inData: data) buildTree() let writer = BitWriter() var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. NSData { restoreTree(fromTable: frequencyTable) let reader = BitReader(data: data) let outData = NSMutableData() let byteCount = tree[root].count var i = 0 while i < byteCount { var b = findLeafNode(reader: reader, nodeIndex: root) outData.append(&b, length: 1) i += 1 } return outData } /* Walks the tree from the root down to the leaf node. At every node, read the next bit and use that to determine whether to step to the left or right. When we get to the leaf node, we simply return its index, which is equal to the original byte value. */ private func findLeafNode(reader: BitReader, nodeIndex: Int) -> UInt8 { var h = nodeIndex while tree[h].right != -1 { if reader.readBit() { h = tree[h].left } else { h = tree[h].right } } return UInt8(h) } } ================================================ FILE: Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift ================================================ import Foundation /* Helper class for writing bits to an NSData object. */ public class BitWriter { public var data = NSMutableData() var outByte: UInt8 = 0 var outCount = 0 public func writeBit(bit: Bool) { if outCount == 8 { data.append(&outByte, length: 1) outCount = 0 } outByte = (outByte << 1) | (bit ? 1 : 0) outCount += 1 } public func flush() { if outCount > 0 { if outCount < 8 { let diff = UInt8(8 - outCount) outByte <<= diff } data.append(&outByte, length: 1) } } } /* Helper class for reading bits from an NSData object. */ public class BitReader { var ptr: UnsafePointer var inByte: UInt8 = 0 var inCount = 8 public init(data: NSData) { ptr = data.bytes.assumingMemoryBound(to: UInt8.self) } public func readBit() -> Bool { if inCount == 8 { inByte = ptr.pointee // load the next byte inCount = 0 ptr = ptr.successor() } let bit = inByte & 0x80 // read the next bit inByte <<= 1 inCount += 1 return bit == 0 ? false : true } } ================================================ FILE: Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift ================================================ /* Priority Queue, a queue where the most "important" items are at the front of the queue. The heap is a natural data structure for a priority queue, so this object simply wraps the Heap struct. All operations are O(lg n). Just like a heap can be a max-heap or min-heap, the queue can be a max-priority queue (largest element first) or a min-priority queue (smallest element first). */ public struct PriorityQueue { fileprivate var heap: Heap /* To create a max-priority queue, supply a > sort function. For a min-priority queue, use <. */ public init(sort: @escaping (T, T) -> Bool) { heap = Heap(sort: sort) } public var isEmpty: Bool { return heap.isEmpty } public var count: Int { return heap.count } public func peek() -> T? { return heap.peek() } public mutating func enqueue(_ element: T) { heap.insert(element) } public mutating func dequeue() -> T? { return heap.remove() } /* Allows you to change the priority of an element. In a max-priority queue, the new priority should be larger than the old one; in a min-priority queue it should be smaller. */ public mutating func changePriority(index i: Int, value: T) { return heap.replace(index: i, value: value) } } extension PriorityQueue where T: Equatable { public func indexOf(element: T) -> Int? { return heap.index(of: element) } } ================================================ FILE: Huffman Coding/Huffman.playground/contents.xcplayground ================================================ ================================================ FILE: Huffman Coding/Huffman.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Huffman Coding/Huffman.playground/timeline.xctimeline ================================================ ================================================ FILE: Huffman Coding/Huffman.swift ================================================ import Foundation /* Basic implementation of Huffman encoding. It encodes bytes that occur often with a smaller number of bits than bytes that occur less frequently. Based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February 1991 and October 1992. Note: This code is not optimized for speed but explanation. */ public class Huffman { /* Tree nodes don't use pointers to refer to each other, but simple integer indices. That allows us to use structs for the nodes. */ typealias NodeIndex = Int /* A node in the compression tree. Leaf nodes represent the actual bytes that are present in the input data. The count of an intermediary node is the sum of the counts of all nodes below it. The root node's count is the number of bytes in the original, uncompressed input data. */ struct Node { var count = 0 var index: NodeIndex = -1 var parent: NodeIndex = -1 var left: NodeIndex = -1 var right: NodeIndex = -1 } /* The tree structure. The first 256 entries are for the leaf nodes (not all of those may be used, depending on the input). We add additional nodes as we build the tree. */ var tree = [Node](repeating: Node(), count: 256) /* This is the last node we add to the tree. */ var root: NodeIndex = -1 /* The frequency table describes how often a byte occurs in the input data. You need it to decompress the Huffman-encoded data. The frequency table should be serialized along with the compressed data. */ public struct Freq { var byte: UInt8 = 0 var count = 0 } public init() { } } extension Huffman { /* To compress a block of data, first we need to count how often each byte occurs. These counts are stored in the first 256 nodes in the tree, i.e. the leaf nodes. The frequency table used by decompression is derived from this. */ fileprivate func countByteFrequency(inData data: NSData) { var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. [Freq] { var a = [Freq]() for i in 0..<256 where tree[i].count > 0 { a.append(Freq(byte: UInt8(i), count: tree[i].count)) } return a } } extension Huffman { /* Builds a Huffman tree from a frequency table. */ fileprivate func buildTree() { // Create a min-priority queue and enqueue all used nodes. var queue = PriorityQueue(sort: { $0.count < $1.count }) for node in tree where node.count > 0 { queue.enqueue(node) } while queue.count > 1 { // Find the two nodes with the smallest frequencies that do not have // a parent node yet. let node1 = queue.dequeue()! let node2 = queue.dequeue()! // Create a new intermediate node. var parentNode = Node() parentNode.count = node1.count + node2.count parentNode.left = node1.index parentNode.right = node2.index parentNode.index = tree.count tree.append(parentNode) // Link the two nodes into their new parent node. tree[node1.index].parent = parentNode.index tree[node2.index].parent = parentNode.index // Put the intermediate node back into the queue. queue.enqueue(parentNode) } // The final remaining node in the queue becomes the root of the tree. let rootNode = queue.dequeue()! root = rootNode.index } } extension Huffman { /* Compresses the contents of an NSData object. */ public func compressData(data: NSData) -> NSData { countByteFrequency(inData: data) buildTree() let writer = BitWriter() var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. NSData { restoreTree(fromTable: frequencyTable) let reader = BitReader(data: data) let outData = NSMutableData() let byteCount = tree[root].count var i = 0 while i < byteCount { var b = findLeafNode(reader: reader, nodeIndex: root) outData.append(&b, length: 1) i += 1 } return outData } /* Walks the tree from the root down to the leaf node. At every node, read the next bit and use that to determine whether to step to the left or right. When we get to the leaf node, we simply return its index, which is equal to the original byte value. */ private func findLeafNode(reader: BitReader, nodeIndex: Int) -> UInt8 { var h = nodeIndex while tree[h].right != -1 { if reader.readBit() { h = tree[h].left } else { h = tree[h].right } } return UInt8(h) } } ================================================ FILE: Huffman Coding/NSData+Bits.swift ================================================ import Foundation /* Helper class for writing bits to an NSData object. */ public class BitWriter { public var data = NSMutableData() var outByte: UInt8 = 0 var outCount = 0 public func writeBit(bit: Bool) { if outCount == 8 { data.append(&outByte, length: 1) outCount = 0 } outByte = (outByte << 1) | (bit ? 1 : 0) outCount += 1 } public func flush() { if outCount > 0 { if outCount < 8 { let diff = UInt8(8 - outCount) outByte <<= diff } data.append(&outByte, length: 1) } } } /* Helper class for reading bits from an NSData object. */ public class BitReader { var ptr: UnsafePointer var inByte: UInt8 = 0 var inCount = 8 public init(data: NSData) { ptr = data.bytes.assumingMemoryBound(to: UInt8.self) } public func readBit() -> Bool { if inCount == 8 { inByte = ptr.pointee // load the next byte inCount = 0 ptr = ptr.successor() } let bit = inByte & 0x80 // read the next bit inByte <<= 1 inCount += 1 return bit == 0 ? false : true } } ================================================ FILE: Huffman Coding/README.markdown ================================================ # Huffman Coding The idea: To encode objects that occur often with a smaller number of bits than objects that occur less frequently. Although any type of objects can be encoded with this scheme, it is common to compress a stream of bytes. Suppose you have the following text, where each character is one byte: so much words wow many compression If you count how often each byte appears, you can see some bytes occur more than others: space: 5 u: 1 o: 5 h: 1 s: 4 d: 1 m: 3 a: 1 w: 3 y: 1 c: 2 p: 1 r: 2 e: 1 n: 2 i: 1 We can assign bit strings to each of these bytes. The more common a byte is, the fewer bits we assign to it. We might get something like this: space: 5 010 u: 1 11001 o: 5 000 h: 1 10001 s: 4 101 d: 1 11010 m: 3 111 a: 1 11011 w: 3 0010 y: 1 01111 c: 2 0011 p: 1 11000 r: 2 1001 e: 1 01110 n: 2 0110 i: 1 10000 Now if we replace the original bytes with these bit strings, the compressed output becomes: 101 000 010 111 11001 0011 10001 010 0010 000 1001 11010 101 s o _ m u c h _ w o r d s 010 0010 000 0010 010 111 11011 0110 01111 010 0011 000 111 _ w o w _ m a n y _ c o m 11000 1001 01110 101 101 10000 000 0110 0 p r e s s i o n The extra 0-bit at the end is there to make a full number of bytes. We were able to compress the original 34 bytes into merely 16 bytes, a space savings of over 50%! To be able to decode these bits, we need to have the original frequency table. That table needs to be transmitted or saved along with the compressed data. Otherwise, the decoder does not know how to interpret the bits. Because of the overhead of this frequency table (about 1 kilobyte), it is not beneficial to use Huffman encoding on small inputs. ## How it works When compressing a stream of bytes, the algorithm first creates a frequency table that counts how often each byte occurs. Based on this table, the algorithm creates a binary tree that describes the bit strings for each of the input bytes. For our example, the tree looks like this: ![The compression tree](Images/Tree.png) Note that the tree has 16 leaf nodes (the grey ones), one for each byte value from the input. Each leaf node also shows the count of how often it occurs. The other nodes are "intermediate" nodes. The number shown in these nodes is the sum of the counts of their child nodes. The count of the root node is therefore the total number of bytes in the input. The edges between the nodes are either "1" or "0". These correspond to the bit-encodings of the leaf nodes. Notice how each left branch is always 1 and each right branch is always 0. Compression is then a matter of looping through the input bytes and for each byte traversing the tree from the root node to that byte's leaf node. Every time we take a left branch, we emit a 1-bit. When we take a right branch, we emit a 0-bit. For example, to go from the root node to `c`, we go right (`0`), right again (`0`), left (`1`), and left again (`1`). This gives the Huffman code as `0011` for `c`. Decompression works in exactly the opposite way. It reads the compressed bits one-by-one and traverses the tree until it reaches to a leaf node. The value of that leaf node is the uncompressed byte. For example, if the bits are `11010`, we start at the root and go left, left again, right, left, and a final right to end up at `d`. ## The code Before we get to the actual Huffman coding scheme, it is useful to have some helper code that can write individual bits to an `NSData` object. The smallest piece of data that `NSData` understands is the byte, but we are dealing in bits, so we need to translate between the two. ```swift public class BitWriter { public var data = NSMutableData() var outByte: UInt8 = 0 var outCount = 0 public func writeBit(bit: Bool) { if outCount == 8 { data.append(&outByte, length: 1) outCount = 0 } outByte = (outByte << 1) | (bit ? 1 : 0) outCount += 1 } public func flush() { if outCount > 0 { if outCount < 8 { let diff = UInt8(8 - outCount) outByte <<= diff } data.append(&outByte, length: 1) } } } ``` To add a bit to the `NSData`, you can call `writeBit()`. This helper object stuffs each new bit into the `outByte` variable. Once you have written 8 bits, `outByte` gets added to the `NSData` object for real. The `flush()` method is used for outputting the very last byte. There is no guarantee that the number of compressed bits is a nice round multiple of 8, in which case there may be some spare bits at the end. If so, `flush()` adds a few 0-bits to make sure that we write a full byte. Here is a similar helper object for reading individual bits from `NSData`: ```swift public class BitReader { var ptr: UnsafePointer var inByte: UInt8 = 0 var inCount = 8 public init(data: NSData) { ptr = data.bytes.assumingMemoryBound(to: UInt8.self) } public func readBit() -> Bool { if inCount == 8 { inByte = ptr.pointee // load the next byte inCount = 0 ptr = ptr.successor() } let bit = inByte & 0x80 // read the next bit inByte <<= 1 inCount += 1 return bit == 0 ? false : true } } ``` By using this helper object, we can read one whole byte from the `NSData` object and put it in `inByte`. Then, `readBit()` returns the individual bits from that byte. Once `readBit()` has been called 8 times, we read the next byte from the `NSData`. > **Note:** If you are unfamiliar with this type of bit manipulation, just know that these two helper objects make it simple for us to write and read bits. ## The frequency table The first step in the Huffman compression is to read the entire input stream and build a frequency table. This table contains a list of all 256 possible byte values and shows how often each of these bytes occurs in the input data. We could store this frequency information in a dictionary or an array, but since we need to build a tree, we might store the frequency table as the leaves of the tree. Here are the definitions we need: ```swift class Huffman { typealias NodeIndex = Int struct Node { var count = 0 var index: NodeIndex = -1 var parent: NodeIndex = -1 var left: NodeIndex = -1 var right: NodeIndex = -1 } var tree = [Node](repeating: Node(), count: 256) var root: NodeIndex = -1 } ``` The tree structure is stored in the `tree` array and will be made up of `Node` objects. Since this is a [binary tree](../Binary%20Tree/), each node needs two children, `left` and `right`, and a reference back to its `parent` node. Unlike a typical binary tree, these nodes do not use pointers to refer to each other but use simple integer indices in the `tree` array. (We also store the array `index` of the node itself; the reason for this will become clear later.) Note that the `tree` currently has room for 256 entries. These are for the leaf nodes because there are 256 possible byte values. Of course, not all of those may end up being used, depending on the input data. Later, we will add more nodes as we build up the actual tree. For the moment, there is not a tree yet. It includes 256 separate leaf nodes with no connections between them. All the node counts are 0. We use the following method to count how often each byte occurs in the input data: ```swift fileprivate func countByteFrequency(inData data: NSData) { var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. [Freq] { var a = [Freq]() for i in 0..<256 where tree[i].count > 0 { a.append(Freq(byte: UInt8(i), count: tree[i].count)) } return a } ``` The `frequencyTable()` method looks at those first 256 nodes from the tree but keeps only those that are used, without the `parent`, `left`, and `right` pointers. It returns an array of `Freq` objects. You have to serialize this array along with the compressed data, so that it can be properly decompressed later. ## The tree As a reminder, there is the compression tree for the example: ![The compression tree](Images/Tree.png) The leaf nodes represent the actual bytes that are present in the input data. The intermediary nodes connect the leaves in such a way that the path from the root to a frequently-used byte value is shorter than the path to a less common byte value. As you can see, `m`, `s`, space, and `o` are the most common letters in our input data and the highest up in the tree. To build the tree, we do the following: 1. Find the two nodes with the smallest counts that do not have a parent node yet. 2. Create a new parent node that links these two nodes together. 3. This repeats over and over until only one node with no parent remains. This becomes the root node of the tree. This is an ideal place to use a [priority queue](../Priority%20Queue/). A priority queue is a data structure that is optimized, so that finding the minimum value is always fast. Here, we repeatedly need to find the node with the smallest count. The function `buildTree()` then becomes: ```swift fileprivate func buildTree() { var queue = PriorityQueue(sort: { $0.count < $1.count }) for node in tree where node.count > 0 { queue.enqueue(node) // 1 } while queue.count > 1 { let node1 = queue.dequeue()! // 2 let node2 = queue.dequeue()! var parentNode = Node() // 3 parentNode.count = node1.count + node2.count parentNode.left = node1.index parentNode.right = node2.index parentNode.index = tree.count tree.append(parentNode) tree[node1.index].parent = parentNode.index // 4 tree[node2.index].parent = parentNode.index queue.enqueue(parentNode) // 5 } let rootNode = queue.dequeue()! // 6 root = rootNode.index } ``` Here is how it works step-by-step: 1. Create a priority queue and enqueue all the leaf nodes that have at least a count of 1. (If the count is 0, then this byte value did not appear in the input data.) The `PriorityQueue` object sorts the nodes by their count, so that the node with the lowest count is always the first one that gets dequeued. 2. While there are at least two nodes left in the queue, remove the two nodes that are at the front of the queue. Since this is a min-priority queue, this gives us the two nodes with the smallest counts that do not have a parent node yet. 3. Create a new intermediate node that connects `node1` and `node2`. The count of this new node is the sum of the counts of `node1` and `node2`. Because the nodes are connected using array indices instead of real pointers, we use `node1.index` and `node2.index` to find these nodes in the `tree` array. (This is why a `Node` needs to know its own index.) 4. Link the two nodes into their new parent node. Now this new intermediate node has become part of the tree. 5. Put the new intermediate node back into the queue. At this point we are done with `node1` and `node2`, but the `parentNode` still needs to be connected to other nodes in the tree. 6. Repeat steps 2-5 until there is only one node left in the queue. This becomes the root node of the tree, and we are done. The animation shows what the process looks like: ![Building the tree](Images/BuildTree.gif) > **Note:** Instead of using a priority queue, you can repeatedly iterate through the `tree` array to find the next two smallest nodes, but that makes the compressor slow as **O(n^2)**. Using the priority queue, the running time is only **O(n log n)** where **n** is the number of nodes. > **Fun fact:** Due to the nature of binary trees, if we have *x* leaf nodes we can at most add *x - 1* additional nodes to the tree. Given that at most there will be 256 leaf nodes, the tree will never contain more than 511 nodes total. ## Compression Now that we know how to build the compression tree from the frequency table, we can use it to compress the contents of an `NSData` object. Here is the code: ```swift public func compressData(data: NSData) -> NSData { countByteFrequency(inData: data) buildTree() let writer = BitWriter() var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. **Note:** Compression always requires two passes through the entire input data: first to build the frequency table, and second to convert the bytes to their compressed bit sequences. The interesting stuff happens in `traverseTree()`. This is a recursive method: ```swift private func traverseTree(writer: BitWriter, nodeIndex h: Int, childIndex child: Int) { if tree[h].parent != -1 { traverseTree(writer: writer, nodeIndex: tree[h].parent, childIndex: h) } if child != -1 { if child == tree[h].left { writer.writeBit(bit: true) } else if child == tree[h].right { writer.writeBit(bit: false) } } } ``` When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we need to encode. This method recursively walks the tree from a leaf node up to the root and then back again. As we are going back from the root to the leaf node, we write a 1 bit or a 0 bit for every node we encounter. If a child is the left node, we emit a 1; if it is the right node, we emit a 0. In a picture: ![How compression works](Images/Compression.png) Even though the illustration of the tree shows a 0 or 1 for each edge between the nodes, the bit values 0 and 1 are not actually stored in the tree! The rule is that we write a 1 bit if we take the left branch and a 0 bit if we take the right branch, so just knowing the direction we are going in is enough to determine what bit value to write. You use the `compressData()` method as follows: ```swift let s1 = "so much words wow many compression" if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) { let huffman1 = Huffman() let compressedData = huffman1.compressData(originalData) print(compressedData.length) } ``` ## Decompression Decompression is the compression in reverse. However, the compressed bits are useless without the frequency table. As mentioned, the `frequencyTable()` method returns an array of `Freq` objects. If we were saving the compressed data into a file or sending it across the network, we'd also save that `[Freq]` array along with it. We first need some way to turn the `[Freq]` array back into a compression tree: ```swift fileprivate func restoreTree(fromTable frequencyTable: [Freq]) { for freq in frequencyTable { let i = Int(freq.byte) tree[i].count = freq.count tree[i].index = i } buildTree() } ``` We convert the `Freq` objects into leaf nodes and then call `buildTree()` to do the rest. Here is the code for `decompressData()`, which takes an `NSData` object with Huffman-encoded bits and a frequency table, and it returns the original data: ```swift func decompressData(data: NSData, frequencyTable: [Freq]) -> NSData { restoreTree(fromTable: frequencyTable) let reader = BitReader(data: data) let outData = NSMutableData() let byteCount = tree[root].count var i = 0 while i < byteCount { var b = findLeafNode(reader: reader, nodeIndex: root) outData.append(&b, length: 1) i += 1 } return outData } ``` This also uses a helper method to traverse the tree: ```swift private func findLeafNode(reader reader: BitReader, nodeIndex: Int) -> UInt8 { var h = nodeIndex while tree[h].right != -1 { if reader.readBit() { h = tree[h].left } else { h = tree[h].right } } return UInt8(h) } ``` `findLeafNode()` walks the tree from the root down to the leaf node given by `nodeIndex`. At each intermediate node, we read a new bit and then step to the left (bit is 1) or the right (bit is 0). When we get to the leaf node, we simply return its index, which is equal to the original byte value. In a picture: ![How decompression works](Images/Decompression.png) Here is how we use the decompression method: ```swift let frequencyTable = huffman1.frequencyTable() let huffman2 = Huffman() let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable) let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! ``` First we get the frequency table from somewhere (in this case the `Huffman` object we used to encode the data) and then call `decompressData()`. The string that results should be equal to the one we compressed in the first place. we can see how this works in more detail in the Playground. ## See also [Huffman coding at Wikipedia](https://en.wikipedia.org/wiki/Huffman_coding) The code is loosely based on Al Stevens' C Programming column from Dr.Dobb's Magazine, February 1991 and October 1992. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Insertion Sort/InsertionSort.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play /// Performs the Insertion sort algorithm to a given array /// /// - Parameters: /// - array: the array of elements to be sorted /// - isOrderedBefore: returns true if the elements provided are in the corect order /// - Returns: a sorted array containing the same elements func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } var sortedArray = array for index in 1.. 0 && isOrderedBefore(temp, sortedArray[currentIndex - 1]) { sortedArray[currentIndex] = sortedArray[currentIndex - 1] currentIndex -= 1 } sortedArray[currentIndex] = temp } return sortedArray } /// Performs the Insertion sort algorithm to a given array /// /// - Parameter array: the array to be sorted, conatining elements that conform to the Comparable protocol /// - Returns: a sorted array containing the same elements func insertionSort(_ array: [T]) -> [T] { var sortedArray = array for index in 1.. 0 && temp < sortedArray[currentIndex - 1] { sortedArray[currentIndex] = sortedArray[currentIndex - 1] currentIndex -= 1 } sortedArray[currentIndex] = temp } return sortedArray } let list = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] print(insertionSort(list)) print(insertionSort(list, <)) print(insertionSort(list, >)) ================================================ FILE: Insertion Sort/InsertionSort.playground/contents.xcplayground ================================================ ================================================ FILE: Insertion Sort/InsertionSort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Insertion Sort/InsertionSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Insertion Sort/InsertionSort.swift ================================================ /// Performs the Insertion sort algorithm to a given array /// /// - Parameters: /// - array: the array of elements to be sorted /// - isOrderedBefore: returns true if the elements provided are in the corect order /// - Returns: a sorted array containing the same elements func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } /// - sortedArray: copy the array to save stability var sortedArray = array for index in 1.. 0, isOrderedBefore(temp, sortedArray[currentIndex - 1]) { sortedArray[currentIndex] = sortedArray[currentIndex - 1] currentIndex -= 1 } sortedArray[currentIndex] = temp } return sortedArray } /// Performs the Insertion sort algorithm to a given array /// /// - Parameter array: the array to be sorted, containing elements that conform to the Comparable protocol /// - Returns: a sorted array containing the same elements func insertionSort(_ array: [T]) -> [T] { guard array.count > 1 else { return array } var sortedArray = array for var index in 1.. 0, temp < sortedArray[index - 1] { sortedArray[index] = sortedArray[index - 1] index -= 1 } sortedArray[index] = temp } return sortedArray } ================================================ FILE: Insertion Sort/README.markdown ================================================ # Insertion Sort Goal: Sort an array from low to high (or high to low). You are given an array of numbers and need to put them in the right order. The insertion sort algorithm works as follows: - Put the numbers on a pile. This pile is unsorted. - Pick a number from the pile. It doesn't really matter which one you pick, but it's easiest to pick from the top of the pile. - Insert this number into a new array. - Pick the next number from the unsorted pile and also insert that into the new array. It either goes before or after the first number you picked, so that now these two numbers are sorted. - Again, pick the next number from the pile and insert it into the array in the proper sorted position. - Keep doing this until there are no more numbers on the pile. You end up with an empty pile and an array that is sorted. That's why this is called an "insertion" sort, because you take a number from the pile and insert it in the array in its proper sorted position. ## An example Let's say the numbers to sort are `[ 8, 3, 5, 4, 6 ]`. This is our unsorted pile. Pick the first number, `8`, and insert it into the new array. There is nothing in that array yet, so that's easy. The sorted array is now `[ 8 ]` and the pile is `[ 3, 5, 4, 6 ]`. Pick the next number from the pile, `3`, and insert it into the sorted array. It should go before the `8`, so the sorted array is now `[ 3, 8 ]` and the pile is reduced to `[ 5, 4, 6 ]`. Pick the next number from the pile, `5`, and insert it into the sorted array. It goes in between the `3` and `8`. The sorted array is `[ 3, 5, 8 ]` and the pile is `[ 4, 6 ]`. Repeat this process until the pile is empty. ## In-place sort The above explanation makes it seem like you need two arrays: one for the unsorted pile and one that contains the numbers in sorted order. But you can perform the insertion sort *in-place*, without having to create a separate array. You just keep track of which part of the array is sorted already and which part is the unsorted pile. Initially, the array is `[ 8, 3, 5, 4, 6 ]`. The `|` bar shows where the sorted portion ends and the pile begins: [| 8, 3, 5, 4, 6 ] This shows that the sorted portion is empty and the pile starts at `8`. After processing the first number, we have: [ 8 | 3, 5, 4, 6 ] The sorted portion is `[ 8 ]` and the pile is `[ 3, 5, 4, 6 ]`. The `|` bar has shifted one position to the right. This is how the content of the array changes during the sort: [| 8, 3, 5, 4, 6 ] [ 8 | 3, 5, 4, 6 ] [ 3, 8 | 5, 4, 6 ] [ 3, 5, 8 | 4, 6 ] [ 3, 4, 5, 8 | 6 ] [ 3, 4, 5, 6, 8 |] In each step, the `|` bar moves up one position. As you can see, the beginning of the array up to the `|` is always sorted. The pile shrinks by one and the sorted portion grows by one, until the pile is empty and there are no more unsorted numbers left. ## How to insert At each step you pick the top-most number from the unsorted pile and insert it into the sorted portion of the array. You must put that number in the proper place so that the beginning of the array remains sorted. How does that work? Let's say we've already done the first few elements and the array looks like this: [ 3, 5, 8 | 4, 6 ] The next number to sort is `4`. We need to insert that into the sorted portion `[ 3, 5, 8 ]` somewhere. Here's one way to do this: Look at the previous element, `8`. [ 3, 5, 8, 4 | 6 ] ^ Is this greater than `4`? Yes it is, so the `4` should come before the `8`. We swap these two numbers to get: [ 3, 5, 4, 8 | 6 ] <--> swapped We're not done yet. The new previous element, `5`, is also greater than `4`. We also swap these two numbers: [ 3, 4, 5, 8 | 6 ] <--> swapped Again, look at the previous element. Is `3` greater than `4`? No, it is not. That means we're done with number `4`. The beginning of the array is sorted again. This was a description of the inner loop of the insertion sort algorithm, which you'll see in the next section. It inserts the number from the top of the pile into the sorted portion by swapping numbers. ## The code Here is an implementation of insertion sort in Swift: ```swift func insertionSort(_ array: [Int]) -> [Int] { var sortedArray = array // 1 for index in 1.. 0 && sortedArray[currentIndex] < sortedArray[currentIndex - 1] { // 3 sortedArray.swapAt(currentIndex - 1, currentIndex) currentIndex -= 1 } } return sortedArray } ``` Put this code in a playground and test it like so: ```swift let list = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] insertionSort(list) ``` Here is how the code works. 1. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly. Like Swift's own `sorted()`, the `insertionSort()` function will return a sorted *copy* of the original array. 2. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what picks the top-most number from the pile. The variable `currentIndex` is the index of where the sorted portion ends and the pile begins (the position of the `|` bar). Remember, at any given moment the beginning of the array -- from index 0 up to `currentIndex` -- is always sorted. The rest, from index `currentIndex` until the last element, is the unsorted pile. 3. The inner loop looks at the element at position `currentIndex`. This is the number at the top of the pile, and it may be smaller than any of the previous elements. The inner loop steps backwards through the sorted array; every time it finds a previous number that is larger, it swaps them. When the inner loop completes, the beginning of the array is sorted again, and the sorted portion has grown by one element. > **Note:** The outer loop starts at index 1, not 0. Moving the very first element from the pile to the sorted portion doesn't actually change anything, so we might as well skip it. ## No more swaps The above version of insertion sort works fine, but it can be made a tiny bit faster by removing the call to `swap()`. You've seen that we swap numbers to move the next element into its sorted position: [ 3, 5, 8, 4 | 6 ] <--> swap [ 3, 5, 4, 8 | 6 ] <--> swap Instead of swapping with each of the previous elements, we can just shift all those elements one position to the right, and then copy the new number into the right position. [ 3, 5, 8, 4 | 6 ] remember 4 * [ 3, 5, 8, 8 | 6 ] shift 8 to the right ---> [ 3, 5, 5, 8 | 6 ] shift 5 to the right ---> [ 3, 4, 5, 8 | 6 ] copy 4 into place * In code that looks like this: ```swift func insertionSort(_ array: [Int]) -> [Int] { var sortedArray = array for index in 1.. 0 && temp < sortedArray[currentIndex - 1] { sortedArray[currentIndex] = sortedArray[currentIndex - 1] // 1 currentIndex -= 1 } sortedArray[currentIndex] = temp // 2 } return sortedArray } ``` The line at `//1` is what shifts up the previous elements by one position. At the end of the inner loop, `y` is the destination index for the new number in the sorted portion, and the line at `//2` copies this number into place. ## Making it generic It would be nice to sort other things than just numbers. We can make the datatype of the array generic and use a user-supplied function (or closure) to perform the less-than comparison. This only requires two changes to the code. The function signature becomes: ```swift func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { ``` The array has type `[T]` where `T` is the placeholder type for the generics. Now `insertionSort()` will accept any kind of array, whether it contains numbers, strings, or something else. The new parameter `isOrderedBefore: (T, T) -> Bool` is a function that takes two `T` objects and returns true if the first object comes before the second, and false if the second object should come before the first. This is exactly what Swift's built-in `sort()` function does. The only other change is in the inner loop, which now becomes: ```swift while y > 0 && isOrderedBefore(temp, a[y - 1]) { ``` Instead of writing `temp < a[y - 1]`, we call the `isOrderedBefore()` function. It does the exact same thing, except we can now compare any kind of object, not just numbers. To test this in a playground, do: ```swift let numbers = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] insertionSort(numbers, <) insertionSort(numbers, >) ``` The `<` and `>` determine the sort order, low-to-high and high-to-low, respectively. Of course, you can also sort other things such as strings, ```swift let strings = [ "b", "a", "d", "c", "e" ] insertionSort(strings, <) ``` or even more complex objects: ```swift let objects = [ obj1, obj2, obj3, ... ] insertionSort(objects) { $0.priority < $1.priority } ``` The closure tells `insertionSort()` to sort on the `priority` property of the objects. Insertion sort is a *stable* sort. A sort is stable when elements that have identical sort keys remain in the same relative order after sorting. This is not important for simple values such as numbers or strings, but it is important when sorting more complex objects. In the example above, if two objects have the same `priority`, regardless of the values of their other properties, those two objects don't get swapped around. ## Performance Insertion sort is really fast if the array is already sorted. That sounds obvious, but this is not true for all search algorithms. In practice, a lot of data will already be largely -- if not entirely -- sorted and insertion sort works quite well in that case. The worst-case and average case performance of insertion sort is **O(n^2)**. That's because there are two nested loops in this function. Other sort algorithms, such as quicksort and merge sort, have **O(n log n)** performance, which is faster on large inputs. Insertion sort is actually very fast for sorting small arrays. Some standard libraries have sort functions that switch from a quicksort to insertion sort when the partition size is 10 or less. I did a quick test comparing our `insertionSort()` with Swift's built-in `sort()`. On arrays of about 100 items or so, the difference in speed is tiny. However, as your input becomes larger, **O(n^2)** quickly starts to perform a lot worse than **O(n log n)** and insertion sort just can't keep up. ## See also [Insertion sort on Wikipedia](https://en.wikipedia.org/wiki/Insertion_sort) *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Insertion Sort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Insertion Sort/Tests/InsertionSortTests.swift ================================================ import XCTest class InsertionSortTests: XCTestCase { func testInsertionSort() { checkSortAlgorithm(insertionSort) } } ================================================ FILE: Insertion Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */; }; 7B80C3EC1C77A536003CECC7 /* InsertionSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3EB1C77A536003CECC7 /* InsertionSortTests.swift */; }; 7B80C3EE1C77A53E003CECC7 /* InsertionSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3ED1C77A53E003CECC7 /* InsertionSort.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = ../../Quicksort/Tests/SortingTestHelpers.swift; sourceTree = SOURCE_ROOT; }; 7B80C3EB1C77A536003CECC7 /* InsertionSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InsertionSortTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3ED1C77A53E003CECC7 /* InsertionSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InsertionSort.swift; path = ../InsertionSort.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3ED1C77A53E003CECC7 /* InsertionSort.swift */, 7B80C3EB1C77A536003CECC7 /* InsertionSortTests.swift */, 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */, 7B80C3EE1C77A53E003CECC7 /* InsertionSort.swift in Sources */, 7B80C3EC1C77A536003CECC7 /* InsertionSortTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Insertion Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Insertion Sort/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Insertion Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Introsort/HeapSort.swift ================================================ import Foundation private func shiftDown(_ elements: inout [T], _ index: Int, _ range: Range, by areInIncreasingOrder: (T, T) -> Bool) { let countToIndex = elements.distance(from: range.lowerBound, to: index) let countFromIndex = elements.distance(from: index, to: range.upperBound) guard countToIndex + 1 < countFromIndex else { return } let left = elements.index(index, offsetBy: countToIndex + 1) var largest = index if areInIncreasingOrder(elements[largest], elements[left]) { largest = left } if countToIndex + 2 < countFromIndex { let right = elements.index(after: left) if areInIncreasingOrder(elements[largest], elements[right]) { largest = right } } if largest != index { elements.swapAt(index, largest) shiftDown(&elements, largest, range, by: areInIncreasingOrder) } } private func heapify(_ list: inout [T], _ range: Range, by areInIncreasingOrder: (T, T) -> Bool) { let root = range.lowerBound var node = list.index(root, offsetBy: list.distance(from: range.lowerBound, to: range.upperBound)/2) while node != root { list.formIndex(before: &node) shiftDown(&list, node, range, by: areInIncreasingOrder) } } public func heapsort(for array: inout [T], range: Range, by areInIncreasingOrder: (T, T) -> Bool) { var hi = range.upperBound let lo = range.lowerBound heapify(&array, range, by: areInIncreasingOrder) array.formIndex(before: &hi) while hi != lo { array.swapAt(lo, hi) shiftDown(&array, lo, lo..(for array: inout [T], range: Range, by areInIncreasingOrder: (T, T) -> Bool) { guard !range.isEmpty else { return } let start = range.lowerBound var sortedEnd = start array.formIndex(after: &sortedEnd) while sortedEnd != range.upperBound { let x = array[sortedEnd] var i = sortedEnd repeat { let predecessor = array[array.index(before: i)] guard areInIncreasingOrder(x, predecessor) else { break } array[i] = predecessor array.formIndex(before: &i) } while i != start if i != sortedEnd { array[i] = x } array.formIndex(after: &sortedEnd) } } ================================================ FILE: Introsort/IntroSort.swift ================================================ import Foundation public func introsort(_ array: inout [T], by areInIncreasingOrder: (T, T) -> Bool) { //The depth limit is as best practice 2 * log( n ) let depthLimit = 2 * floor(log2(Double(array.count))) introSortImplementation(for: &array, range: 0..(for array: inout [T], range: Range, depthLimit: Int, by areInIncreasingOrder: (T, T) -> Bool) { if array.distance(from: range.lowerBound, to: range.upperBound) < 20 { //if the partition count is less than 20 we can sort it using insertion sort. This algorithm in fact performs well on collections //of this size, plus, at this point is quite probable that the quisksort part of the algorithm produced a partition which is //nearly sorted. As we knoe insertion sort tends to O( n ) if this is the case. insertionSort(for: &array, range: range, by: areInIncreasingOrder) } else if depthLimit == 0 { //If we reached the depth limit for this recursion branch, it's possible that we are hitting quick sort's worst case. //Since quicksort degrades to O( n^2 ) in its worst case we stop using quicksort for this recursion branch and we switch to heapsort. //Our preference remains quicksort, and we hope to be rare to see this condition to be true heapsort(for: &array, range: range, by: areInIncreasingOrder) } else { //By default we use quicksort to sort our collection. The partition index method chose a pivot, and puts all the //elements less than pivot on the left, and the ones bigger than pivot on the right. At the end of the operation the //position of the pivot in the array is returned so that we can form the two partitions. let partIdx = partitionIndex(for: &array, subRange: range, by: areInIncreasingOrder) //We can recursively call introsort implementation, decreasing the depthLimit for the left partition and the right partition. introSortImplementation(for: &array, range: range.lowerBound..(_ array: inout [T], by areInIncreasingOrder: (T, T) -> Bool) { //The depth limit is as best practice 2 * log( n ) let depthLimit = 2 * floor(log2(Double(array.count))) introSortImplementation(for: &array, range: 0..(for array: inout [T], range: Range, depthLimit: Int, by areInIncreasingOrder: (T, T) -> Bool) { if array.distance(from: range.lowerBound, to: range.upperBound) < 20 { //if the partition count is less than 20 we can sort it using insertion sort. This algorithm in fact performs well on collections //of this size, plus, at this point is quite probable that the quisksort part of the algorithm produced a partition which is //nearly sorted. As we knoe insertion sort tends to O( n ) if this is the case. insertionSort(for: &array, range: range, by: areInIncreasingOrder) } else if depthLimit == 0 { //If we reached the depth limit for this recursion branch, it's possible that we are hitting quick sort's worst case. //Since quicksort degrades to O( n^2 ) in its worst case we stop using quicksort for this recursion branch and we switch to heapsort. //Our preference remains quicksort, and we hope to be rare to see this condition to be true heapsort(for: &array, range: range, by: areInIncreasingOrder) } else { //By default we use quicksort to sort our collection. The partition index method chose a pivot, and puts all the //elements less than pivot on the left, and the ones bigger than pivot on the right. At the end of the operation the //position of the pivot in the array is returned so that we can form the two partitions. let partIdx = partitionIndex(for: &array, subRange: range, by: areInIncreasingOrder) //We can recursively call introsort implementation, decreasing the depthLimit for the left partition and the right partition. introSortImplementation(for: &array, range: range.lowerBound..(_ elements: inout [T], _ index: Int, _ range: Range, by areInIncreasingOrder: (T, T) -> Bool) { let countToIndex = elements.distance(from: range.lowerBound, to: index) let countFromIndex = elements.distance(from: index, to: range.upperBound) guard countToIndex + 1 < countFromIndex else { return } let left = elements.index(index, offsetBy: countToIndex + 1) var largest = index if areInIncreasingOrder(elements[largest], elements[left]) { largest = left } if countToIndex + 2 < countFromIndex { let right = elements.index(after: left) if areInIncreasingOrder(elements[largest], elements[right]) { largest = right } } if largest != index { elements.swapAt(index, largest) shiftDown(&elements, largest, range, by: areInIncreasingOrder) } } private func heapify(_ list: inout [T], _ range: Range, by areInIncreasingOrder: (T, T) -> Bool) { let root = range.lowerBound var node = list.index(root, offsetBy: list.distance(from: range.lowerBound, to: range.upperBound)/2) while node != root { list.formIndex(before: &node) shiftDown(&list, node, range, by: areInIncreasingOrder) } } public func heapsort(for array: inout [T], range: Range, by areInIncreasingOrder: (T, T) -> Bool) { var hi = range.upperBound let lo = range.lowerBound heapify(&array, range, by: areInIncreasingOrder) array.formIndex(before: &hi) while hi != lo { array.swapAt(lo, hi) shiftDown(&array, lo, lo..(for array: inout [T], range: Range, by areInIncreasingOrder: (T, T) -> Bool) { guard !range.isEmpty else { return } let start = range.lowerBound var sortedEnd = start array.formIndex(after: &sortedEnd) while sortedEnd != range.upperBound { let x = array[sortedEnd] var i = sortedEnd repeat { let predecessor = array[array.index(before: i)] guard areInIncreasingOrder(x, predecessor) else { break } array[i] = predecessor array.formIndex(before: &i) } while i != start if i != sortedEnd { array[i] = x } array.formIndex(after: &sortedEnd) } } ================================================ FILE: Introsort/Introsort.playground/Sources/Partition.swift ================================================ import Foundation public func partitionIndex(for elements: inout [T], subRange range: Range, by areInIncreasingOrder: (T, T) -> Bool) -> Int { var lo = range.lowerBound var hi = elements.index(before: range.upperBound) // Sort the first, middle, and last elements, then use the middle value // as the pivot for the partition. let half = elements.distance(from: lo, to: hi) / 2 let mid = elements.index(lo, offsetBy: half) sort3(in: &elements, a: lo, b: mid, c: hi, by: areInIncreasingOrder) let pivot = elements[mid] while true { elements.formIndex(after: &lo) guard findLo(in: elements, pivot: pivot, from: &lo, to: hi, by: areInIncreasingOrder) else { break } elements.formIndex(before: &hi) guard findHi(in: elements, pivot: pivot, from: lo, to: &hi, by: areInIncreasingOrder) else { break } elements.swapAt(lo, hi) } return lo } private func findLo(in array: [T], pivot: T, from lo: inout Int, to hi: Int, by areInIncreasingOrder: (T, T)->Bool) -> Bool { while lo != hi { if !areInIncreasingOrder(array[lo], pivot) { return true } array.formIndex(after: &lo) } return false } private func findHi(in array: [T], pivot: T, from lo: Int, to hi: inout Int, by areInIncreasingOrder: (T, T)->Bool) -> Bool { while hi != lo { if areInIncreasingOrder(array[hi], pivot) { return true } array.formIndex(before: &hi) } return false } ================================================ FILE: Introsort/Introsort.playground/Sources/Randomize.swift ================================================ import Foundation public func randomize(n: Int) -> [Int] { var unsorted = [Int]() for _ in 0..(in array: inout [T], a: Int, b: Int, c: Int, by areInIncreasingOrder: (T, T) -> Bool) { switch (areInIncreasingOrder(array[b], array[a]), areInIncreasingOrder(array[c], array[b])) { case (false, false): break case (true, true): array.swapAt(a, c) case (true, false): array.swapAt(a, b) if areInIncreasingOrder(array[c], array[b]) { array.swapAt(b, c) } case (false, true): array.swapAt(b, c) if areInIncreasingOrder(array[b], array[a]) { array.swapAt(a, b) } } } ================================================ FILE: Introsort/Introsort.playground/contents.xcplayground ================================================ ================================================ FILE: Introsort/Partition.swift ================================================ import Foundation public func partitionIndex(for elements: inout [T], subRange range: Range, by areInIncreasingOrder: (T, T) -> Bool) -> Int { var lo = range.lowerBound var hi = elements.index(before: range.upperBound) // Sort the first, middle, and last elements, then use the middle value // as the pivot for the partition. let half = elements.distance(from: lo, to: hi) / 2 let mid = elements.index(lo, offsetBy: half) sort3(in: &elements, a: lo, b: mid, c: hi, by: areInIncreasingOrder) let pivot = elements[mid] while true { elements.formIndex(after: &lo) guard findLo(in: elements, pivot: pivot, from: &lo, to: hi, by: areInIncreasingOrder) else { break } elements.formIndex(before: &hi) guard findHi(in: elements, pivot: pivot, from: lo, to: &hi, by: areInIncreasingOrder) else { break } elements.swapAt(lo, hi) } return lo } private func findLo(in array: [T], pivot: T, from lo: inout Int, to hi: Int, by areInIncreasingOrder: (T, T)->Bool) -> Bool { while lo != hi { if !areInIncreasingOrder(array[lo], pivot) { return true } array.formIndex(after: &lo) } return false } private func findHi(in array: [T], pivot: T, from lo: Int, to hi: inout Int, by areInIncreasingOrder: (T, T)->Bool) -> Bool { while hi != lo { if areInIncreasingOrder(array[hi], pivot) { return true } array.formIndex(before: &hi) } return false } ================================================ FILE: Introsort/README.markdown ================================================ # IntroSort Goal: Sort an array from low to high (or high to low). IntroSort is the algorithm used by Swift to sort a collection. Introsort is an hybrid algorithm invented by David Musser in 1993 with the purpose of giving a generic sorting algorithm for the C++ standard library. The classic implementation of introsort uses a recursive Quicksort with a fallback to Heapsort in the case where the recursion depth level reached a certain maximum value. The maximum depends on the number of elements in the collection and it is usually 2 * log(n). The reason behind this “fallback” is that if Quicksort was not able to get the solution after 2 * log(n) recursions for a branch, probably it hit its worst case and it is degrading to complexity O( n^2 ). To optimise even further this algorithm, the Swift implementation introduce an extra step in each recursion where the partition is sorted using InsertionSort if the count of the partition is less than 20. The number 20 is an empiric number obtained observing the behaviour of InsertionSort with lists of this size. Here's an implementation in pseudocode: ``` procedure sort(A : array): let maxdepth = ⌊log(length(A))⌋ × 2 introSort(A, maxdepth) procedure introsort(A, maxdepth): n ← length(A) if n < 20: insertionsort(A) else if maxdepth = 0: heapsort(A) else: p ← partition(A) // the pivot is selected using median of 3 introsort(A[0:p], maxdepth - 1) introsort(A[p+1:n], maxdepth - 1) ``` ## An example Let's walk through the example. The array is initially: [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] For this example let's assume that `maxDepth` is **2** and that the size of the partition for the insertionSort to kick in is **5** The first iteration of introsort begins by attempting to use insertionSort. The collection has 13 elements, so it tries to do heapsort instead. The condition for heapsort to occur is if `maxdepth == 0` evaluates true. Since `maxdepth` is currently **2** for the first iteration, introsort will default to quicksort. The `partition` method picks the first element, the median and the last, it sorts them and uses the new median as pivot. [ 10, 8, 26 ] -> [ 8, 10, 26 ] Our array is now [ 8, 0, 3, 9, 2, 14, 10, 27, 1, 5, 8, -1, 26 ] **10** is the pivot. After the choice of the pivot, the `partition` method swaps elements to get all the elements less than pivot on the left, and all the elements more or equal than pivot on the right. [ 8, 0, 3, 9, 2, 1, 5, 8, -1, 10, 27, 14, 26 ] Because of the swaps, the index of of pivot is now changed and returned. The next step of introsort is to call recursively itself for the two sub arrays: less: [ 8, 0, 3, 9, 2, 1, 5, 8, -1, 10 ] greater: [ 27, 14, 26 ] ## maxDepth: 1, branch: less [ 8, 0, 3, 9, 2, 1, 5, 8, -1, 10 ] The count of the array is still more than 5 so we don't meet yet the conditions for insertion sort to kick in. At this iteration maxDepth is decreased by one but it is still more than zero, so heapsort will not act. Just like in the previous iteration quicksort wins and the `partition` method choses a pivot and sorts the elemets less than pivot on the left and the elements more or equeal than pivot on the right. array: [ 8, 0, 3, 9, 2, 1, 5, 8, -1, 10 ] pivot candidates: [ 8, 1, 10] -> [ 1, 8, 10] pivot: 8 before partition: [ 1, 0, 3, 9, 2, 8, 5, 8, -1, 10 ] after partition: [ 1, 0, 3, -1, 2, 5, 8, 8, 9, 10 ] less: [ 1, 0, 3, -1, 2, 5, 8 ] greater: [ 8, 9, 10 ] ## maxDepth: 0, branch: less [ 1, 0, 3, -1, 2, 5, 8 ] Just like before, introsort is recursively executed for `less` and greater. This time `less`has a count more than **5** so it will not be sorted with insertion sort, but the maxDepth decreased again by 1 is now 0 and heapsort takes over sorting the array. heapsort -> [ -1, 0, 1, 2, 3, 5, 8 ] ## maxDepth: 0, branch: greater [ 8, 9, 10 ] following greater in this recursion, the count of elements is 3, which is less than 5, so this partition is sorted using insertionSort. insertionSort -> [ 8, 9 , 10] ## back to maxDepth = 1, branch: greater [ 27, 14, 26 ] At this point the original array has mutated to be [ -1, 0, 1, 2, 3, 5, 8, 8, 9, 10, 27, 14, 26 ] now the `less` partition is sorted and since the count of the `greater` partition is 3 it will be sorted with insertion sort `[ 14, 26, 27 ]` The array is now successfully sorted [ -1, 0, 1, 2, 3, 5, 8, 8, 9, 10, 14, 26, 27 ] ## See also [Introsort on Wikipedia](https://en.wikipedia.org/wiki/Introsort) [Introsort comparison with other sorting algorithms](http://agostini.tech/2017/12/18/swift-sorting-algorithm/) [Introsort implementation from the Swift standard library](https://github.com/apple/swift/blob/09f77ff58d250f5d62855ea359fc304f40b531df/stdlib/public/core/Sort.swift.gyb) *Written for Swift Algorithm Club by Giuseppe Lanza* ================================================ FILE: Introsort/Randomize.swift ================================================ import Foundation public func randomize(n: Int) -> [Int] { var unsorted = [Int]() for _ in 0..(in array: inout [T], a: Int, b: Int, c: Int, by areInIncreasingOrder: (T, T) -> Bool) { switch (areInIncreasingOrder(array[b], array[a]), areInIncreasingOrder(array[c], array[b])) { case (false, false): break case (true, true): array.swapAt(a, c) case (true, false): array.swapAt(a, b) if areInIncreasingOrder(array[c], array[b]) { array.swapAt(b, c) } case (false, true): array.swapAt(b, c) if areInIncreasingOrder(array[b], array[a]) { array.swapAt(a, b) } } } ================================================ FILE: K-Means/KMeans.swift ================================================ import Foundation class KMeans { let numCenters: Int let labels: [Label] private(set) var centroids = [Vector]() init(labels: [Label]) { assert(labels.count > 1, "Exception: KMeans with less than 2 centers.") self.labels = labels self.numCenters = labels.count } private func indexOfNearestCenter(_ x: Vector, centers: [Vector]) -> Int { var nearestDist = Double.greatestFiniteMagnitude var minIndex = 0 for (idx, center) in centers.enumerated() { let dist = x.distanceTo(center) if dist < nearestDist { minIndex = idx nearestDist = dist } } return minIndex } func trainCenters(_ points: [Vector], convergeDistance: Double) { let zeroVector = Vector([Double](repeating: 0, count: points[0].length)) // Randomly take k objects from the input data to make the initial centroids. var centers = reservoirSample(points, k: numCenters) var centerMoveDist = 0.0 repeat { // This array keeps track of which data points belong to which centroids. var classification: [[Vector]] = .init(repeating: [], count: numCenters) // For each data point, find the centroid that it is closest to. for p in points { let classIndex = indexOfNearestCenter(p, centers: centers) classification[classIndex].append(p) } // Take the average of all the data points that belong to each centroid. // This moves the centroid to a new position. let newCenters = classification.map { assignedPoints in assignedPoints.reduce(zeroVector, +) / Double(assignedPoints.count) } // Find out how far each centroid moved since the last iteration. If it's // only a small distance, then we're done. centerMoveDist = 0.0 for idx in 0.. convergeDistance centroids = centers } func fit(_ point: Vector) -> Label { assert(!centroids.isEmpty, "Exception: KMeans tried to fit on a non trained model.") let centroidIndex = indexOfNearestCenter(point, centers: centroids) return labels[centroidIndex] } func fit(_ points: [Vector]) -> [Label] { assert(!centroids.isEmpty, "Exception: KMeans tried to fit on a non trained model.") return points.map(fit) } } // Pick k random elements from samples func reservoirSample(_ samples: [T], k: Int) -> [T] { var result = [T]() // Fill the result array with first k elements for i in 0.. **Note:** These examples are contrived to show the exact nature of k-Means and finding clusters. The clusters in these examples are very easily identified by human eyes: we see there is one in the lower left corner, one in the upper right corner, and maybe one in the middle. In practice, however, data may have many dimensions and may be impossible to visualize. In such cases, k-Means is much better at this job than human eyes! #### Bad clustering The next two examples highlight the unpredictability of k-Means and how it does not always find the best clustering. ![Bad Clustering 1](Images/k_means_bad1.png) As you can see in this example, the initial centroids were all a little too close to one another, and the blue one didn't quite get to a good place. By adjusting the convergence distance we should be able to improve the fit of our centroids to the data. ![Bad Clustering 1](Images/k_means_bad2.png) In this example, the blue cluster never really could separate from the red cluster and as such sort of got stuck down there. #### Improving bad clustering In these examples of "bad" clustering, the algorithm got stuck in a local optimum. It does find clusters but they're not the best way to divide up the data. To increase your chances of success, you can run the algorithm several times, each time with different points as the initial centroids. You choose the clustering that gives the best results. To calculate how "good" the clustering is, you find the distance of each data point to its cluster, and add up all these distances. The lower this number, the better! That means each cluster is really in the center of a group of data points, and all clusters are roughly the same size and are spaced evenly apart. ## The code This is what the algorithm could look like in Swift. The `points` array contains the input data as `Vector` objects. The output is an array of `Vector` objects representing the clusters that were found. ```swift func kMeans(numCenters: Int, convergeDistance: Double, points: [Vector]) -> [Vector] { // Randomly take k objects from the input data to make the initial centroids. var centers = reservoirSample(points, k: numCenters) // This loop repeats until we've reached convergence, i.e. when the centroids // have moved less than convergeDistance since the last iteration. var centerMoveDist = 0.0 repeat { // In each iteration of the loop, we move the centroids to a new position. // The newCenters array contains those new positions. let zeros = [Double](count: points[0].length, repeatedValue: 0) var newCenters = [Vector](count: numCenters, repeatedValue: Vector(zeros)) // We keep track of how many data points belong to each centroid, so we // can calculate the average later. var counts = [Double](count: numCenters, repeatedValue: 0) // For each data point, find the centroid that it is closest to. We also // add up the data points that belong to that centroid, in order to compute // that average. for p in points { let c = indexOfNearestCenter(p, centers: centers) newCenters[c] += p counts[c] += 1 } // Take the average of all the data points that belong to each centroid. // This moves the centroid to a new position. for idx in 0.. convergeDistance return centers } ``` > **Note:** The code in [KMeans.swift](KMeans.swift) is slightly more advanced than the above listing. It also assigns labels to the clusters and has a few other tricks up its sleeve. Check it out! ## Performance k-Means is classified as an NP-Hard type of problem. That means it's almost impossible to find the optimal solution. The selection of the initial centroids has a big effect on how the resulting clusters may end up. Finding an exact solution is not likely -- even in 2 dimensional space. As seen from the steps above the complexity really isn't that bad -- it is often considered to be on the order of **O(kndi)**, where **k** is the number of centroids, **n** is the number of **d**-dimensional vectors, and **i** is the number of iterations for convergence. The amount of data has a linear effect on the running time of k-Means, but tuning how far you want the centroids to converge can have a big impact how many iterations will be done. As a general rule, **k** should be relatively small compared to the number of vectors. Often times as more data is added certain points may lie in the boundary between two centroids and as such those centroids would continue to bounce back and forth and the convergence distance would need to be tuned to prevent that. ## See Also [K-Means Clustering on Wikipedia](https://en.wikipedia.org/wiki/K-means_clustering) *Written by John Gill and Matthijs Hollemans* ================================================ FILE: K-Means/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: K-Means/Tests/KMeansTests.swift ================================================ // // Tests.swift // Tests // // Created by John Gill on 2/29/16. // // import Foundation import XCTest class KMeansTests: XCTestCase { func genPoints(_ numPoints: Int, numDimensions: Int) -> [Vector] { var points = [Vector]() for _ in 0..(labels: ["A", "B", "C"]) kmm.trainCenters(points, convergeDistance: 0.01) for (label, centroid) in zip(kmm.labels, kmm.centroids) { print("\(label): \(centroid)") } print("\nClassifications") for (label, point) in zip(kmm.fit(points), points) { print("\(label): \(point)") } } func testSmall_10D() { let points = genPoints(10, numDimensions: 10) print("\nCenters") let kmm = KMeans(labels: [1, 2, 3]) kmm.trainCenters(points, convergeDistance: 0.01) for c in kmm.centroids { print(c) } } func testLarge_2D() { let points = genPoints(10000, numDimensions: 2) print("\nCenters") let kmm = KMeans(labels: ["A", "B", "C", "D", "E"]) kmm.trainCenters(points, convergeDistance: 0.01) for c in kmm.centroids { print(c) } } func testLarge_10D() { let points = genPoints(10000, numDimensions: 10) print("\nCenters") let kmm = KMeans(labels: [1, 2, 3, 4, 5]) kmm.trainCenters(points, convergeDistance: 0.01) for c in kmm.centroids { print(c) } } } ================================================ FILE: K-Means/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ B80894E41C852D100018730E /* KMeansTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80894E31C852D100018730E /* KMeansTests.swift */; }; B80894EA1C852DA00018730E /* Vector.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80894E91C852DA00018730E /* Vector.swift */; }; B80894EB1C8530830018730E /* KMeans.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80894DB1C852CFA0018730E /* KMeans.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ B80894DB1C852CFA0018730E /* KMeans.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = KMeans.swift; path = ../KMeans.swift; sourceTree = SOURCE_ROOT; tabWidth = 2; }; B80894E01C852D100018730E /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B80894E31C852D100018730E /* KMeansTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMeansTests.swift; sourceTree = SOURCE_ROOT; }; B80894E51C852D100018730E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; B80894E91C852DA00018730E /* Vector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vector.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ B80894DD1C852D100018730E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ B80894D41C852CDC0018730E = { isa = PBXGroup; children = ( B80894E21C852D100018730E /* Tests */, B80894E11C852D100018730E /* Products */, ); sourceTree = ""; }; B80894E11C852D100018730E /* Products */ = { isa = PBXGroup; children = ( B80894E01C852D100018730E /* Tests.xctest */, ); name = Products; sourceTree = ""; }; B80894E21C852D100018730E /* Tests */ = { isa = PBXGroup; children = ( B80894DB1C852CFA0018730E /* KMeans.swift */, B80894E31C852D100018730E /* KMeansTests.swift */, B80894E91C852DA00018730E /* Vector.swift */, B80894E51C852D100018730E /* Info.plist */, ); path = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ B80894DF1C852D100018730E /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = B80894E61C852D100018730E /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( B80894DC1C852D100018730E /* Sources */, B80894DD1C852D100018730E /* Frameworks */, B80894DE1C852D100018730E /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = B80894E01C852D100018730E /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ B80894D51C852CDC0018730E /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; TargetAttributes = { B80894DF1C852D100018730E = { CreatedOnToolsVersion = 7.2.1; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = B80894D81C852CDC0018730E /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = B80894D41C852CDC0018730E; productRefGroup = B80894E11C852D100018730E /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( B80894DF1C852D100018730E /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ B80894DE1C852D100018730E /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ B80894DC1C852D100018730E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( B80894EA1C852DA00018730E /* Vector.swift in Sources */, B80894E41C852D100018730E /* KMeansTests.swift in Sources */, B80894EB1C8530830018730E /* KMeans.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ B80894D91C852CDC0018730E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; B80894DA1C852CDC0018730E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; B80894E71C852D100018730E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.alvahouse322.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; }; name = Debug; }; B80894E81C852D100018730E /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = com.alvahouse322.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ B80894D81C852CDC0018730E /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( B80894D91C852CDC0018730E /* Debug */, B80894DA1C852CDC0018730E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; B80894E61C852D100018730E /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( B80894E71C852D100018730E /* Debug */, B80894E81C852D100018730E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = B80894D51C852CDC0018730E /* Project object */; } ================================================ FILE: K-Means/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: K-Means/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: K-Means/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: K-Means/Tests/Vector.swift ================================================ import Foundation struct Vector: CustomStringConvertible, Equatable { private(set) var length = 0 private(set) var data: [Double] init(_ data: [Double]) { self.data = data self.length = data.count } var description: String { return "Vector (\(data)" } func distanceTo(_ other: Vector) -> Double { var result = 0.0 for idx in 0.. Bool { for idx in 0.. Vector { var results = [Double]() for idx in 0.. Vector { var results = [Double]() for idx in 0.. Vector { var results = [Double](repeating: 0, count: left.length) for (idx, value) in left.data.enumerated() { results[idx] = value / right } return Vector(results) } func /= (left: inout Vector, right: Double) { left = left / right } ================================================ FILE: Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation precedencegroup ExponentiativePrecedence { higherThan: MultiplicationPrecedence lowerThan: BitwiseShiftPrecedence associativity: left } infix operator ^^: ExponentiativePrecedence func ^^ (radix: Int, power: Int) -> Int { return Int(pow(Double(radix), Double(power))) } // Long Multiplication - O(n^2) func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { let num1Array = String(num1).reversed().map { Int(String($0))! } let num2Array = String(num2).reversed().map { Int(String($0))! } var product = Array(repeating: 0, count: num1Array.count + num2Array.count) for i in num1Array.indices { var carry = 0 for j in num2Array.indices { product[i + j] += carry + num1Array[i] * num2Array[j] carry = product[i + j] / base product[i + j] %= base } product[i + num2Array.count] += carry } return Int(product.reversed().map { String($0) }.reduce("", +))! } // Karatsuba Multiplication - O(n^log2(3)) func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1String = String(num1) let num2String = String(num2) guard num1String.count > 1 && num2String.count > 1 else { return multiply(num1, by: num2) } let n = max(num1String.count, num2String.count) let nBy2 = n / 2 let a = num1 / 10^^nBy2 let b = num1 % 10^^nBy2 let c = num2 / 10^^nBy2 let d = num2 % 10^^nBy2 let ac = karatsuba(a, by: c) let bd = karatsuba(b, by: d) let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd return product } ================================================ FILE: Karatsuba Multiplication/KaratsubaMultiplication.playground/contents.xcplayground ================================================ ================================================ FILE: Karatsuba Multiplication/KaratsubaMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Karatsuba Multiplication/KaratsubaMultiplication.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Karatsuba Multiplication/KaratsubaMultiplication.swift ================================================ // // KaratsubaMultiplication.swift // // // Created by Richard Ash on 9/12/16. // // import Foundation precedencegroup ExponentiativePrecedence { higherThan: MultiplicationPrecedence lowerThan: BitwiseShiftPrecedence associativity: left } infix operator ^^: ExponentiativePrecedence func ^^ (radix: Int, power: Int) -> Int { return Int(pow(Double(radix), Double(power))) } // Long Multiplication - O(n^2) func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { let num1Array = String(num1).reversed().map { Int(String($0))! } let num2Array = String(num2).reversed().map { Int(String($0))! } var product = Array(repeating: 0, count: num1Array.count + num2Array.count) for i in num1Array.indices { var carry = 0 for j in num2Array.indices { product[i + j] += carry + num1Array[i] * num2Array[j] carry = product[i + j] / base product[i + j] %= base } product[i + num2Array.count] += carry } return Int(product.reversed().map { String($0) }.reduce("", +))! } // Karatsuba Multiplication - O(n^log2(3)) func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1String = String(num1) let num2String = String(num2) guard num1String.count > 1 && num2String.count > 1 else { return multiply(num1, by: num2) } let n = max(num1String.count, num2String.count) let nBy2 = n / 2 let a = num1 / 10^^nBy2 let b = num1 % 10^^nBy2 let c = num2 / 10^^nBy2 let d = num2 % 10^^nBy2 let ac = karatsuba(a, by: c) let bd = karatsuba(b, by: d) let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd return product } ================================================ FILE: Karatsuba Multiplication/README.markdown ================================================ # Karatsuba Multiplication Goal: To quickly multiply two numbers together ## Long Multiplication In grade school we learned how to multiply two numbers together via Long Multiplication. Let's try that first! ### Example 1: Multiply 1234 by 5678 using Long Multiplication 5678 *1234 ------ 22712 17034- 11356-- 5678--- -------- 7006652 So what's the problem with Long Multiplication? Well remember the first part of our goal. To *quickly* multiply two numbers together. Long Multiplication is slow! (**O(n^2)**) You can see where the **O(n^2)** comes from in the implementation of Long Multiplication: ```swift // Long Multiplication func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { let num1Array = String(num1).characters.reversed().map{ Int(String($0))! } let num2Array = String(num2).characters.reversed().map{ Int(String($0))! } var product = Array(repeating: 0, count: num1Array.count + num2Array.count) for i in num1Array.indices { var carry = 0 for j in num2Array.indices { product[i + j] += carry + num1Array[i] * num2Array[j] carry = product[i + j] / base product[i + j] %= base } product[i + num2Array.count] += carry } return Int(product.reversed().map{ String($0) }.reduce("", +))! } ``` The double for loop is the culprit! By comparing each of the digits (as is necessary!) we set ourselves up for an **O(n^2)** running time. So Long Multiplication might not be the best algorithm after all. Can we do better? ## Karatsuba Multiplication The Karatsuba Algorithm was discovered by Anatoly Karatsuba and published in 1962. Karatsuba discovered that you could compute the product of two large numbers using three smaller products and some addition and subtraction. For two numbers x, y, where m <= n: x = a*10^m + b y = c*10^m + d Now, we can say: x*y = (a*10^m + b) * (c*10^m + d) = a*c*10^(2m) + (a*d + b*c)*10^(m) + b*d This had been know since the 19th century. The problem is that the method requires 4 multiplications (`a*c`, `a*d`, `b*c`, `b*d`). Karatsuba's insight was that you only need three! (`a*c`, `b*d`, `(a+b)*(c+d)`). Now a perfectly valid question right now would be "How is that possible!?!" Here's the math: (a+b)*(c+d) - a*c - b*d = (a*c + a*d + b*c + b*d) - a*c - b*d = (a*d + b*c) Pretty cool, huh? Here's the full implementation. Note that the recursive algorithm is most efficient at m = n/2. ```swift // Karatsuba Multiplication func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1String = String(num1) let num2String = String(num2) guard num1String.count > 1 && num2String.count > 1 else { return multiply(num1, by: num2) } let n = max(num1String.count, num2String.count) let nBy2 = n / 2 let a = num1 / 10^^nBy2 let b = num1 % 10^^nBy2 let c = num2 / 10^^nBy2 let d = num2 % 10^^nBy2 let ac = karatsuba(a, by: c) let bd = karatsuba(b, by: d) let adPlusbc = karatsuba(a+b, by: c+d) - ac - bd let product = ac * 10^^(2 * nBy2) + adPlusbc * 10^^nBy2 + bd return product } ``` What about the running time of this algorithm? Is all this extra work worth it? We can use the Master Theorem to answer this question. This leads us to `T(n) = 3*T(n/2) + c*n + d` where c & d are some constants. It follows (because 3 > 2^1) that the running time is **O(n^log2(3))** which is roughly **O(n^1.56)**. Much better! ### Example 2: Multiply 1234 by 5678 using Karatsuba Multiplication m = 2 x = 1234 = a*10^2 + b = 12*10^2 + 34 y = 5678 = c*10^2 + d = 56*10^2 + 78 a*c = 672 b*d = 2652 (a*d + b*c) = 2840 x*y = 672*10^4 + 2840*10^2 + 2652 = 6720000 + 284000 + 2652 = 7006652 ## Resources [Wikipedia](https://en.wikipedia.org/wiki/Karatsuba_algorithm) [WolframMathWorld](http://mathworld.wolfram.com/KaratsubaMultiplication.html) [Master Theorem](https://en.wikipedia.org/wiki/Master_theorem) *Written for Swift Algorithm Club by Richard Ash* ================================================ FILE: Karatsuba Multiplication/Tests/KaratsubaMultiplicationTests.swift ================================================ // // KaratsubaMultiplicationTests.swift // Tests // // Created by Afonso Graça on 8/10/18. // import XCTest final class KaratsubaMultiplicationTests: XCTestCase { func testReadmeExample() { let subject = karatsuba(1234, by: 5678) XCTAssertEqual(subject, 7006652) } } ================================================ FILE: Karatsuba Multiplication/Tests/Tests/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Karatsuba Multiplication/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 50; objects = { /* Begin PBXBuildFile section */ 6AF099AC216B54E200F69B16 /* KaratsubaMultiplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AF099AB216B54E200F69B16 /* KaratsubaMultiplication.swift */; }; 6AF099AE216B55A100F69B16 /* KaratsubaMultiplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AF099AD216B55A100F69B16 /* KaratsubaMultiplicationTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 6AF099A2216B54D500F69B16 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6AF099A7216B54D500F69B16 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Tests/Info.plist; sourceTree = SOURCE_ROOT; }; 6AF099AB216B54E200F69B16 /* KaratsubaMultiplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = KaratsubaMultiplication.swift; path = ../KaratsubaMultiplication.swift; sourceTree = ""; }; 6AF099AD216B55A100F69B16 /* KaratsubaMultiplicationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KaratsubaMultiplicationTests.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 6AF0999F216B54D500F69B16 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 6AF09997216B545D00F69B16 = { isa = PBXGroup; children = ( 6AF099AB216B54E200F69B16 /* KaratsubaMultiplication.swift */, 6AF099A4216B54D500F69B16 /* Tests */, 6AF099A3216B54D500F69B16 /* Products */, ); sourceTree = ""; }; 6AF099A3216B54D500F69B16 /* Products */ = { isa = PBXGroup; children = ( 6AF099A2216B54D500F69B16 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 6AF099A4216B54D500F69B16 /* Tests */ = { isa = PBXGroup; children = ( 6AF099AD216B55A100F69B16 /* KaratsubaMultiplicationTests.swift */, 6AF099A7216B54D500F69B16 /* Info.plist */, ); name = Tests; sourceTree = SOURCE_ROOT; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 6AF099A1216B54D500F69B16 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 6AF099A8216B54D500F69B16 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 6AF0999E216B54D500F69B16 /* Sources */, 6AF0999F216B54D500F69B16 /* Frameworks */, 6AF099A0216B54D500F69B16 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = 6AF099A2216B54D500F69B16 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 6AF09998216B545D00F69B16 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1000; LastUpgradeCheck = 1000; TargetAttributes = { 6AF099A1216B54D500F69B16 = { CreatedOnToolsVersion = 10.0; }; }; }; buildConfigurationList = 6AF0999B216B545D00F69B16 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 6AF09997216B545D00F69B16; productRefGroup = 6AF099A3216B54D500F69B16 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 6AF099A1216B54D500F69B16 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 6AF099A0216B54D500F69B16 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 6AF0999E216B54D500F69B16 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 6AF099AE216B55A100F69B16 /* KaratsubaMultiplicationTests.swift in Sources */, 6AF099AC216B54E200F69B16 /* KaratsubaMultiplication.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 6AF0999C216B545D00F69B16 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Debug; }; 6AF0999D216B545D00F69B16 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Release; }; 6AF099A9216B54D500F69B16 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.2; }; name = Debug; }; 6AF099AA216B54D500F69B16 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 6AF0999B216B545D00F69B16 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 6AF0999C216B545D00F69B16 /* Debug */, 6AF0999D216B545D00F69B16 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 6AF099A8216B54D500F69B16 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 6AF099A9216B54D500F69B16 /* Debug */, 6AF099AA216B54D500F69B16 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 6AF09998216B545D00F69B16 /* Project object */; } ================================================ FILE: Karatsuba Multiplication/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play func ZetaAlgorithm(ptnr: String) -> [Int]? { let pattern = Array(ptnr) let patternLength: Int = pattern.count guard patternLength > 0 else { return nil } var zeta: [Int] = [Int](repeating: 0, count: patternLength) var left: Int = 0 var right: Int = 0 var k_1: Int = 0 var betaLength: Int = 0 var textIndex: Int = 0 var patternIndex: Int = 0 for k in 1 ..< patternLength { if k > right { patternIndex = 0 while k + patternIndex < patternLength && pattern[k + patternIndex] == pattern[patternIndex] { patternIndex = patternIndex + 1 } zeta[k] = patternIndex if zeta[k] > 0 { left = k right = k + zeta[k] - 1 } } else { k_1 = k - left + 1 betaLength = right - k + 1 if zeta[k_1 - 1] < betaLength { zeta[k] = zeta[k_1 - 1] } else if zeta[k_1 - 1] >= betaLength { textIndex = betaLength patternIndex = right + 1 while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } zeta[k] = patternIndex - k left = k right = patternIndex - 1 } } } return zeta } extension String { func indexesOf(ptnr: String) -> [Int]? { let text = Array(self) let pattern = Array(ptnr.characters) let textLength: Int = text.count let patternLength: Int = pattern.count guard patternLength > 0 else { return nil } var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength) var textIndex: Int = 0 var patternIndex: Int = 0 var indexes: [Int] = [Int]() /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ let zeta = ZetaAlgorithm(ptnr: ptnr) for patternIndex in (1 ..< patternLength).reversed() { textIndex = patternIndex + zeta![patternIndex] - 1 suffixPrefix[textIndex] = zeta![patternIndex] } /* Search stage: scanning the text for pattern matching */ textIndex = 0 patternIndex = 0 while textIndex + (patternLength - patternIndex - 1) < textLength { while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } if patternIndex == patternLength { indexes.append(textIndex - patternIndex) } if patternIndex == 0 { textIndex = textIndex + 1 } else { patternIndex = suffixPrefix[patternIndex - 1] } } guard !indexes.isEmpty else { return nil } return indexes } } /* Examples */ let dna = "ACCCGGTTTTAAAGAACCACCATAAGATATAGACAGATATAGGACAGATATAGAGACAAAACCCCATACCCCAATATTTTTTTGGGGAGAAAAACACCACAGATAGATACACAGACTACACGAGATACGACATACAGCAGCATAACGACAACAGCAGATAGACGATCATAACAGCAATCAGACCGAGCGCAGCAGCTTTTAAGCACCAGCCCCACAAAAAACGACAATFATCATCATATACAGACGACGACACGACATATCACACGACAGCATA" dna.indexesOf(ptnr: "CATA") // [20, 64, 130, 140, 166, 234, 255, 270] let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" concert.indexesOf(ptnr: "🎻🎷") // [6] ================================================ FILE: Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground ================================================ ================================================ FILE: Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Knuth-Morris-Pratt/KnuthMorrisPratt.swift ================================================ /* Knuth-Morris-Pratt algorithm for pattern/string matching The code is based on the book: "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" by Dan Gusfield Cambridge University Press, 1997 */ import Foundation extension String { func indexesOf(ptnr: String) -> [Int]? { let text = Array(self) let pattern = Array(ptnr) let textLength: Int = text.count let patternLength: Int = pattern.count guard patternLength > 0 else { return nil } var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength) var textIndex: Int = 0 var patternIndex: Int = 0 var indexes: [Int] = [Int]() /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ let zeta = ZetaAlgorithm(ptnr: ptnr) for patternIndex in (1 ..< patternLength).reversed() { textIndex = patternIndex + zeta![patternIndex] - 1 suffixPrefix[textIndex] = zeta![patternIndex] } /* Search stage: scanning the text for pattern matching */ textIndex = 0 patternIndex = 0 while textIndex + (patternLength - patternIndex - 1) < textLength { while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } if patternIndex == patternLength { indexes.append(textIndex - patternIndex) } if patternIndex == 0 { textIndex = textIndex + 1 } else { patternIndex = suffixPrefix[patternIndex - 1] } } guard !indexes.isEmpty else { return nil } return indexes } } ================================================ FILE: Knuth-Morris-Pratt/README.markdown ================================================ # Knuth-Morris-Pratt String Search Goal: Write a linear-time string matching algorithm in Swift that returns the indexes of all the occurrencies of a given pattern. In other words, we want to implement an `indexesOf(pattern: String)` extension on `String` that returns an array `[Int]` of integers, representing all occurrences' indexes of the search pattern, or `nil` if the pattern could not be found inside the string. For example: ```swift let dna = "ACCCGGTTTTAAAGAACCACCATAAGATATAGACAGATATAGGACAGATATAGAGACAAAACCCCATACCCCAATATTTTTTTGGGGAGAAAAACACCACAGATAGATACACAGACTACACGAGATACGACATACAGCAGCATAACGACAACAGCAGATAGACGATCATAACAGCAATCAGACCGAGCGCAGCAGCTTTTAAGCACCAGCCCCACAAAAAACGACAATFATCATCATATACAGACGACGACACGACATATCACACGACAGCATA" dna.indexesOf(ptnr: "CATA") // Output: [20, 64, 130, 140, 166, 234, 255, 270] let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" concert.indexesOf(ptnr: "🎻🎷") // Output: [6] ``` The [Knuth-Morris-Pratt algorithm](https://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm) is considered one of the best algorithms for solving the pattern matching problem. Although in practice [Boyer-Moore](../Boyer-Moore-Horspool/) is usually preferred, the algorithm that we will introduce is simpler, and has the same (linear) running time. The idea behind the algorithm is not too different from the [naive string search](../Brute-Force%20String%20Search/) procedure. As it, Knuth-Morris-Pratt aligns the text with the pattern and goes with character comparisons from left to right. But, instead of making a shift of one character when a mismatch occurs, it uses a more intelligent way to move the pattern along the text. In fact, the algorithm features a pattern pre-processing stage where it acquires all the informations that will make the algorithm skip redundant comparisons, resulting in larger shifts. The pre-processing stage produces an array (called `suffixPrefix` in the code) of integers in which every element `suffixPrefix[i]` records the length of the longest proper suffix of `P[0...i]` (where `P` is the pattern) that matches a prefix of `P`. In other words, `suffixPrefix[i]` is the longest proper substring of `P` that ends at position `i` and that is a prefix of `P`. Just a quick example. Consider `P = "abadfryaabsabadffg"`, then `suffixPrefix[4] = 0`, `suffixPrefix[9] = 2`, `suffixPrefix[14] = 4`. There are different ways to obtain the values of `SuffixPrefix` array. We will use the method based on the [Z-Algorithm](../Z-Algorithm/). This function takes in input the pattern and produces an array of integers. Each element represents the length of the longest substring starting at position `i` of `P` and that matches a prefix of `P`. You can notice that the two arrays are similar, they record the same informations but on the different places. We only have to find a method to map `Z[i]` to `suffixPrefix[j]`. It is not that difficult and this is the code that will do for us: ```swift for patternIndex in (1 ..< patternLength).reversed() { textIndex = patternIndex + zeta![patternIndex] - 1 suffixPrefix[textIndex] = zeta![patternIndex] } ``` We are simply computing the index of the end of the substring starting at position `i` (as we know matches a prefix of `P`). The element of `suffixPrefix` at that index then it will be set with the length of the substring. Once the shift-array `suffixPrefix` is ready we can begin with pattern search stage. The algorithm first attempts to compare the characters of the text with those of the pattern. If it succeeds, it goes on until a mismatch occurs. When it happens, it checks if an occurrence of the pattern is present (and reports it). Otherwise, if no comparisons are made then the text cursor is moved forward, else the pattern is shifted to the right. The shift's amount is based on the `suffixPrefix` array, and it guarantees that the prefix `P[0...suffixPrefix[i]]` will match its opposing substring in the text. In this way, shifts of more than one character are often made and lot of comparisons can be avoided, saving a lot of time. Here is the code of the Knuth-Morris-Pratt algorithm: ```swift extension String { func indexesOf(ptnr: String) -> [Int]? { let text = Array(self.characters) let pattern = Array(ptnr.characters) let textLength: Int = text.count let patternLength: Int = pattern.count guard patternLength > 0 else { return nil } var suffixPrefix: [Int] = [Int](repeating: 0, count: patternLength) var textIndex: Int = 0 var patternIndex: Int = 0 var indexes: [Int] = [Int]() /* Pre-processing stage: computing the table for the shifts (through Z-Algorithm) */ let zeta = ZetaAlgorithm(ptnr: ptnr) for patternIndex in (1 ..< patternLength).reversed() { textIndex = patternIndex + zeta![patternIndex] - 1 suffixPrefix[textIndex] = zeta![patternIndex] } /* Search stage: scanning the text for pattern matching */ textIndex = 0 patternIndex = 0 while textIndex + (patternLength - patternIndex - 1) < textLength { while patternIndex < patternLength && text[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } if patternIndex == patternLength { indexes.append(textIndex - patternIndex) } if patternIndex == 0 { textIndex = textIndex + 1 } else { patternIndex = suffixPrefix[patternIndex - 1] } } guard !indexes.isEmpty else { return nil } return indexes } } ``` Let's make an example reasoning with the code above. Let's consider the string `P = ACTGACTA"`, the consequentially obtained `suffixPrefix` array equal to `[0, 0, 0, 0, 0, 0, 3, 1]`, and the text `T = "GCACTGACTGACTGACTAG"`. The algorithm begins with the text and the pattern aligned like below. We have to compare `T[0]` with `P[0]`. 1 0123456789012345678 text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ x suffixPrefix: 00000031 We have a mismatch and we move on comparing `T[1]` and `P[0]`. We have to check if a pattern occurrence is present but there is not. So, we have to shift the pattern right and by doing so we have to check `suffixPrefix[1 - 1]`. Its value is `0` and we restart by comparing `T[1]` with `P[0]`. Again a mismath occurs, so we go on with `T[2]` and `P[0]`. 1 0123456789012345678 text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ suffixPrefix: 00000031 This time we have a match. And it continues until position `8`. Unfortunately the length of the match is not equal to the pattern length, we cannot report an occurrence. But we are still lucky because we can use the values computed in the `suffixPrefix` array now. In fact, the length of the match is `7`, and if we look at the element `suffixPrefix[7 - 1]` we discover that is `3`. This information tell us that that the prefix of `P` matches the suffix of the susbtring `T[0...8]`. So the `suffixPrefix` array guarantees us that the two substring match and that we do not have to compare their characters, so we can shift right the pattern for more than one character! The comparisons restart from `T[9]` and `P[3]`. 1 0123456789012345678 text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ suffixPrefix: 00000031 They match so we continue the compares until position `13` where a misatch occurs beetwen charcter `G` and `A`. Just like before, we are lucky and we can use the `suffixPrefix` array to shift right the pattern. 1 0123456789012345678 text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ suffixPrefix: 00000031 Again, we have to compare. But this time the comparisons finally take us to an occurrence, at position `17 - 7 = 10`. 1 0123456789012345678 text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ suffixPrefix: 00000031 The algorithm than tries to compare `T[18]` with `P[1]` (because we used the element `suffixPrefix[8 - 1] = 1`) but it fails and at the next iteration it ends its work. The pre-processing stage involves only the pattern. The running time of the Z-Algorithm is linear and takes `O(n)`, where `n` is the length of the pattern `P`. After that, the search stage does not "overshoot" the length of the text `T` (call it `m`). It can be be proved that number of comparisons of the search stage is bounded by `2 * m`. The final running time of the Knuth-Morris-Pratt algorithm is `O(n + m)`. > **Note:** To execute the code in the [KnuthMorrisPratt.swift](./KnuthMorrisPratt.swift) you have to copy the [ZAlgorithm.swift](../Z-Algorithm/ZAlgorithm.swift) file contained in the [Z-Algorithm](../Z-Algorithm/) folder. The [KnuthMorrisPratt.playground](./KnuthMorrisPratt.playground) already includes the definition of the `Zeta` function. Credits: This code is based on the handbook ["Algorithm on String, Trees and Sequences: Computer Science and Computational Biology"](https://books.google.it/books/about/Algorithms_on_Strings_Trees_and_Sequence.html?id=Ofw5w1yuD8kC&redir_esc=y) by Dan Gusfield, Cambridge University Press, 1997. *Written for Swift Algorithm Club by Matteo Dunnhofer* ================================================ FILE: Kth Largest Element/README.markdown ================================================ # k-th Largest Element Problem You're given an integer array `a`. Write an algorithm that finds the *k*-th largest element in the array. For example, the 1-st largest element is the maximum value that occurs in the array. If the array has *n* elements, the *n*-th largest element is the minimum. The median is the *n/2*-th largest element. ## The naive solution The following solution is semi-naive. Its time complexity is **O(n log n)** since it first sorts the array, and therefore also uses additional **O(n)** space. ```swift func kthLargest(a: [Int], k: Int) -> Int? { let len = a.count if k > 0 && k <= len { let sorted = a.sorted() return sorted[len - k] } else { return nil } } ``` The `kthLargest()` function takes two parameters: the array `a` consisting of integers, and `k`. It returns the *k*-th largest element. Let's take a look at an example and run through the algorithm to see how it works. Given `k = 4` and the array: ```swift [ 7, 92, 23, 9, -1, 0, 11, 6 ] ``` Initially there's no direct way to find the k-th largest element, but after sorting the array it's rather straightforward. Here's the sorted array: ```swift [ -1, 0, 6, 7, 9, 11, 23, 92 ] ``` Now, all we must do is take the value at index `a.count - k`: ```swift a[a.count - k] = a[8 - 4] = a[4] = 9 ``` Of course, if you were looking for the k-th *smallest* element, you'd use `a[k-1]`. ## A faster solution There is a clever algorithm that combines the ideas of [binary search](../Binary%20Search/) and [quicksort](../Quicksort/) to arrive at an **O(n)** solution. Recall that binary search splits the array in half over and over again, to quickly narrow in on the value you're searching for. That's what we'll do here too. Quicksort also splits up arrays. It uses partitioning to move all smaller values to the left of the pivot and all greater values to the right. After partitioning around a certain pivot, that pivot value will already be in its final, sorted position. We can use that to our advantage here. Here's how it works: We choose a random pivot, partition the array around that pivot, then act like a binary search and only continue in the left or right partition. This repeats until we've found a pivot that happens to end up in the *k*-th position. Let's look at the original example again. We're looking for the 4-th largest element in this array: [ 7, 92, 23, 9, -1, 0, 11, 6 ] The algorithm is a bit easier to follow if we look for the k-th *smallest* item instead, so let's take `k = 4` and look for the 4-th smallest element. Note that we don't have to sort the array first. We pick one of the elements at random to be the pivot, let's say `11`, and partition the array around that. We might end up with something like this: [ 7, 9, -1, 0, 6, 11, 92, 23 ] <------ smaller larger --> As you can see, all values smaller than `11` are on the left; all values larger are on the right. The pivot value `11` is now in its final place. The index of the pivot is 5, so the 4-th smallest element must be in the left partition somewhere. We can ignore the rest of the array from now on: [ 7, 9, -1, 0, 6, x, x, x ] Again let's pick a random pivot, let's say `6`, and partition the array around it. We might end up with something like this: [ -1, 0, 6, 9, 7, x, x, x ] Pivot `6` ended up at index 2, so obviously the 4-th smallest item must be in the right partition. We can ignore the left partition: [ x, x, x, 9, 7, x, x, x ] Again we pick a pivot value at random, let's say `9`, and partition the array: [ x, x, x, 7, 9, x, x, x ] The index of pivot `9` is 4, and that's exactly the *k* we're looking for. We're done! Notice how this only took a few steps and we did not have to sort the array first. The following function implements these ideas: ```swift public func randomizedSelect(_ array: [T], order k: Int) -> T { var a = array func randomPivot(_ a: inout [T], _ low: Int, _ high: Int) -> T { let pivotIndex = random(min: low, max: high) a.swapAt(pivotIndex, high) return a[high] } func randomizedPartition(_ a: inout [T], _ low: Int, _ high: Int) -> Int { let pivot = randomPivot(&a, low, high) var i = low for j in low..(_ a: inout [T], _ low: Int, _ high: Int, _ k: Int) -> T { if low < high { let p = randomizedPartition(&a, low, high) if k == p { return a[p] } else if k < p { return randomizedSelect(&a, low, p - 1, k) } else { return randomizedSelect(&a, p + 1, high, k) } } else { return a[low] } } precondition(a.count > 0) return randomizedSelect(&a, 0, a.count - 1, k) } ``` To keep things readable, the functionality is split into three inner functions: - `randomPivot()` picks a random number and puts it at the end of the current partition (this is a requirement of the Lomuto partitioning scheme, see the discussion on [quicksort](../Quicksort/) for more details). - `randomizedPartition()` is Lomuto's partitioning scheme from quicksort. When this completes, the randomly chosen pivot is in its final sorted position in the array. It returns the array index of the pivot. - `randomizedSelect()` does all the hard work. It first calls the partitioning function and then decides what to do next. If the index of the pivot is equal to the *k*-th number we're looking for, we're done. If `k` is less than the pivot index, it must be in the left partition and we'll recursively try again there. Likewise for when the *k*-th number must be in the right partition. Pretty cool, huh? Normally quicksort is an **O(n log n)** algorithm, but because we only partition smaller and smaller slices of the array, the running time of `randomizedSelect()` works out to **O(n)**. > **Note:** This function calculates the *k*-th smallest item in the array, where *k* starts at 0. If you want the *k*-th largest item, call it with `a.count - k`. *Written by Daniel Speiser. Additions by Matthijs Hollemans.* ================================================ FILE: Kth Largest Element/kthLargest.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play let a = [5, 1, 3, 2, 7, 6, 4] kthLargest(a, 0) kthLargest(a, 1) kthLargest(a, 2) kthLargest(a, 3) kthLargest(a, 4) kthLargest(a, 5) kthLargest(a, 6) kthLargest(a, 7) kthLargest(a, 8) randomizedSelect(a, order: 0) randomizedSelect(a, order: 1) randomizedSelect(a, order: 2) randomizedSelect(a, order: 3) randomizedSelect(a, order: 4) randomizedSelect(a, order: 5) randomizedSelect(a, order: 6) ================================================ FILE: Kth Largest Element/kthLargest.playground/Sources/kthLargest.swift ================================================ import Foundation /* Returns the k-th largest value inside of an array a. This is an O(n log n) solution since we sort the array. */ public func kthLargest(_ a: [Int], _ k: Int) -> Int? { let len = a.count if k > 0 && k <= len { let sorted = a.sorted() return sorted[len - k] } else { return nil } } // MARK: - Randomized selection /* Returns the i-th smallest element from the array. This works a bit like quicksort and a bit like binary search. The partitioning step picks a random pivot and uses Lomuto's scheme to rearrange the array; afterwards, this pivot is in its final sorted position. If this pivot index equals i, we're done. If i is smaller, then we continue with the left side, otherwise we continue with the right side. Expected running time: O(n) if the elements are distinct. */ public func randomizedSelect(_ array: [T], order k: Int) -> T { var a = array func randomPivot(_ a: inout [T], _ low: Int, _ high: Int) -> T { let pivotIndex = Int.random(in: low...high) a.swapAt(pivotIndex, high) return a[high] } func randomizedPartition(_ a: inout [T], _ low: Int, _ high: Int) -> Int { let pivot = randomPivot(&a, low, high) var i = low for j in low..(_ a: inout [T], _ low: Int, _ high: Int, _ k: Int) -> T { if low < high { let p = randomizedPartition(&a, low, high) if k == p { return a[p] } else if k < p { return randomizedSelect(&a, low, p - 1, k) } else { return randomizedSelect(&a, p + 1, high, k) } } else { return a[low] } } precondition(a.count > 0) return randomizedSelect(&a, 0, a.count - 1, k) } ================================================ FILE: Kth Largest Element/kthLargest.playground/contents.xcplayground ================================================ ================================================ FILE: Kth Largest Element/kthLargest.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Kth Largest Element/kthLargest.playground/playground.xcworkspace/xcshareddata/kthLargest.xcscmblueprint ================================================ { "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "CF309AABC690F91A443043D5C69EECB0069B5411", "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { }, "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { "CF309AABC690F91A443043D5C69EECB0069B5411" : 9223372036854775807, "FA0506A44181383605977F2A9C8020B861F7CE04" : 9223372036854775807 }, "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "6CCD70DA-EE44-4E31-98F0-6DA8B083772A", "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { "CF309AABC690F91A443043D5C69EECB0069B5411" : "swift-algorithm-club\/", "FA0506A44181383605977F2A9C8020B861F7CE04" : "" }, "DVTSourceControlWorkspaceBlueprintNameKey" : "kthLargest", "DVTSourceControlWorkspaceBlueprintVersion" : 204, "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Kth Largest Element\/kthLargest.playground", "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ { "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Deeer\/swift-algorithm-club.git", "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "CF309AABC690F91A443043D5C69EECB0069B5411" }, { "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/Deeer\/CuteSticker.git", "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "FA0506A44181383605977F2A9C8020B861F7CE04" } ] } ================================================ FILE: LICENSE.txt ================================================ Copyright (c) 2016 Matthijs Hollemans and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: LRU Cache/LRUCache.playground/Contents.swift ================================================ let cache = LRUCache(2) cache.set("a", val: 1) cache.set("b", val: 2) cache.get("a") // returns 1 cache.set("c", val: 3) // evicts key "b" cache.get("b") // returns nil (not found) cache.set("d", val: 4) // evicts key "a" cache.get("a") // returns nil (not found) cache.get("c") // returns 3 cache.get("d") // returns 4 ================================================ FILE: LRU Cache/LRUCache.playground/Sources/LRUCache.swift ================================================ // // LRUCache.swift // // // Created by Kai Chen on 16/07/2017. // // import Foundation public class LRUCache { private let maxSize: Int private var cache: [KeyType: Any] = [:] private var priority: LinkedList = LinkedList() private var key2node: [KeyType: LinkedList.LinkedListNode] = [:] public init(_ maxSize: Int) { self.maxSize = maxSize } public func get(_ key: KeyType) -> Any? { guard let val = cache[key] else { return nil } remove(key) insert(key, val: val) return val } public func set(_ key: KeyType, val: Any) { if cache[key] != nil { remove(key) } else if priority.count >= maxSize, let keyToRemove = priority.last?.value { remove(keyToRemove) } insert(key, val: val) } private func remove(_ key: KeyType) { cache.removeValue(forKey: key) guard let node = key2node[key] else { return } priority.remove(node: node) key2node.removeValue(forKey: key) } private func insert(_ key: KeyType, val: Any) { cache[key] = val priority.insert(key, atIndex: 0) guard let first = priority.first else { return } key2node[key] = first } } ================================================ FILE: LRU Cache/LRUCache.playground/Sources/LinkedList.swift ================================================ public final class LinkedList { public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? public init(value: T) { self.value = value } } public typealias Node = LinkedListNode fileprivate var head: Node? public init() {} public var isEmpty: Bool { return head == nil } public var first: Node? { return head } public var last: Node? { if var node = head { while let next = node.next { node = next } return node } else { return nil } } public var count: Int { if var node = head { var c = 1 while let next = node.next { node = next c += 1 } return c } else { return 0 } } public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head var i = index while node != nil { if i == 0 { return node } i -= 1 node = node!.next } } return nil } public subscript(index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return node!.value } public func append(_ value: T) { let newNode = Node(value: value) self.append(newNode) } public func append(_ node: Node) { let newNode = LinkedListNode(value: node.value) if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode } else { head = newNode } } public func append(_ list: LinkedList) { var nodeToCopy = list.head while let node = nodeToCopy { self.append(node.value) nodeToCopy = node.next } } private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) var i = index var next = head var prev: Node? while next != nil && i > 0 { i -= 1 prev = next next = next!.next } assert(i == 0) // if > 0, then specified index was too large return (prev, next) } public func insert(_ value: T, atIndex index: Int) { let newNode = Node(value: value) self.insert(newNode, atIndex: index) } public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = LinkedListNode(value: node.value) newNode.previous = prev newNode.next = next prev?.next = newNode next?.previous = newNode if prev == nil { head = newNode } } public func insert(_ list: LinkedList, atIndex index: Int) { if list.isEmpty { return } var (prev, next) = nodesBeforeAndAfter(index: index) var nodeToCopy = list.head var newNode: Node? while let node = nodeToCopy { newNode = Node(value: node.value) newNode?.previous = prev if let previous = prev { previous.next = newNode } else { self.head = newNode } nodeToCopy = nodeToCopy?.next prev = newNode } prev?.next = next next?.previous = prev } public func removeAll() { head = nil } @discardableResult public func remove(node: Node) -> T { let prev = node.previous let next = node.next if let prev = prev { prev.next = next } else { head = next } next?.previous = prev node.previous = nil node.next = nil return node.value } @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } @discardableResult public func remove(atIndex index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return remove(node: node!) } } extension LinkedList: CustomStringConvertible { public var description: String { var s = "[" var node = head while node != nil { s += "\(node!.value)" node = node!.next if node != nil { s += ", " } } return s + "]" } } extension LinkedList { public func reverse() { var node = head while let currentNode = node { node = currentNode.next swap(¤tNode.next, ¤tNode.previous) head = currentNode } } } extension LinkedList { public func map(transform: (T) -> U) -> LinkedList { let result = LinkedList() var node = head while node != nil { result.append(transform(node!.value)) node = node!.next } return result } public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head while node != nil { if predicate(node!.value) { result.append(node!.value) } node = node!.next } return result } } extension LinkedList { convenience init(array: Array) { self.init() for element in array { self.append(element) } } } extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() for element in elements { self.append(element) } } } ================================================ FILE: LRU Cache/LRUCache.playground/contents.xcplayground ================================================ ================================================ FILE: LRU Cache/LRUCache.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: LRU Cache/LRUCache.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: LRU Cache/LRUCache.swift ================================================ // // LRUCache.swift // // // Created by Kai Chen on 16/07/2017. // // import Foundation public class LRUCache { private let maxSize: Int private var cache: [KeyType: Any] = [:] private var priority: LinkedList = LinkedList() private var key2node: [KeyType: LinkedList.LinkedListNode] = [:] public init(_ maxSize: Int) { self.maxSize = maxSize } public func get(_ key: KeyType) -> Any? { guard let val = cache[key] else { return nil } remove(key) insert(key, val: val) return val } public func set(_ key: KeyType, val: Any) { if cache[key] != nil { remove(key) } else if priority.count >= maxSize, let keyToRemove = priority.last?.value { remove(keyToRemove) } insert(key, val: val) } private func remove(_ key: KeyType) { cache.removeValue(forKey: key) guard let node = key2node[key] else { return } priority.remove(node: node) key2node.removeValue(forKey: key) } private func insert(_ key: KeyType, val: Any) { cache[key] = val priority.insert(key, atIndex: 0) guard let first = priority.first else { return } key2node[key] = first } } ================================================ FILE: LRU Cache/Readme.md ================================================ # LRU Cache Caches are used to hold objects in memory. A caches size is finite; If the system doesn't have enough memory, the cache must be purged or the program will crash. [Least Recently Used][1] (LRU) is a popular algorithm in cache design. In this implementation of the LRU Cache, a size is declared during instantiation, and any insertions that go beyond the size will purge the least recently used element of the cache. A *priority queue* is used to enforce this behavior. ## The priority queue The key to the LRU cache is the priority queue. For simplicity, you'll model the queue using a linked list. All interactions with the LRU cache should respect this queue; Calling `get` and `set` should update the priority queue to reflect the most recently accessed element. ### Interesting tidbits #### Adding values Each time we access an element, either `set` or `get` we need to insert the element in the head of priority list. We use a helper method to handle this procedure: ```swift private func insert(_ key: KeyType, val: Any) { cache[key] = val priority.insert(key, atIndex: 0) guard let first = priority.first else { return } key2node[key] = first } ``` #### Purging the cache When the cache is full, a purge must take place starting with the least recently used element. In this case, we need to `remove` the lowest priority node. The operation is like this: ```swift private func remove(_ key: KeyType) { cache.removeValue(key) guard let node = key2node[key] else { return } priority.remove(node) key2node.removeValue(key) } ``` ### Optimizing Performance Removing elements from the priority queue is a frequent operation for the LRU cache. Since priority queue is modelled using a linked list, this is an expensive operation that costs `O(n)` time. This is the bottleneck for both the `set` and `get` methods. To help alleviate this problem, a hash table is used to store the references of each node: ``` private var key2node: [KeyType: LinkedList.LinkedListNode] = [:] ``` *Written for the Swift Algorithm Club by Kai Chen, with additions by Kelvin Lau* [1]: https://en.wikipedia.org/wiki/Cache_replacement_policies#LRU ================================================ FILE: Linear Regression/LinearRegression.playground/Contents.swift ================================================ // Linear Regression import Foundation let carAge: [Double] = [10, 8, 3, 3, 2, 1] let carPrice: [Double] = [500, 400, 7000, 8500, 11000, 10500] var intercept = 0.0 var slope = 0.0 func predictedCarPrice(_ carAge: Double) -> Double { return intercept + slope * carAge } // An iterative approach let numberOfCarAdvertsWeSaw = carPrice.count let numberOfIterations = 100 let alpha = 0.0001 for _ in 1...numberOfIterations { for i in 0.. Double { return input.reduce(0, +) / Double(input.count) } func multiply(_ a: [Double], _ b: [Double]) -> [Double] { return zip(a, b).map(*) } func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double) -> Double { let sum1 = average(multiply(xs, ys)) - average(xs) * average(ys) let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 let intercept = average(ys) - slope * average(xs) return { x in intercept + slope * x } } let result = linearRegression(carAge, carPrice)(4) print("A car of age 4 years is predicted to be worth £\(Int(result))") ================================================ FILE: Linear Regression/LinearRegression.playground/contents.xcplayground ================================================ ================================================ FILE: Linear Regression/LinearRegression.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Linear Regression/README.markdown ================================================ # Linear Regression Linear regression is a technique for creating a model of the relationship between two (or more) variable quantities. For example, let's say we are planning to sell a car. We are not sure how much money to ask for. So we look at recent advertisments for the asking prices of other cars. There are a lot of variables we could look at - for example: make, model, engine size. To simplify our task, we collect data on just the age of the car and the price: Age (in years)| Price (in £) --------------|------------- 10 | 500 8 | 400 3 | 7,000 3 | 8,500 2 | 11,000 1 | 10,500 Our car is 4 years old. How can we set a price for our car based on the data in this table? Let's start by looking at the data plotted out: ![graph1](Images/graph1.png) We could imagine a straight line drawn through the points on this graph. It's not (in this case) going to go exactly through every point, but we could place the line so that it goes as close to all the points as possible. To say this in another way, we want to make the distance from the line to each point as small as possible. This is most often done by minimizing the square of the distance from the line to each point. We can describe the straight line in terms of two variables: 1. The point at which it crosses the y-axis i.e. the predicted price of a brand new car. This is the *intercept*. 2. The *slope* of the line - i.e. for every year of age, how much does the price change. This is the equation for our line: `carPrice = slope * carAge + intercept` How can we find the best values for the intercept and the slope? Let's look at two different ways to do this. ## An iterative approach One approach is to start with some arbitrary values for the intercept and the slope. We work out what small changes we make to these values to move our line closer to the data points. Then we repeat this multiple times. Eventually our line will approach the optimum position. First let's set up our data structures. We will use two Swift arrays for the car age and the car price: ```swift let carAge: [Double] = [10, 8, 3, 3, 2, 1] let carPrice: [Double] = [500, 400, 7000, 8500, 11000, 10500] ``` This is how we can represent our straight line: ```swift var intercept = 0.0 var slope = 0.0 func predictedCarPrice(_ carAge: Double) -> Double { return intercept + slope * carAge } ``` Now for the code which will perform the iterations: ```swift let numberOfCarAdvertsWeSaw = carPrice.count let numberOfIterations = 100 let alpha = 0.0001 for _ in 1...numberOfIterations { for i in 0.. Double { return input.reduce(0, +) / Double(input.count) } ``` We are using the ```reduce``` Swift function to sum up all the elements of the array, and then divide that by the number of elements. This gives us the mean value. We also need to be able to multiply each element in an array by the corresponding element in another array, to create a new array. Here is a function which will do this: ```swift func multiply(_ a: [Double], _ b: [Double]) -> [Double] { return zip(a,b).map(*) } ``` We are using the ```map``` function to multiply each element. Finally, the function which fits the line to the data: ```swift func linearRegression(_ xs: [Double], _ ys: [Double]) -> (Double) -> Double { let sum1 = average(multiply(ys, xs)) - average(xs) * average(ys) let sum2 = average(multiply(xs, xs)) - pow(average(xs), 2) let slope = sum1 / sum2 let intercept = average(ys) - slope * average(xs) return { x in intercept + slope * x } } ``` This function takes as arguments two arrays of Doubles, and returns a function which is the line of best fit. The formulas to calculate the slope and the intercept can be derived from our definition of the function `J`. Let's see how the output from this line fits our data: ![graph3](Images/graph3.png) Using this line, we would predict a price for our 4 year old car of £6952. ## Summary We've seen two different ways to implement a simple linear regression in Swift. An obvious question is: why bother with the iterative approach at all? Well, the line we've found doesn't fit the data perfectly. For one thing, the graph includes some negative values at high car ages! Possibly we would have to pay someone to tow away a very old car... but really these negative values just show that we have not modelled the real life situation very accurately. The relationship between the car age and the car price is not linear but instead is some other function. We also know that a car's price is not just related to its age but also other factors such as the make, model and engine size of the car. We would need to use additional variables to describe these other factors. It turns out that in some of these more complicated models, the iterative approach is the only viable or efficient approach. This can also occur when the arrays of data are very large and may be sparsely populated with data values. *Written for Swift Algorithm Club by James Harrop* ================================================ FILE: Linear Search/LinearSearch.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play func linearSearch(_ array: [T], _ object: T) -> Int? { for (index, obj) in array.enumerated() where obj == object { return index } return nil } let array = [5, 2, 4, 7] linearSearch(array, 2) // returns 1 linearSearch(array, 3) // returns nil ================================================ FILE: Linear Search/LinearSearch.playground/contents.xcplayground ================================================ ================================================ FILE: Linear Search/LinearSearch.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Linear Search/LinearSearch.swift ================================================ func linearSearch(_ array: [T], _ object: T) -> Int? { for (index, obj) in array.enumerated() where obj == object { return index } return nil } func linearSearch1(_ array: [T], _ object: T) -> Array.Index? { return array.index { $0 == object } } ================================================ FILE: Linear Search/README.markdown ================================================ # Linear Search Goal: Find a particular value in an array. We have an array of generic objects. With linear search, we iterate over all the objects in the array and compare each one to the object we're looking for. If the two objects are equal, we stop and return the current array index. If not, we continue to look for the next object as long as we have objects in the array. ## An example Let's say we have an array of numbers `[5, 2, 4, 7]` and we want to check if the array contains the number `2`. We start by comparing the first number in the array, `5`, to the number we're looking for, `2`. They are obviously not the same, and so we continue to the next array element. We compare the number `2` from the array to our number `2` and notice they are equal. Now we can stop our iteration and return 1, which is the index of the number `2` in the array. ## The code Here is a simple implementation of linear search in Swift: ```swift func linearSearch(_ array: [T], _ object: T) -> Int? { for (index, obj) in array.enumerated() where obj == object { return index } return nil } ``` Put this code in a playground and test it like so: ```swift let array = [5, 2, 4, 7] linearSearch(array, 2) // This will return 1 ``` ## Performance Linear search runs at **O(n)**. It compares the object we are looking for with each object in the array and so the time it takes is proportional to the array length. In the worst case, we need to look at all the elements in the array. The best-case performance is **O(1)** but this case is rare because the object we're looking for has to be positioned at the start of the array to be immediately found. You might get lucky, but most of the time you won't. On average, linear search needs to look at half the objects in the array. ## See also [Linear search on Wikipedia](https://en.wikipedia.org/wiki/Linear_search) *Written by [Patrick Balestra](http://www.github.com/BalestraPatrick)* ================================================ FILE: Linked List/LinkedList.playground/Contents.swift ================================================ //: # Linked Lists // For best results, don't forget to select "Show Rendered Markup" from XCode's "Editor" menu //: Linked List Class Declaration: public final class LinkedList { /// Linked List's Node Class Declaration public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? public init(value: T) { self.value = value } } /// Typealiasing the node class to increase readability of code public typealias Node = LinkedListNode /// The head of the Linked List private(set) var head: Node? /// Computed property to iterate through the linked list and return the last node in the list (if any) public var last: Node? { guard var node = head else { return nil } while let next = node.next { node = next } return node } /// Computed property to check if the linked list is empty public var isEmpty: Bool { return head == nil } /// Computed property to iterate through the linked list and return the total number of nodes public var count: Int { guard var node = head else { return 0 } var count = 1 while let next = node.next { node = next count += 1 } return count } /// Default initializer public init() {} /// Subscript function to return the node at a specific index /// /// - Parameter index: Integer value of the requested value's index public subscript(index: Int) -> T { let node = self.node(at: index) return node.value } /// Function to return the node at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameter index: Integer value of the node's index to be returned /// - Returns: LinkedListNode public func node(at index: Int) -> Node { assert(head != nil, "List is empty") assert(index >= 0, "index must be greater than 0") if index == 0 { return head! } else { var node = head!.next for _ in 1.. T { let prev = node.previous let next = node.next if let prev = prev { prev.next = next } else { head = next } next?.previous = prev node.previous = nil node.next = nil return node.value } /// Function to remove the last node/value in the list. Crashes if the list is empty /// /// - Returns: The data value contained in the deleted node. @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } /// Function to remove a node/value at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameter index: Integer value of the index of the node to be removed /// - Returns: The data value contained in the deleted node @discardableResult public func remove(at index: Int) -> T { let node = self.node(at: index) return remove(node: node) } } //: End of the base class declarations & beginning of extensions' declarations: // MARK: - Extension to enable the standard conversion of a list to String extension LinkedList: CustomStringConvertible { public var description: String { var s = "[" var node = head while let nd = node { s += "\(nd.value)" node = nd.next if node != nil { s += ", " } } return s + "]" } } // MARK: - Extension to add a 'reverse' function to the list extension LinkedList { public func reverse() { var node = head while let currentNode = node { node = currentNode.next swap(¤tNode.next, ¤tNode.previous) head = currentNode } } } // MARK: - An extension with an implementation of 'map' & 'filter' functions extension LinkedList { public func map(transform: (T) -> U) -> LinkedList { let result = LinkedList() var node = head while let nd = node { result.append(transform(nd.value)) node = nd.next } return result } public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head while let nd = node { if predicate(nd.value) { result.append(nd.value) } node = nd.next } return result } } // MARK: - Extension to enable initialization from an Array extension LinkedList { convenience init(array: Array) { self.init() array.forEach { append($0) } } } // MARK: - Extension to enable initialization from an Array Literal extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() elements.forEach { append($0) } } } // MARK: - Collection extension LinkedList: Collection { public typealias Index = LinkedListIndex /// The position of the first element in a nonempty collection. /// /// If the collection is empty, `startIndex` is equal to `endIndex`. /// - Complexity: O(1) public var startIndex: Index { get { return LinkedListIndex(node: head, tag: 0) } } /// The collection's "past the end" position---that is, the position one /// greater than the last valid subscript argument. /// - Complexity: O(n), where n is the number of elements in the list. This can be improved by keeping a reference /// to the last node in the collection. public var endIndex: Index { get { if let h = self.head { return LinkedListIndex(node: h, tag: count) } else { return LinkedListIndex(node: nil, tag: startIndex.tag) } } } public subscript(position: Index) -> T { get { return position.node!.value } } public func index(after idx: Index) -> Index { return LinkedListIndex(node: idx.node?.next, tag: idx.tag + 1) } } // MARK: - Collection Index /// Custom index type that contains a reference to the node at index 'tag' public struct LinkedListIndex: Comparable { fileprivate let node: LinkedList.LinkedListNode? fileprivate let tag: Int public static func==(lhs: LinkedListIndex, rhs: LinkedListIndex) -> Bool { return (lhs.tag == rhs.tag) } public static func< (lhs: LinkedListIndex, rhs: LinkedListIndex) -> Bool { return (lhs.tag < rhs.tag) } } //: Ok, now that the declarations are done, let's see our Linked List in action: let list = LinkedList() list.isEmpty // true list.head // nil list.last // nil list.append("Hello") list.isEmpty // false list.head!.value // "Hello" list.last!.value // "Hello" list.count // 1 list.append("World") list.head!.value // "Hello" list.last!.value // "World" list.count // 2 list.head!.previous // nil list.head!.next!.value // "World" list.last!.previous!.value // "Hello" list.last!.next // nil list.node(at: 0).value // "Hello" list.node(at: 1).value // "World" //list.node(at: 2) // crash! list[0] // "Hello" list[1] // "World" //list[2] // crash! let list2 = LinkedList() list2.append("Goodbye") list2.append("World") list.append(list2) // [Hello, World, Goodbye, World] list2.removeAll() // [ ] list2.isEmpty // true list.removeLast() // "World" list.remove(at: 2) // "Goodbye" list.insert("Swift", at: 1) list[0] // "Hello" list[1] // "Swift" list[2] // "World" print(list) list.reverse() // [World, Swift, Hello] list.node(at: 0).value = "Universe" list.node(at: 1).value = "Swifty" let m = list.map { s in s.count } m // [8, 6, 5] let f = list.filter { s in s.count > 5 } f // [Universe, Swifty] list.remove(node: list.head!) // "Universe" list.count // 2 list[0] // "Swifty" list[1] // "Hello" list.count // 2 list.removeLast() // "Hello" list.head?.value list.count // 1 list[0] // "Swifty" list.remove(at: 0) // "Swifty" list.count // 0 let list3 = LinkedList() list3.insert("2", at: 0) // [2] list3.count // 1 list3.insert("4", at: 1) // [2,4] list3.count // 2 list3.insert("5", at: 2) // [2,4,5] list3.count // 3 list3.insert("3", at: 1) // [2,3,4,5] list3.insert("1", at: 0) // [1,2,3,4,5] let list4 = LinkedList() list4.insert(list3, at: 0) // [1,2,3,4,5] list4.count // 5 let list5 = LinkedList() list5.append("0") // [0] list5.insert("End", at:1) // [0,End] list5.count // 2 list5.insert(list4, at: 1) // [0,1,2,3,4,5,End] list5.count // 7 let linkedList: LinkedList = [1, 2, 3, 4] // [1, 2, 3, 4] linkedList.count // 4 linkedList[0] // 1 // Infer the type from the array let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] listArrayLiteral2.count // 3 listArrayLiteral2[0] // "Swift" listArrayLiteral2.removeLast() // "Club" // Conformance to the Collection protocol let collection: LinkedList = [1, 2, 3, 4, 5] let index2 = collection.index(collection.startIndex, offsetBy: 2) let value = collection[index2] // 3 // Iterating in a for loop, since the Sequence protocol allows this. var sum = 0 for element in collection { sum += element } sum //15 // Another way of achieving the same result though 'reduce', another method defined in an extension of Sequence. Collections are Sequences. let result = collection.reduce(0) {$0 + $1} // 15 ================================================ FILE: Linked List/LinkedList.playground/contents.xcplayground ================================================ ================================================ FILE: Linked List/LinkedList.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Linked List/LinkedList.swift ================================================ public final class LinkedList { /// Linked List's Node Class Declaration public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? public init(value: T) { self.value = value } } /// Typealiasing the node class to increase readability of code public typealias Node = LinkedListNode /// The head of the Linked List private(set) var head: Node? /// Computed property to iterate through the linked list and return the last node in the list (if any) public var last: Node? { guard var node = head else { return nil } while let next = node.next { node = next } return node } /// Computed property to check if the linked list is empty public var isEmpty: Bool { return head == nil } /// Computed property to iterate through the linked list and return the total number of nodes public var count: Int { guard var node = head else { return 0 } var count = 1 while let next = node.next { node = next count += 1 } return count } /// Default initializer public init() {} /// Subscript function to return the node at a specific index /// /// - Parameter index: Integer value of the requested value's index public subscript(index: Int) -> T { let node = self.node(at: index) return node.value } /// Function to return the node at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameter index: Integer value of the node's index to be returned /// - Returns: LinkedListNode public func node(at index: Int) -> Node { assert(head != nil, "List is empty") assert(index >= 0, "index must be greater or equal to 0") if index == 0 { return head! } else { var node = head!.next for _ in 1.. T { let prev = node.previous let next = node.next if let prev = prev { prev.next = next } else { head = next } next?.previous = prev node.previous = nil node.next = nil return node.value } /// Function to remove the last node/value in the list. Crashes if the list is empty /// /// - Returns: The data value contained in the deleted node. @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } /// Function to remove a node/value at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameter index: Integer value of the index of the node to be removed /// - Returns: The data value contained in the deleted node @discardableResult public func remove(at index: Int) -> T { let node = self.node(at: index) return remove(node: node) } } //: End of the base class declarations & beginning of extensions' declarations: // MARK: - Extension to enable the standard conversion of a list to String extension LinkedList: CustomStringConvertible { public var description: String { var s = "[" var node = head while let nd = node { s += "\(nd.value)" node = nd.next if node != nil { s += ", " } } return s + "]" } } // MARK: - Extension to add a 'reverse' function to the list extension LinkedList { public func reverse() { var node = head while let currentNode = node { node = currentNode.next swap(¤tNode.next, ¤tNode.previous) head = currentNode } } } // MARK: - An extension with an implementation of 'map' & 'filter' functions extension LinkedList { public func map(transform: (T) -> U) -> LinkedList { let result = LinkedList() var node = head while let nd = node { result.append(transform(nd.value)) node = nd.next } return result } public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head while let nd = node { if predicate(nd.value) { result.append(nd.value) } node = nd.next } return result } } // MARK: - Extension to enable initialization from an Array extension LinkedList { convenience init(array: Array) { self.init() array.forEach { append($0) } } } // MARK: - Extension to enable initialization from an Array Literal extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() elements.forEach { append($0) } } } // MARK: - Collection extension LinkedList: Collection { public typealias Index = LinkedListIndex /// The position of the first element in a nonempty collection. /// /// If the collection is empty, `startIndex` is equal to `endIndex`. /// - Complexity: O(1) public var startIndex: Index { get { return LinkedListIndex(node: head, tag: 0) } } /// The collection's "past the end" position---that is, the position one /// greater than the last valid subscript argument. /// - Complexity: O(n), where n is the number of elements in the list. This can be improved by keeping a reference /// to the last node in the collection. public var endIndex: Index { get { if let h = self.head { return LinkedListIndex(node: h, tag: count) } else { return LinkedListIndex(node: nil, tag: startIndex.tag) } } } public subscript(position: Index) -> T { get { return position.node!.value } } public func index(after idx: Index) -> Index { return LinkedListIndex(node: idx.node?.next, tag: idx.tag + 1) } } // MARK: - Collection Index /// Custom index type that contains a reference to the node at index 'tag' public struct LinkedListIndex: Comparable { fileprivate let node: LinkedList.LinkedListNode? fileprivate let tag: Int public static func==(lhs: LinkedListIndex, rhs: LinkedListIndex) -> Bool { return (lhs.tag == rhs.tag) } public static func< (lhs: LinkedListIndex, rhs: LinkedListIndex) -> Bool { return (lhs.tag < rhs.tag) } } ================================================ FILE: Linked List/README.markdown ================================================ # Linked List > This topic has been tutorialized [here](https://www.raywenderlich.com/144083/swift-algorithm-club-swift-linked-list-data-structure) A linked list is a sequence of data items, just like an array. But where an array allocates a big block of memory to store the objects, the elements in a linked list are totally separate objects in memory and are connected through links: +--------+ +--------+ +--------+ +--------+ | | | | | | | | | node 0 |--->| node 1 |--->| node 2 |--->| node 3 | | | | | | | | | +--------+ +--------+ +--------+ +--------+ The elements of a linked list are referred to as *nodes*. The above picture shows a *singly linked list*, where each node only has a reference -- or a "pointer" -- to the next node. In a *doubly linked list*, shown below, nodes also have pointers to the previous node: +--------+ +--------+ +--------+ +--------+ | |--->| |--->| |--->| | | node 0 | | node 1 | | node 2 | | node 3 | | |<---| |<---| |<---| | +--------+ +--------+ +--------+ +--------+ You need to keep track of where the list begins. That's usually done with a pointer called the *head*: +--------+ +--------+ +--------+ +--------+ head --->| |--->| |--->| |--->| |---> nil | node 0 | | node 1 | | node 2 | | node 3 | nil <---| |<---| |<---| |<---| |<--- tail +--------+ +--------+ +--------+ +--------+ It's also useful to have a reference to the end of the list, known as the *tail*. Note that the "next" pointer of the last node is `nil`, just like the "previous" pointer of the very first node. ## Performance of linked lists Most operations on a linked list have **O(n)** time, so linked lists are generally slower than arrays. However, they are also much more flexible -- rather than having to copy large chunks of memory around as with an array, many operations on a linked list just require you to change a few pointers. The reason for the **O(n)** time is that you can't simply write `list[2]` to access node 2 from the list. If you don't have a reference to that node already, you have to start at the `head` and work your way down to that node by following the `next` pointers (or start at the `tail` and work your way back using the `previous` pointers). But once you have a reference to a node, operations like insertion and deletion are really quick. It's just that finding the node is slow. This means that when you're dealing with a linked list, you should insert new items at the front whenever possible. That is an **O(1)** operation. Likewise for inserting at the back if you're keeping track of the `tail` pointer. ## Singly vs doubly linked lists A singly linked list uses a little less memory than a doubly linked list because it doesn't need to store all those `previous` pointers. But if you have a node and you need to find its previous node, you're screwed. You have to start at the head of the list and iterate through the entire list until you get to the right node. For many tasks, a doubly linked list makes things easier. ## Why use a linked list? A typical example of where to use a linked list is when you need a [queue](../Queue/). With an array, removing elements from the front of the queue is slow because it needs to shift down all the other elements in memory. But with a linked list it's just a matter of changing `head` to point to the second element. Much faster. But to be honest, you hardly ever need to write your own linked list these days. Still, it's useful to understand how they work; the principle of linking objects together is also used with [trees](../Tree/) and [graphs](../Graph/). ## The code We'll start by defining a type to describe the nodes: ```swift public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? public init(value: T) { self.value = value } } ``` This is a generic type, so `T` can be any kind of data that you'd like to store in the node. We'll be using strings in the examples that follow. Ours is a doubly-linked list and each node has a `next` and `previous` pointer. These can be `nil` if there are no next or previous nodes, so these variables must be optionals. (In what follows, I'll point out which functions would need to change if this was just a singly- instead of a doubly-linked list.) > **Note:** To avoid ownership cycles, we declare the `previous` pointer to be weak. If you have a node `A` that is followed by node `B` in the list, then `A` points to `B` but also `B` points to `A`. In certain circumstances, this ownership cycle can cause nodes to be kept alive even after you deleted them. We don't want that, so we make one of the pointers `weak` to break the cycle. Let's start building `LinkedList`. Here's the first bit: ```swift public class LinkedList { public typealias Node = LinkedListNode private var head: Node? public var isEmpty: Bool { return head == nil } public var first: Node? { return head } } ``` Ideally, we would want a class name to be as descriptive as possible, yet, we don't want to type a long name every time we want to use the class, therefore, we're using a typealias so inside `LinkedList` we can write the shorter `Node` instead of `LinkedListNode`. This linked list only has a `head` pointer, not a tail. Adding a tail pointer is left as an exercise for the reader. (I'll point out which functions would be different if we also had a tail pointer.) The list is empty if `head` is nil. Because `head` is a private variable, I've added the property `first` to return a reference to the first node in the list. You can try it out in a playground like this: ```swift let list = LinkedList() list.isEmpty // true list.first // nil ``` Let's also add a property that gives you the last node in the list. This is where it starts to become interesting: ```swift public var last: Node? { guard var node = head else { return nil } while let next = node.next { node = next } return node } ``` If you're new to Swift, you've probably seen `if let` but maybe not `if var`. It does the same thing -- it unwraps the `head` optional and puts the result in a new local variable named `node`. The difference is that `node` is not a constant but an actual variable, so we can change it inside the loop. The loop also does some Swift magic. The `while let next = node.next` bit keeps looping until `node.next` is nil. You could have written this as follows: ```swift var node: Node? = head while node != nil && node!.next != nil { node = node!.next } ``` But that doesn't feel very Swifty to me. We might as well make use of Swift's built-in support for unwrapping optionals. You'll see a bunch of these kinds of loops in the code that follows. > **Note:** If we kept a tail pointer, `last` would simply do `return tail`. But we don't, so it has to step through the entire list from beginning to the end. It's an expensive operation, especially if the list is long. Of course, `last` only returns nil because we don't have any nodes in the list. Let's add a method that adds a new node to the end of the list: ```swift public func append(value: T) { let newNode = Node(value: value) if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode } else { head = newNode } } ``` The `append()` method first creates a new `Node` object and then asks for the last node using the `last` property we've just added. If there is no such node, the list is still empty and we make `head` point to this new `Node`. But if we did find a valid node object, we connect the `next` and `previous` pointers to link this new node into the chain. A lot of linked list code involves this kind of `next` and `previous` pointer manipulation. Let's test it in the playground: ```swift list.append("Hello") list.isEmpty // false list.first!.value // "Hello" list.last!.value // "Hello" ``` The list looks like this: +---------+ head --->| |---> nil | "Hello" | nil <---| | +---------+ Now add a second node: ```swift list.append("World") list.first!.value // "Hello" list.last!.value // "World" ``` And the list looks like: +---------+ +---------+ head --->| |--->| |---> nil | "Hello" | | "World" | nil <---| |<---| | +---------+ +---------+ You can verify this for yourself by looking at the `next` and `previous` pointers: ```swift list.first!.previous // nil list.first!.next!.value // "World" list.last!.previous!.value // "Hello" list.last!.next // nil ``` Let's add a method to count how many nodes are in the list. This will look very similar to what we did already: ```swift public var count: Int { guard var node = head else { return 0 } var count = 1 while let next = node.next { node = next count += 1 } return count } ``` It loops through the list in the same manner but this time increments a counter as well. > **Note:** One way to speed up `count` from **O(n)** to **O(1)** is to keep track of a variable that counts how many nodes are in the list. Whenever you add or remove a node, you also update this variable. What if we wanted to find the node at a specific index in the list? With an array we can just write `array[index]` and it's an **O(1)** operation. It's a bit more involved with linked lists, but again the code follows a similar pattern: ```swift public func node(atIndex index: Int) -> Node { if index == 0 { return head! } else { var node = head!.next for _ in 1.. T { let node = node(atIndex: index) return node.value } ``` Now you can write the following: ```swift list[0] // "Hello" list[1] // "World" list[2] // crash! ``` It crashes on `list[2]` because there is no node at that index. So far we've written code to add new nodes to the end of the list, but that's slow because you need to find the end of the list first. (It would be fast if we used a tail pointer.) For this reason, if the order of the items in the list doesn't matter, you should insert at the front of the list instead. That's always an **O(1)** operation. Let's write a method that lets you insert a new node at any index in the list. ```swift public func insert(_ node: Node, atIndex index: Int) { let newNode = node if index == 0 { newNode.next = head head?.previous = newNode head = newNode } else { let prev = self.node(atIndex: index-1) let next = prev.next newNode.previous = prev newNode.next = prev.next prev.next = newNode next?.previous = newNode } } ``` As with node(atIndex :) method, insert(_: at:) method also branches depending on whether the given index is 0 or not. First let's look at the former case. Suppose we have the following list and the new node(C). +---------+ +---------+ head --->| |---->| |-----//-----> | A | | B | nil <---| |<----| |<----//------ +---------+ +---------+ [0] [1] +---------+ new --->| |----> nil | C | | | +---------+ Now put the new node before the first node. In this way: new.next = head head.previous = new +---------+ +---------+ +---------+ new --->| |--> head -->| |---->| |-----//-----> | C | | A | | B | | |<-----------| |<----| |<----//------ +---------+ +---------+ +---------+ Finally, replace the head with the new node. head = new +---------+ +---------+ +---------+ head --->| |--->| |---->| |-----//-----> | C | | A | | B | nil <---| |<---| |<----| |<----//------ +---------+ +---------+ +---------+ [0] [1] [2] However, when the given index is greater than 0, it is necessary to get the node previous and next index and insert between them. You can also obtain the previous and next node using node(atIndex:) as follows: +---------+ +---------+ +---------+ head --->| |---//--->| |---->| |---- | | | A | | B | nil <---| |---//<---| |<----| |<--- +---------+ +---------+ +---------+ [0] [index-1] [index] ^ ^ | | prev next prev = node(at: index-1) next = prev.next Now insert new node between the prev and the next. new.prev = prev; prev.next = new // connect prev and new. new.next = next; next.prev = new // connect new and next. +---------+ +---------+ +---------+ +---------+ head --->| |---//--->| |---->| |---->| | | | | A | | C | | B | nil <---| |---//<---| |<----| |<----| | +---------+ +---------+ +---------+ +---------+ [0] [index-1] [index] [index+1] ^ ^ ^ | | | prev new next Try it out: ```swift list.insert("Swift", atIndex: 1) list[0] // "Hello" list[1] // "Swift" list[2] // "World" ``` Also try adding new nodes to the front and back of the list, to verify that this works properly. > **Note:** The `node(atIndex:)` and `insert(_: atIndex:)` functions can also be used with a singly linked list because we don't depend on the node's `previous` pointer to find the previous element. What else do we need? Removing nodes, of course! First we'll do `removeAll()`, which is really simple: ```swift public func removeAll() { head = nil } ``` If you had a tail pointer, you'd set it to `nil` here too. Next we'll add some functions that let you remove individual nodes. If you already have a reference to the node, then using `remove()` is the most optimal because you don't need to iterate through the list to find the node first. ```swift public func remove(node: Node) -> T { let prev = node.previous let next = node.next if let prev = prev { prev.next = next } else { head = next } next?.previous = prev node.previous = nil node.next = nil return node.value } ``` When we take this node out of the list, we break the links to the previous node and the next node. To make the list whole again we must connect the previous node to the next node. Don't forget the `head` pointer! If this was the first node in the list then `head` needs to be updated to point to the next node. (Likewise for when you have a tail pointer and this was the last node). Of course, if there are no more nodes left, `head` should become nil. Try it out: ```swift list.remove(list.first!) // "Hello" list.count // 2 list[0] // "Swift" list[1] // "World" ``` If you don't have a reference to the node, you can use `removeLast()` or `removeAt()`: ```swift public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } public func removeAt(_ index: Int) -> T { let node = nodeAt(index) assert(node != nil) return remove(node: node!) } ``` All these removal functions also return the value from the removed element. ```swift list.removeLast() // "World" list.count // 1 list[0] // "Swift" list.removeAt(0) // "Swift" list.count // 0 ``` > **Note:** For a singly linked list, removing the last node is slightly more complicated. You can't just use `last` to find the end of the list because you also need a reference to the second-to-last node. Instead, use the `nodesBeforeAndAfter()` helper method. If the list has a tail pointer, then `removeLast()` is really quick, but you do need to remember to make `tail` point to the previous node. There's a few other fun things we can do with our `LinkedList` class. It's handy to have some sort of readable debug output: ```swift extension LinkedList: CustomStringConvertible { public var description: String { var s = "[" var node = head while node != nil { s += "\(node!.value)" node = node!.next if node != nil { s += ", " } } return s + "]" } } ``` This will print the list like so: [Hello, Swift, World] How about reversing a list, so that the head becomes the tail and vice versa? There is a very fast algorithm for that: Iterative Approach: ```swift public func reverse() { var node = head tail = node // If you had a tail pointer while let currentNode = node { node = currentNode.next swap(¤tNode.next, ¤tNode.previous) head = currentNode } } ``` Recursive Approach: ```swift public func reverse(node: head) { if !head || !head.next { return head } let temp = reverse(head.next) head.next.next = head head.next = nil return temp } ``` This loops through the entire list and simply swaps the `next` and `previous` pointers of each node. It also moves the `head` pointer to the very last element. (If you had a tail pointer you'd also need to update it.) You end up with something like this: +--------+ +--------+ +--------+ +--------+ tail --->| |<---| |<---| |<---| |---> nil | node 0 | | node 1 | | node 2 | | node 3 | nil <---| |--->| |--->| |--->| |<--- head +--------+ +--------+ +--------+ +--------+ Arrays have `map()` and `filter()` functions, and there's no reason why linked lists shouldn't either. ```swift public func map(transform: T -> U) -> LinkedList { let result = LinkedList() var node = head while node != nil { result.append(transform(node!.value)) node = node!.next } return result } ``` You can use it like this: ```swift let list = LinkedList() list.append("Hello") list.append("Swifty") list.append("Universe") let m = list.map { s in s.characters.count } m // [5, 6, 8] ``` And here's filter: ```swift public func filter(predicate: T -> Bool) -> LinkedList { let result = LinkedList() var node = head while node != nil { if predicate(node!.value) { result.append(node!.value) } node = node!.next } return result } ``` And a silly example: ```swift let f = list.filter { s in s.count > 5 } f // [Universe, Swifty] ``` Exercise for the reader: These implementations of `map()` and `filter()` aren't very fast because they `append()` the new node to the end of the new list. Recall that append is **O(n)** because it needs to scan through the entire list to find the last node. Can you make this faster? (Hint: keep track of the last node that you added.) ## An alternative approach The version of `LinkedList` you've seen so far uses nodes that are classes and therefore have reference semantics. Nothing wrong with that, but that does make them a bit more heavyweight than Swift's other collections such as `Array` and `Dictionary`. It is possible to implement a linked list with value semantics using an enum. That would look somewhat like this: ```swift enum ListNode { indirect case node(T, next: ListNode) case end } ``` The big difference with the enum-based version is that any modification you make to this list will result in a *new copy* being created because of [Swift's value semantics](https://developer.apple.com/swift/blog/?id=10). Whether that's what you want or not depends on the application. [I might fill out this section in more detail if there's a demand for it.] ## Conforming to the Collection protocol Types that conform to the Sequence protocol, whose elements can be traversed multiple times, nondestructively, and accessed by indexed subscript should conform to the Collection protocol defined in Swift's Standard Library. Doing so grants access to a very large number of properties and operations that are common when dealing collections of data. In addition to this, it lets custom types follow the patterns that are common to Swift developers. In order to conform to this protocol, classes need to provide: 1 `startIndex` and `endIndex` properties. 2 Subscript access to elements as O(1). Diversions of this time complexity need to be documented. ```swift /// The position of the first element in a nonempty collection. public var startIndex: Index { get { return LinkedListIndex(node: head, tag: 0) } } /// The collection's "past the end" position---that is, the position one /// greater than the last valid subscript argument. /// - Complexity: O(n), where n is the number of elements in the list. /// This diverts from the protocol's expectation. public var endIndex: Index { get { if let h = self.head { return LinkedListIndex(node: h, tag: count) } else { return LinkedListIndex(node: nil, tag: startIndex.tag) } } } ``` ```swift public subscript(position: Index) -> T { get { return position.node!.value } } ``` Becuase collections are responsible for managing their own indexes, the implementation below keeps a reference to a node in the list. A tag property in the index represents the position of the node in the list. ```swift /// Custom index type that contains a reference to the node at index 'tag' public struct LinkedListIndex : Comparable { fileprivate let node: LinkedList.LinkedListNode? fileprivate let tag: Int public static func==(lhs: LinkedListIndex, rhs: LinkedListIndex) -> Bool { return (lhs.tag == rhs.tag) } public static func< (lhs: LinkedListIndex, rhs: LinkedListIndex) -> Bool { return (lhs.tag < rhs.tag) } } ``` Finally, the linked is is able to calculate the index after a given one with the following implementation. ```swift public func index(after idx: Index) -> Index { return LinkedListIndex(node: idx.node?.next, tag: idx.tag+1) } ``` ## Some things to keep in mind Linked lists are flexible but many operations are **O(n)**. When performing operations on a linked list, you always need to be careful to update the relevant `next` and `previous` pointers, and possibly also the `head` and `tail` pointers. If you mess this up, your list will no longer be correct and your program will likely crash at some point. Be careful! When processing lists, you can often use recursion: process the first element and then recursively call the function again on the rest of the list. You’re done when there is no next element. This is why linked lists are the foundation of functional programming languages such as LISP. *Originally written by Matthijs Hollemans for Ray Wenderlich's Swift Algorithm Club* ================================================ FILE: Linked List/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Linked List/Tests/LinkedListTests.swift ================================================ import XCTest class LinkedListTest: XCTestCase { let numbers = [8, 2, 10, 9, 7, 5] fileprivate func buildList() -> LinkedList { let list = LinkedList() for number in numbers { list.append(number) } return list } func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testEmptyList() { let list = LinkedList() XCTAssertTrue(list.isEmpty) XCTAssertEqual(list.count, 0) XCTAssertNil(list.first) XCTAssertNil(list.last) } func testListWithOneElement() { let list = LinkedList() list.append(123) XCTAssertFalse(list.isEmpty) XCTAssertEqual(list.count, 1) XCTAssertNotNil(list.first) XCTAssertNil(list.head!.previous) XCTAssertNil(list.head!.next) XCTAssertEqual(list.head!.value, 123) XCTAssertNotNil(list.last) XCTAssertNil(list.last!.previous) XCTAssertNil(list.last!.next) XCTAssertEqual(list.last!.value, 123) XCTAssertTrue(list.head === list.last) } func testListWithTwoElements() { let list = LinkedList() list.append(123) list.append(456) XCTAssertEqual(list.count, 2) XCTAssertNotNil(list.first) XCTAssertEqual(list.head!.value, 123) XCTAssertNotNil(list.last) XCTAssertEqual(list.last!.value, 456) XCTAssertTrue(list.head !== list.last) XCTAssertNil(list.head!.previous) XCTAssertTrue(list.head!.next === list.last) XCTAssertTrue(list.last!.previous === list.head) XCTAssertNil(list.last!.next) } func testListWithThreeElements() { let list = LinkedList() list.append(123) list.append(456) list.append(789) XCTAssertEqual(list.count, 3) XCTAssertNotNil(list.first) XCTAssertEqual(list.head!.value, 123) let second = list.head!.next XCTAssertNotNil(second) XCTAssertEqual(second!.value, 456) XCTAssertNotNil(list.last) XCTAssertEqual(list.last!.value, 789) XCTAssertNil(list.head!.previous) XCTAssertTrue(list.head!.next === second) XCTAssertTrue(second!.previous === list.head) XCTAssertTrue(second!.next === list.last) XCTAssertTrue(list.last!.previous === second) XCTAssertNil(list.last!.next) } func testNodeAtIndexInListWithOneElement() { let list = LinkedList() list.append(123) let node = list.node(at: 0) XCTAssertNotNil(node) XCTAssertEqual(node.value, 123) XCTAssertTrue(node === list.head) } func testNodeAtIndex() { let list = buildList() let nodeCount = list.count XCTAssertEqual(nodeCount, numbers.count) let first = list.node(at: 0) XCTAssertNotNil(first) XCTAssertTrue(first === list.head) XCTAssertEqual(first.value, numbers[0]) let last = list.node(at: nodeCount - 1) XCTAssertNotNil(last) XCTAssertTrue(last === list.last) XCTAssertEqual(last.value, numbers[nodeCount - 1]) for i in 0..() list.insert(123, at: 0) XCTAssertFalse(list.isEmpty) XCTAssertEqual(list.count, 1) let node = list.node(at: 0) XCTAssertNotNil(node) XCTAssertEqual(node.value, 123) } func testInsertAtIndex() { let list = buildList() let prev = list.node(at: 2) let next = list.node(at: 3) let nodeCount = list.count list.insert(444, at: 3) let node = list.node(at: 3) XCTAssertNotNil(node) XCTAssertEqual(node.value, 444) XCTAssertEqual(nodeCount + 1, list.count) XCTAssertFalse(prev === node) XCTAssertFalse(next === node) XCTAssertTrue(prev.next === node) XCTAssertTrue(next.previous === node) } func testInsertListAtIndex() { let list = buildList() let list2 = LinkedList() list2.append(99) list2.append(102) list.insert(list2, at: 2) XCTAssertTrue(list.count == 8) XCTAssertEqual(list.node(at: 1).value, 2) XCTAssertEqual(list.node(at: 2).value, 99) XCTAssertEqual(list.node(at: 3).value, 102) XCTAssertEqual(list.node(at: 4).value, 10) } func testInsertListAtFirstIndex() { let list = buildList() let list2 = LinkedList() list2.append(99) list2.append(102) list.insert(list2, at: 0) XCTAssertTrue(list.count == 8) XCTAssertEqual(list.node(at: 0).value, 99) XCTAssertEqual(list.node(at: 1).value, 102) XCTAssertEqual(list.node(at: 2).value, 8) } func testInsertListAtLastIndex() { let list = buildList() let list2 = LinkedList() list2.append(99) list2.append(102) list.insert(list2, at: list.count) XCTAssertTrue(list.count == 8) XCTAssertEqual(list.node(at: 5).value, 5) XCTAssertEqual(list.node(at: 6).value, 99) XCTAssertEqual(list.node(at: 7).value, 102) } func testAppendList() { let list = buildList() let list2 = LinkedList() list2.append(99) list2.append(102) list.append(list2) XCTAssertTrue(list.count == 8) XCTAssertEqual(list.node(at: 5).value, 5) XCTAssertEqual(list.node(at: 6).value, 99) XCTAssertEqual(list.node(at: 7).value, 102) } func testAppendListToEmptyList() { let list = LinkedList() let list2 = LinkedList() list2.append(5) list2.append(10) list.append(list2) XCTAssertTrue(list.count == 2) XCTAssertEqual(list.node(at: 0).value, 5) XCTAssertEqual(list.node(at: 1).value, 10) } func testRemoveAtIndexOnListWithOneElement() { let list = LinkedList() list.append(123) let value = list.remove(at: 0) XCTAssertEqual(value, 123) XCTAssertTrue(list.isEmpty) XCTAssertEqual(list.count, 0) XCTAssertNil(list.first) XCTAssertNil(list.last) } func testRemoveAtIndex() { let list = buildList() let prev = list.node(at: 2) let next = list.node(at: 3) let nodeCount = list.count list.insert(444, at: 3) let value = list.remove(at: 3) XCTAssertEqual(value, 444) let node = list.node(at: 3) XCTAssertTrue(next === node) XCTAssertTrue(prev.next === node) XCTAssertTrue(node.previous === prev) XCTAssertEqual(nodeCount, list.count) } func testRemoveLastOnListWithOneElement() { let list = LinkedList() list.append(123) let value = list.removeLast() XCTAssertEqual(value, 123) XCTAssertTrue(list.isEmpty) XCTAssertEqual(list.count, 0) XCTAssertNil(list.first) XCTAssertNil(list.last) } func testRemoveLast() { let list = buildList() let last = list.last let prev = last!.previous let nodeCount = list.count let value = list.removeLast() XCTAssertEqual(value, 5) XCTAssertNil(last!.previous) XCTAssertNil(last!.next) XCTAssertNil(prev!.next) XCTAssertTrue(list.last === prev) XCTAssertEqual(nodeCount - 1, list.count) } func testRemoveAll() { let list = buildList() list.removeAll() XCTAssertTrue(list.isEmpty) XCTAssertEqual(list.count, 0) XCTAssertNil(list.first) XCTAssertNil(list.last) } func testReverseLinkedList() { let list = buildList() let first = list.head let last = list.last let nodeCount = list.count list.reverse() XCTAssertTrue(first === list.last) XCTAssertTrue(last === list.head) XCTAssertEqual(nodeCount, list.count) } func testArrayLiteralInitTypeInfer() { let arrayLiteralInitInfer: LinkedList = [1.0, 2.0, 3.0] XCTAssertEqual(arrayLiteralInitInfer.count, 3) XCTAssertEqual(arrayLiteralInitInfer.head?.value, 1.0) XCTAssertEqual(arrayLiteralInitInfer.last?.value, 3.0) XCTAssertEqual(arrayLiteralInitInfer[1], 2.0) XCTAssertEqual(arrayLiteralInitInfer.removeLast(), 3.0) XCTAssertEqual(arrayLiteralInitInfer.count, 2) } func testArrayLiteralInitExplicit() { let arrayLiteralInitExplicit: LinkedList = [1, 2, 3] XCTAssertEqual(arrayLiteralInitExplicit.count, 3) XCTAssertEqual(arrayLiteralInitExplicit.head?.value, 1) XCTAssertEqual(arrayLiteralInitExplicit.last?.value, 3) XCTAssertEqual(arrayLiteralInitExplicit[1], 2) XCTAssertEqual(arrayLiteralInitExplicit.removeLast(), 3) XCTAssertEqual(arrayLiteralInitExplicit.count, 2) } func testConformanceToCollectionProtocol() { let collection: LinkedList = [1, 2, 3, 4, 5] let index2 = collection.index(collection.startIndex, offsetBy: 2) let value = collection[index2] XCTAssertTrue(value == 3) } } ================================================ FILE: Linked List/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3F81C77A618003CECC7 /* LinkedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F71C77A618003CECC7 /* LinkedList.swift */; }; 7B80C3FA1C77A61E003CECC7 /* LinkedListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F91C77A61E003CECC7 /* LinkedListTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3F71C77A618003CECC7 /* LinkedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LinkedList.swift; path = ../LinkedList.swift; sourceTree = SOURCE_ROOT; }; 7B80C3F91C77A61E003CECC7 /* LinkedListTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkedListTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3F71C77A618003CECC7 /* LinkedList.swift */, 7B80C3F91C77A61E003CECC7 /* LinkedListTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3F81C77A618003CECC7 /* LinkedList.swift in Sources */, 7B80C3FA1C77A61E003CECC7 /* LinkedListTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Linked List/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Longest Common Subsequence/LongestCommonSubsequence.playground/Contents.swift ================================================ // last checked with Xcode 11.4 #if swift(>=4.0) print("Hello, Swift 4!") #endif extension String { public func longestCommonSubsequence(_ other: String) -> String { func lcsLength(_ other: String) -> [[Int]] { var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.count+1), count: self.count+1) for (i, selfChar) in self.enumerated() { for (j, otherChar) in other.enumerated() { if otherChar == selfChar { matrix[i+1][j+1] = matrix[i][j] + 1 } else { matrix[i+1][j+1] = max(matrix[i][j+1], matrix[i+1][j]) } } } return matrix } func backtrack(_ matrix: [[Int]]) -> String { var i = self.count var j = other.count var charInSequence = self.endIndex var lcs = String() while i >= 1 && j >= 1 { if matrix[i][j] == matrix[i][j - 1] { j -= 1 } else if matrix[i][j] == matrix[i - 1][j] { i -= 1 charInSequence = self.index(before: charInSequence) } else { i -= 1 j -= 1 charInSequence = self.index(before: charInSequence) lcs.append(self[charInSequence]) } } return String(lcs.reversed()) } return backtrack(lcsLength(other)) } } // Examples let a = "ABCBX" let b = "ABDCAB" let c = "KLMK" a.longestCommonSubsequence(c) // "" a.longestCommonSubsequence("") // "" a.longestCommonSubsequence(b) // "ABCB" b.longestCommonSubsequence(a) // "ABCB" a.longestCommonSubsequence(a) // "ABCBX" "Hello World".longestCommonSubsequence("Bonjour le monde") ================================================ FILE: Longest Common Subsequence/LongestCommonSubsequence.playground/contents.xcplayground ================================================ ================================================ FILE: Longest Common Subsequence/LongestCommonSubsequence.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Longest Common Subsequence/LongestCommonSubsequence.swift ================================================ extension String { public func longestCommonSubsequence(_ other: String) -> String { // Computes the length of the lcs using dynamic programming. // Output is a matrix of size (n+1)x(m+1), where matrix[x][y] is the length // of lcs between substring (0, x-1) of self and substring (0, y-1) of other. func lcsLength(_ other: String) -> [[Int]] { // Create matrix of size (n+1)x(m+1). The algorithm needs first row and // first column to be filled with 0. var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1) for (i, selfChar) in self.characters.enumerated() { for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { // Common char found, add 1 to highest lcs found so far. matrix[i+1][j+1] = matrix[i][j] + 1 } else { // Not a match, propagates highest lcs length found so far. matrix[i+1][j+1] = max(matrix[i][j+1], matrix[i+1][j]) } } } // Due to propagation, lcs length is at matrix[n][m]. return matrix } // Backtracks from matrix[n][m] to matrix[1][1] looking for chars that are // common to both strings. func backtrack(_ matrix: [[Int]]) -> String { var i = self.characters.count var j = other.characters.count // charInSequence is in sync with i so we can get self[i] var charInSequence = self.endIndex var lcs = String() while i >= 1 && j >= 1 { // Indicates propagation without change: no new char was added to lcs. if matrix[i][j] == matrix[i][j - 1] { j -= 1 } // Indicates propagation without change: no new char was added to lcs. else if matrix[i][j] == matrix[i - 1][j] { i -= 1 // As i was decremented, move back charInSequence. charInSequence = self.index(before: charInSequence) } // Value on the left and above are different than current cell. // This means 1 was added to lcs length (line 17). else { i -= 1 j -= 1 charInSequence = self.index(before: charInSequence) lcs.append(self[charInSequence]) } } // Due to backtrack, chars were added in reverse order: reverse it back. // Append and reverse is faster than inserting at index 0. return String(lcs.characters.reversed()) } // Combine dynamic programming approach with backtrack to find the lcs. return backtrack(lcsLength(other)) } } ================================================ FILE: Longest Common Subsequence/README.markdown ================================================ # Longest Common Subsequence The Longest Common Subsequence (LCS) of two strings is the longest sequence of characters that appear in the same order in both strings. For example the LCS of `"Hello World"` and `"Bonjour le monde"` is `"oorld"`. If you go through both strings from left-to-right, you'll find that the characters `o`, `o`, `r`, `l`, `d` appear in both strings in that order. Other possible subsequences are `"ed"` and `"old"`, but these are all shorter than `"oorld"`. > **Note:** This should not be confused with the Longest Common Substring problem, where the characters must form a substring of both strings, i.e they have to be immediate neighbors. With a subsequence, it's OK if the characters are not right next to each other, but they must be in the same order. One way to find the LCS of two strings `a` and `b` is using dynamic programming and a backtracking strategy. ## Finding the length of the LCS with dynamic programming First, we want to find the length of the longest common subsequence between strings `a` and `b`. We're not looking for the actual subsequence yet, only how long it is. To determine the length of the LCS between all combinations of substrings of `a` and `b`, we can use a *dynamic programming* technique. Dynamic programming basically means that you compute all possibilities and store them inside a look-up table. > **Note:** During the following explanation, `n` is the length of string `a`, and `m` is the length of string `b`. To find the lengths of all possible subsequences, we use a helper function, `lcsLength(_:)`. This creates a matrix of size `(n+1)` by `(m+1)`, where `matrix[x][y]` is the length of the LCS between the substrings `a[0...x-1]` and `b[0...y-1]`. Given strings `"ABCBX"` and `"ABDCAB"`, the output matrix of `lcsLength(_:)` is the following: ``` | | Ø | A | B | D | C | A | B | | Ø | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | A | 0 | 1 | 1 | 1 | 1 | 1 | 1 | | B | 0 | 1 | 2 | 2 | 2 | 2 | 2 | | C | 0 | 1 | 2 | 2 | 3 | 3 | 3 | | B | 0 | 1 | 2 | 2 | 3 | 3 | 4 | | X | 0 | 1 | 2 | 2 | 3 | 3 | 4 | ``` In this example, if we look at `matrix[3][4]` we find the value `3`. This means the length of the LCS between `a[0...2]` and `b[0...3]`, or between `"ABC"` and `"ABDC"`, is 3. That is correct, because these two substrings have the subsequence `ABC` in common. (Note: the first row and column of the matrix are always filled with zeros.) Here is the source code for `lcsLength(_:)`; this lives in an extension on `String`: ```swift func lcsLength(_ other: String) -> [[Int]] { var matrix = [[Int]](repeating: [Int](repeating: 0, count: other.characters.count+1), count: self.characters.count+1) for (i, selfChar) in self.characters.enumerated() { for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { // Common char found, add 1 to highest lcs found so far. matrix[i+1][j+1] = matrix[i][j] + 1 } else { // Not a match, propagates highest lcs length found so far. matrix[i+1][j+1] = max(matrix[i][j+1], matrix[i+1][j]) } } } return matrix } ``` First, this creates a new matrix -- really a 2-dimensional array -- and fills it with zeros. Then it loops through both strings, `self` and `other`, and compares their characters in order to fill in the matrix. If two characters match, we increment the length of the subsequence. However, if two characters are different, then we "propagate" the highest LCS length found so far. Let's say the following is the current situation: ``` | | Ø | A | B | D | C | A | B | | Ø | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | A | 0 | 1 | 1 | 1 | 1 | 1 | 1 | | B | 0 | 1 | 2 | 2 | 2 | 2 | 2 | | C | 0 | 1 | 2 | * | | | | | B | 0 | | | | | | | | X | 0 | | | | | | | ``` The `*` marks the two characters we're currently comparing, `C` versus `D`. These characters are not the same, so we propagate the highest length we've seen so far, which is `2`: ``` | | Ø | A | B | D | C | A | B | | Ø | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | A | 0 | 1 | 1 | 1 | 1 | 1 | 1 | | B | 0 | 1 | 2 | 2 | 2 | 2 | 2 | | C | 0 | 1 | 2 | 2 | * | | | | B | 0 | | | | | | | | X | 0 | | | | | | | ``` Now we compare `C` with `C`. These are equal, and we increment the length to `3`: ``` | | Ø | A | B | D | C | A | B | | Ø | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | A | 0 | 1 | 1 | 1 | 1 | 1 | 1 | | B | 0 | 1 | 2 | 2 | 2 | 2 | 2 | | C | 0 | 1 | 2 | 2 | 3 | * | | | B | 0 | | | | | | | | X | 0 | | | | | | | ``` And so on... this is how `lcsLength(_:)` fills in the entire matrix. ## Backtracking to find the actual subsequence So far we've calculated the length of every possible subsequence. The length of the longest subsequence is found in the bottom-right corner of matrix, at `matrix[n+1][m+1]`. In the above example it is 4, so the LCS consists of 4 characters. Having the length of every combination of substrings makes it possible to determine *which* characters are part of the LCS itself by using a backtracking strategy. Backtracking starts at `matrix[n+1][m+1]` and walks up and left (in this priority) looking for changes that do not indicate a simple propagation. ``` | | Ø| A| B| D| C| A| B| | Ø | 0| 0| 0| 0| 0| 0| 0| | A | 0|↖ 1| 1| 1| 1| 1| 1| | B | 0| 1|↖ 2|← 2| 2| 2| 2| | C | 0| 1| 2| 2|↖ 3|← 3| 3| | B | 0| 1| 2| 2| 3| 3|↖ 4| | X | 0| 1| 2| 2| 3| 3|↑ 4| ``` Each `↖` move indicates a character (in row/column header) that is part of the LCS. If the number on the left and above are different than the number in the current cell, no propagation happened. In that case `matrix[i][j]` indicates a common char between the strings `a` and `b`, so the characters at `a[i - 1]` and `b[j - 1]` are part of the LCS that we're looking for. One thing to notice is, as it's running backwards, the LCS is built in reverse order. Before returning, the result is reversed to reflect the actual LCS. Here is the backtracking code: ```swift func backtrack(_ matrix: [[Int]]) -> String { var i = self.characters.count var j = other.characters.count var charInSequence = self.endIndex var lcs = String() while i >= 1 && j >= 1 { // Indicates propagation without change: no new char was added to lcs. if matrix[i][j] == matrix[i][j - 1] { j -= 1 } // Indicates propagation without change: no new char was added to lcs. else if matrix[i][j] == matrix[i - 1][j] { i -= 1 charInSequence = self.index(before: charInSequence) } // Value on the left and above are different than current cell. // This means 1 was added to lcs length. else { i -= 1 j -= 1 charInSequence = self.index(before: charInSequence) lcs.append(self[charInSequence]) } } return String(lcs.characters.reversed()) } ``` This backtracks from `matrix[n+1][m+1]` (bottom-right corner) to `matrix[1][1]` (top-left corner), looking for characters that are common to both strings. It adds those characters to a new string, `lcs`. The `charInSequence` variable is an index into the string given by `self`. Initially this points to the last character of the string. Each time we decrement `i`, we also move back `charInSequence`. When the two characters are found to be equal, we add the character at `self[charInSequence]` to the new `lcs` string. (We can't just write `self[i]` because `i` may not map to the current position inside the Swift string.) Due to backtracking, characters are added in reverse order, so at the end of the function we call `reversed()` to put the string in the right order. (Appending new characters to the end of the string and then reversing it once is faster than always inserting the characters at the front of the string.) ## Putting it all together To find the LCS between two strings, we first call `lcsLength(_:)` and then `backtrack(_:)`: ```swift extension String { public func longestCommonSubsequence(_ other: String) -> String { func lcsLength(_ other: String) -> [[Int]] { ... } func backtrack(_ matrix: [[Int]]) -> String { ... } return backtrack(lcsLength(other)) } } ``` To keep everything tidy, the two helper functions are nested inside the main `longestCommonSubsequence()` function. Here's how you could try it out in a Playground: ```swift let a = "ABCBX" let b = "ABDCAB" a.longestCommonSubsequence(b) // "ABCB" let c = "KLMK" a.longestCommonSubsequence(c) // "" (no common subsequence) "Hello World".longestCommonSubsequence("Bonjour le monde") // "oorld" ``` *Written for Swift Algorithm Club by Pedro Vereza* ================================================ FILE: Longest Common Subsequence/Tests/LongestCommonSubsequenceTests.swift ================================================ import Foundation import XCTest class LongestCommonSubsequenceTests: XCTestCase { func testLCSwithSelfIsSelf() { let a = "ABCDE" XCTAssertEqual(a, a.longestCommonSubsequence(a)) } func testLCSWithEmptyStringIsEmptyString() { let a = "ABCDE" XCTAssertEqual("", a.longestCommonSubsequence("")) } func testLCSIsEmptyWhenNoCharMatches() { let a = "ABCDE" let b = "WXYZ" XCTAssertEqual("", a.longestCommonSubsequence(b)) } func testLCSIsNotCommutative() { let a = "ABCDEF" let b = "XAWDMVBEKD" XCTAssertEqual("ADE", a.longestCommonSubsequence(b)) XCTAssertEqual("ABD", b.longestCommonSubsequence(a)) } } ================================================ FILE: Longest Common Subsequence/Tests/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Longest Common Subsequence/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 4716C7AF1C93751E00F6C1C0 /* LongestCommonSubsequenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4716C7891C936E0E00F6C1C0 /* LongestCommonSubsequenceTests.swift */; }; 4716C7B01C93751E00F6C1C0 /* LongestCommonSubsequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4716C7881C936DDD00F6C1C0 /* LongestCommonSubsequence.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 4716C7881C936DDD00F6C1C0 /* LongestCommonSubsequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LongestCommonSubsequence.swift; path = ../../LongestCommonSubsequence.swift; sourceTree = ""; }; 4716C7891C936E0E00F6C1C0 /* LongestCommonSubsequenceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LongestCommonSubsequenceTests.swift; path = ../LongestCommonSubsequenceTests.swift; sourceTree = ""; }; 4716C7A71C93750500F6C1C0 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 4716C7AB1C93750500F6C1C0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 4716C7A41C93750500F6C1C0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 4716C7811C936DCB00F6C1C0 = { isa = PBXGroup; children = ( 4716C7A81C93750500F6C1C0 /* Tests */, 4716C78F1C93746D00F6C1C0 /* Products */, ); sourceTree = ""; }; 4716C78F1C93746D00F6C1C0 /* Products */ = { isa = PBXGroup; children = ( 4716C7A71C93750500F6C1C0 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 4716C7A81C93750500F6C1C0 /* Tests */ = { isa = PBXGroup; children = ( 4716C7881C936DDD00F6C1C0 /* LongestCommonSubsequence.swift */, 4716C7891C936E0E00F6C1C0 /* LongestCommonSubsequenceTests.swift */, 4716C7AB1C93750500F6C1C0 /* Info.plist */, ); path = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 4716C7A61C93750500F6C1C0 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 4716C7AC1C93750500F6C1C0 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 4716C7A31C93750500F6C1C0 /* Sources */, 4716C7A41C93750500F6C1C0 /* Frameworks */, 4716C7A51C93750500F6C1C0 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = 4716C7A71C93750500F6C1C0 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 4716C7821C936DCB00F6C1C0 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; TargetAttributes = { 4716C7A61C93750500F6C1C0 = { CreatedOnToolsVersion = 7.2.1; }; }; }; buildConfigurationList = 4716C7851C936DCB00F6C1C0 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 4716C7811C936DCB00F6C1C0; productRefGroup = 4716C78F1C93746D00F6C1C0 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 4716C7A61C93750500F6C1C0 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 4716C7A51C93750500F6C1C0 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 4716C7A31C93750500F6C1C0 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 4716C7AF1C93751E00F6C1C0 /* LongestCommonSubsequenceTests.swift in Sources */, 4716C7B01C93751E00F6C1C0 /* LongestCommonSubsequence.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 4716C7861C936DCB00F6C1C0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; 4716C7871C936DCB00F6C1C0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 4716C7AD1C93750500F6C1C0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = me.pedrovereza.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; }; name = Debug; }; 4716C7AE1C93750500F6C1C0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = me.pedrovereza.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 4716C7851C936DCB00F6C1C0 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 4716C7861C936DCB00F6C1C0 /* Debug */, 4716C7871C936DCB00F6C1C0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 4716C7AC1C93750500F6C1C0 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 4716C7AD1C93750500F6C1C0 /* Debug */, 4716C7AE1C93750500F6C1C0 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 4716C7821C936DCB00F6C1C0 /* Project object */; } ================================================ FILE: Longest Common Subsequence/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Longest Common Subsequence/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Merge Sort/MergeSort.playground/Contents.swift ================================================ /* Top-down recursive version */ func mergeSort(_ array: [T]) -> [T] { guard array.count > 1 else { return array } let middleIndex = array.count / 2 let leftArray = mergeSort(Array(array[0..(leftPile: [T], rightPile: [T]) -> [T] { var leftIndex = 0 var rightIndex = 0 var orderedPile = [T]() if orderedPile.capacity < leftPile.count + rightPile.count { orderedPile.reserveCapacity(leftPile.count + rightPile.count) } while true { guard leftIndex < leftPile.endIndex else { orderedPile.append(contentsOf: rightPile[rightIndex..(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let n = a.count var z = [a, a] // the two working arrays var d = 0 // z[d] is used for reading, z[1 - d] for writing var width = 1 while width < n { var i = 0 while i < n { var j = i var l = i var r = i + width let lmax = min(l + width, n) let rmax = min(r + width, n) while l < lmax && r < rmax { if isOrderedBefore(z[d][l], z[d][r]) { z[1 - d][j] = z[d][l] l += 1 } else { z[1 - d][j] = z[d][r] r += 1 } j += 1 } while l < lmax { z[1 - d][j] = z[d][l] j += 1 l += 1 } while r < rmax { z[1 - d][j] = z[d][r] j += 1 r += 1 } i += width*2 } width *= 2 // in each step, the subarray to merge becomes larger d = 1 - d // swap active array } return z[d] } mergeSortBottomUp(array, <) ================================================ FILE: Merge Sort/MergeSort.playground/contents.xcplayground ================================================ ================================================ FILE: Merge Sort/MergeSort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Merge Sort/MergeSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Merge Sort/MergeSort.swift ================================================ // // Mergesort.swift // // // Created by Kelvin Lau on 2016-02-03. // // func mergeSort(_ array: [T]) -> [T] { guard array.count > 1 else { return array } let middleIndex = array.count / 2 let leftArray = mergeSort(Array(array[0..(leftPile: [T], rightPile: [T]) -> [T] { var leftIndex = 0 var rightIndex = 0 var orderedPile: [T] = [] if orderedPile.capacity < leftPile.count + rightPile.count { orderedPile.reserveCapacity(leftPile.count + rightPile.count) } while true { guard leftIndex < leftPile.endIndex else { orderedPile.append(contentsOf: rightPile[rightIndex..(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let n = a.count var z = [a, a] // the two working arrays var d = 0 // z[d] is used for reading, z[1 - d] for writing var width = 1 while width < n { var i = 0 while i < n { var j = i var l = i var r = i + width let lmax = min(l + width, n) let rmax = min(r + width, n) while l < lmax && r < rmax { if isOrderedBefore(z[d][l], z[d][r]) { z[1 - d][j] = z[d][l] l += 1 } else { z[1 - d][j] = z[d][r] r += 1 } j += 1 } while l < lmax { z[1 - d][j] = z[d][l] j += 1 l += 1 } while r < rmax { z[1 - d][j] = z[d][r] j += 1 r += 1 } i += width*2 } width *= 2 // in each step, the subarray to merge becomes larger d = 1 - d // swap active array } return z[d] } ================================================ FILE: Merge Sort/README.markdown ================================================ # Merge Sort > This topic has been tutorialized [here](https://www.raywenderlich.com/154256/swift-algorithm-club-swift-merge-sort) Goal: Sort an array from low to high (or high to low) Invented in 1945 by John von Neumann, merge-sort is an efficient algorithm with a best, worst, and average time complexity of **O(n log n)**. The merge-sort algorithm uses the **divide and conquer** approach which is to divide a big problem into smaller problems and solve them. I think of the merge-sort algorithm as **split first** and **merge after**. Assume you need to sort an array of *n* numbers in the right order. The merge-sort algorithm works as follows: - Put the numbers in an unsorted pile. - Split the pile into two. Now, you have **two unsorted piles** of numbers. - Keep splitting the resulting piles until you cannot split anymore. In the end, you will have *n* piles with one number in each pile. - Begin to **merge** the piles together by pairing them sequentially. During each merge, put the contents in sorted order. This is fairly easy because each individual pile is already sorted. ## An example ### Splitting Assume you are given an array of *n* numbers as`[2, 1, 5, 4, 9]`. This is an unsorted pile. The goal is to keep splitting the pile until you cannot split anymore. First, split the array into two halves: `[2, 1]` and `[5, 4, 9]`. Can you keep splitting them? Yes, you can! Focus on the left pile. Split`[2, 1]` into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile. Split `[5, 4, 9]` into `[5]` and `[4, 9]`. Unsurprisingly, `[5]` cannot be split anymore, but `[4, 9]` can be split into `[4]` and `[9]`. The splitting process ends with the following piles: `[2]` `[1]` `[5]` `[4]` `[9]`. Notice that each pile consists of just one element. ### Merging Now that you have split the array, you should **merge** the piles together **while sorting them**. Remember, the idea is to solve many small problems rather than a big one. For each merge iteration, you must be concerned at merging one pile with another. Given the piles `[2]` `[1]` `[5]` `[4]` `[9]`, the first pass will result in `[1, 2]` and `[4, 5]` and `[9]`. Since `[9]` is the odd one out, you cannot merge it with anything during this pass. The next pass will merge `[1, 2]` and `[4, 5]` together. This results in `[1, 2, 4, 5]`, with the `[9]` left out again because it is the odd one out. You are left with only two piles `[1, 2, 4, 5]` and `[9]`, finally gets its chance to merge, resulting in the sorted array as `[1, 2, 4, 5, 9]`. ## Top-down implementation Here's what merge sort may look like in Swift: ```swift func mergeSort(_ array: [Int]) -> [Int] { guard array.count > 1 else { return array } // 1 let middleIndex = array.count / 2 // 2 let leftArray = mergeSort(Array(array[0.. [Int] { // 1 var leftIndex = 0 var rightIndex = 0 // 2 var orderedPile = [Int]() orderedPile.reserveCapacity(leftPile.count + rightPile.count) // 3 while leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { orderedPile.append(leftPile[leftIndex]) leftIndex += 1 } else if leftPile[leftIndex] > rightPile[rightIndex] { orderedPile.append(rightPile[rightIndex]) rightIndex += 1 } else { orderedPile.append(leftPile[leftIndex]) leftIndex += 1 orderedPile.append(rightPile[rightIndex]) rightIndex += 1 } } // 4 while leftIndex < leftPile.count { orderedPile.append(leftPile[leftIndex]) leftIndex += 1 } while rightIndex < rightPile.count { orderedPile.append(rightPile[rightIndex]) rightIndex += 1 } return orderedPile } ``` This method may look scary, but it is quite straightforward: 1. You need two indexes to keep track of your progress for the two arrays while merging. 2. This is the merged array. It is empty right now, but you will build it up in subsequent steps by appending elements from the other arrays. Since you already know number of elements that will end up in this array, you reserve capacity to avoid reallocation overhead later. 3. This while-loop will compare the elements from the left and right sides and append them into the `orderedPile` while making sure that the result stays in order. 4. If control exits from the previous while-loop, it means that either the `leftPile` or the `rightPile` has its contents completely merged into the `orderedPile`. At this point, you no longer need to do comparisons. Just append the rest of the contents of the other array until there is no more to append. As an example of how `merge()` works, suppose that we have the following piles: `leftPile = [1, 7, 8]` and `rightPile = [3, 6, 9]`. Note that each of these piles is individually sorted already -- that is always true with merge sort. These are merged into one larger sorted pile in the following steps: leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ ] l r The left index, here represented as `l`, points at the first item from the left pile, `1`. The right index, `r`, points at `3`. Therefore, the first item we add to `orderedPile` is `1`. We also move the left index `l` to the next item. leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1 ] -->l r Now `l` points at `7` but `r` is still at `3`. We add the smallest item to the ordered pile, so that is `3`. The situation is now: leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3 ] l -->r This process repeats. At each step, we pick the smallest item from either the `leftPile` or the `rightPile` and add the item into the `orderedPile`: leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3, 6 ] l -->r leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3, 6, 7 ] -->l r leftPile rightPile orderedPile [ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3, 6, 7, 8 ] -->l r Now, there are no more items in the left pile. We simply add the remaining items from the right pile, and we are done. The merged pile is `[ 1, 3, 6, 7, 8, 9 ]`. Notice that, this algorithm is very simple: it moves from left-to-right through the two piles and at every step picks the smallest item. This works because we guarantee that each of the piles is already sorted. ## Bottom-up implementation The implementation of the merge-sort algorithm you have seen so far is called the "top-down" approach because it first splits the array into smaller piles and then merges them. When sorting an array (as opposed to, say, a linked list) you can actually skip the splitting step and immediately start merging the individual array elements. This is called the "bottom-up" approach. Time to step up the game a little. :-) Here is a complete bottom-up implementation in Swift: ```swift func mergeSortBottomUp(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let n = a.count var z = [a, a] // 1 var d = 0 var width = 1 while width < n { // 2 var i = 0 while i < n { // 3 var j = i var l = i var r = i + width let lmax = min(l + width, n) let rmax = min(r + width, n) while l < lmax && r < rmax { // 4 if isOrderedBefore(z[d][l], z[d][r]) { z[1 - d][j] = z[d][l] l += 1 } else { z[1 - d][j] = z[d][r] r += 1 } j += 1 } while l < lmax { z[1 - d][j] = z[d][l] j += 1 l += 1 } while r < rmax { z[1 - d][j] = z[d][r] j += 1 r += 1 } i += width*2 } width *= 2 d = 1 - d // 5 } return z[d] } ``` It looks a lot more intimidating than the top-down version, but notice that the main body includes the same three `while` loops from `merge()`. Notable points: 1. The Merge-sort algorithm needs a temporary working array because you cannot merge the left and right piles and at the same time overwrite their contents. Because allocating a new array for each merge is wasteful, we are using two working arrays, and we will switch between them using the value of `d`, which is either 0 or 1. The array `z[d]` is used for reading, and `z[1 - d]` is used for writing. This is called *double-buffering*. 2. Conceptually, the bottom-up version works the same way as the top-down version. First, it merges small piles of one element each, then it merges piles of two elements each, then piles of four elements each, and so on. The size of the pile is given by `width`. Initially, `width` is `1` but at the end of each loop iteration, we multiply it by two, so this outer loop determines the size of the piles being merged, and the subarrays to merge become larger in each step. 3. The inner loop steps through the piles and merges each pair of piles into a larger one. The result is written in the array given by `z[1 - d]`. 4. This is the same logic as in the top-down version. The main difference is that we're using double-buffering, so values are read from `z[d]` and written into `z[1 - d]`. It also uses an `isOrderedBefore` function to compare the elements rather than just `<`, so this merge-sort algorithm is generic, and you can use it to sort any kind of object you want. 5. At this point, the piles of size `width` from array `z[d]` have been merged into larger piles of size `width * 2` in array `z[1 - d]`. Here, we swap the active array, so that in the next step we'll read from the new piles we have just created. This function is generic, so you can use it to sort any type you desire, as long as you provide a proper `isOrderedBefore` closure to compare the elements. Example of how to use it: ```swift let array = [2, 1, 5, 4, 9] mergeSortBottomUp(array, <) // [1, 2, 4, 5, 9] ``` ## Performance The speed of the merge-sort algorithm is dependent on the size of the array it needs to sort. The larger the array, the more work it needs to do. Whether or not the initial array is sorted already does not affect the speed of the merge-sort algorithm since you will be doing the same amount splits and comparisons regardless of the initial order of the elements. Therefore, the time complexity for the best, worst, and average case will always be **O(n log n)**. A disadvantage of the merge-sort algorithm is that it needs a temporary "working" array equal in size to the array being sorted. It is not an **in-place** sort, unlike for example [quicksort](../Quicksort/). Most implementations of the merge-sort algorithm produce a **stable** sort. This means that array elements that have identical sort keys will stay in the same order relative to each other after sorting. This is not important for simple values such as numbers or strings, but it can be an issue when sorting more complex objects. ## See also [Merge sort on Wikipedia](https://en.wikipedia.org/wiki/Merge_sort) *Written by Kelvin Lau. Additions by Matthijs Hollemans.* ================================================ FILE: Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play do { // Real primes try checkWithMillerRabin(5) try checkWithMillerRabin(439) try checkWithMillerRabin(1201) try checkWithMillerRabin(143477) try checkWithMillerRabin(1299869) try checkWithMillerRabin(15487361) try checkWithMillerRabin(179426363) // Fake primes try checkWithMillerRabin(15) try checkWithMillerRabin(435) try checkWithMillerRabin(1207) try checkWithMillerRabin(143473) try checkWithMillerRabin(1291869) try checkWithMillerRabin(15487161) try checkWithMillerRabin(178426363) // Specifying accuracy try checkWithMillerRabin(179426363, accuracy: 10) } catch { dump(error) } ================================================ FILE: Miller-Rabin Primality Test/MRPrimality.playground/Sources/MillerRabin.swift ================================================ // // MRPrimality.swift // // // Created by Sahn Cha on 2016. 10. 18.. // // import Foundation enum MillerRabinError: Error { case primeLowAccuracy case primeLowerBorder case uIntOverflow } /* The Miller–Rabin test relies on an equality or set of equalities that hold true for prime values, then checks whether or not they hold for a number that we want to test for primality. - Parameter n: an odd integer to be tested for primality; - Parameter k: a parameter that determines the accuracy of the test - throws: Can throw an error of type `MillerRabinError`. - Returns: composite if n is composite, otherwise probably prime */ public func checkWithMillerRabin(_ n: UInt, accuracy k: UInt = 1) throws -> Bool { guard k > 0 else { throw MillerRabinError.primeLowAccuracy } guard n > 0 else { throw MillerRabinError.primeLowerBorder } guard n > 3 else { return true } // return false for all even numbers bigger than 2 if n % 2 == 0 { return false } let s: UInt = UInt((n - 1).trailingZeroBitCount) let d: UInt = (n - 1) >> s guard UInt(pow(2.0, Double(s))) * d == n - 1 else { throw MillerRabinError.primeLowerBorder } /// Inspect whether a given witness will reveal the true identity of n. func tryComposite(_ a: UInt, d: UInt, n: UInt) throws -> Bool? { var x = try calculateModularExponentiation(base: a, exponent: d, modulus: n) if x == 1 || x == (n - 1) { return nil } for _ in 1.. UInt { guard modulus > 1 else { return 0 } guard !(modulus-1).multipliedReportingOverflow(by: (modulus-1)).overflow else { throw MillerRabinError.uIntOverflow } var result: UInt = 1 var exponentCopy = exponent var baseCopy = base % modulus while exponentCopy > 0 { if exponentCopy % 2 == 1 { result = (result * baseCopy) % modulus } exponentCopy = exponentCopy >> 1 baseCopy = (baseCopy * baseCopy) % modulus } return result } ================================================ FILE: Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground ================================================ ================================================ FILE: Miller-Rabin Primality Test/MRPrimality.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Miller-Rabin Primality Test/MRPrimality.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Miller-Rabin Primality Test/MRPrimality.swift ================================================ // // MRPrimality.swift // // // Created by Sahn Cha on 2016. 10. 18.. // // import Foundation enum MillerRabinError: Error { case primeLowAccuracy case primeLowerBorder case uIntOverflow } /* The Miller–Rabin test relies on an equality or set of equalities that hold true for prime values, then checks whether or not they hold for a number that we want to test for primality. - Parameter n: an odd integer to be tested for primality; - Parameter k: a parameter that determines the accuracy of the test - throws: Can throw an error of type `MillerRabinError`. - Returns: composite if n is composite, otherwise probably prime */ func checkWithMillerRabin(_ n: UInt, accuracy k: UInt = 1) throws -> Bool { guard k > 0 else { throw MillerRabinError.primeLowAccuracy } guard n > 0 else { throw MillerRabinError.primeLowerBorder } guard n > 3 else { return true } // return false for all even numbers bigger than 2 if n % 2 == 0 { return false } let s: UInt = UInt((n - 1).trailingZeroBitCount) let d: UInt = (n - 1) >> s guard UInt(pow(2.0, Double(s))) * d == n - 1 else { throw EncryptionError.primeLowerBorder } /// Inspect whether a given witness will reveal the true identity of n. func tryComposite(_ a: UInt, d: UInt, n: UInt) throws -> Bool? { var x = try calculateModularExponentiation(base: a, exponent: d, modulus: n) if x == 1 || x == (n - 1) { return nil } for _ in 1.. UInt { guard modulus > 1 else { return 0 } guard !(modulus-1).multipliedReportingOverflow(by: (modulus-1)).overflow else { throw MillerRabinError.uIntOverflow } var result: UInt = 1 var exponentCopy = exponent var baseCopy = base % modulus while exponentCopy > 0 { if exponentCopy % 2 == 1 { result = (result * baseCopy) % modulus } exponentCopy = exponentCopy >> 1 baseCopy = (baseCopy * baseCopy) % modulus } return result } ================================================ FILE: Miller-Rabin Primality Test/README.markdown ================================================ # Miller-Rabin Primality Test In 1976, Gray Miller introduced an algorithm, through his ph.d thesis[1], which determines a primality of the given number. The original algorithm was deterministic under the Extended Reimann Hypothesis, which is yet to be proven. After four years, Michael O. Rabin improved the algorithm[2] by using probabilistic approach and it no longer assumes the unproven hypothesis. ## Probabilistic The result of the test is simply a boolean. However, `true` does not implicate _the number is prime_. In fact, it means _the number is **probably** prime_. But `false` does mean _the number is composite_. In order to increase the accuracy of the test, it needs to be iterated few times. If it returns `true` in every single iteration, then we can say with confidence that _the number is pro......bably prime_. ## Algorithm Let `n` be the given number, and write `n-1` as `2^s·d`, where `d` is odd. And choose a random number `a` within the range from `2` to `n - 1`. Now make a sequence, in modulo `n`, as following: > a^d, a^(2·d), a^(4·d), ... , a^((2^(s-1))·d), a^((2^s)·d) = a^(n-1) And we say the number `n` passes the test, _probably prime_, if 1) `a^d` is congruence to `1` in modulo `n`, or 2) `a^((2^k)·d)` is congruence to `-1` for some `k = 1, 2, ..., s-1`. ### Pseudo Code The following pseudo code is excerpted from Wikipedia[3]: ![Image of Pseudocode](./Images/img_pseudo.png) ## Usage ```swift checkWithMillerRabin(7) // test if 7 is prime. (default iteration = 1) checkWithMillerRabin(7, accuracy: 10) // test if 7 is prime && iterate 10 times. ``` ## Reference 1. G. L. Miller, "Riemann's Hypothesis and Tests for Primality". _J. Comput. System Sci._ 13 (1976), 300-317. 2. M. O. Rabin, "Probabilistic algorithm for testing primality". _Journal of Number Theory._ 12 (1980), 128-138. 3. Miller–Rabin primality test - Wikipedia, the free encyclopedia _Written for Swift Algorithm Club by **Sahn Cha**, @scha00_ _Code updated by **Simon C. Krüger**._ [1]: https://cs.uwaterloo.ca/research/tr/1975/CS-75-27.pdf [2]: http://www.sciencedirect.com/science/article/pii/0022314X80900840 [3]: https://en.wikipedia.org/wiki/Miller–Rabin_primality_test ================================================ FILE: Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift ================================================ // Minimum Edit Distance extension String { public func minimumEditDistance(other: String) -> Int { let m = self.count let n = other.count var matrix = [[Int]](repeating: [Int](repeating: 0, count: n + 1), count: m + 1) // initialize matrix for index in 1...m { // the distance of any first string to an empty second string matrix[index][0] = index } for index in 1...n { // the distance of any second string to an empty first string matrix[0][index] = index } // compute Levenshtein distance for (i, selfChar) in self.enumerated() { for (j, otherChar) in other.enumerated() { if otherChar == selfChar { // substitution of equal symbols with cost 0 matrix[i + 1][j + 1] = matrix[i][j] } else { // minimum of the cost of insertion, deletion, or substitution // added to the already computed costs in the corresponding cells matrix[i + 1][j + 1] = Swift.min(matrix[i][j] + 1, matrix[i + 1][j] + 1, matrix[i][j + 1] + 1) } } } return matrix[m][n] } } "Door".minimumEditDistance(other: "Dolls") ================================================ FILE: Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground ================================================ ================================================ FILE: Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Minimum Edit Distance/README.markdown ================================================ # Minimum Edit Distance The minimum edit distance is a possibility to measure the similarity of two strings *w* and *u* by counting costs of operations which are necessary to transform *w* into *u* (or vice versa). ### Algorithm using Levenshtein distance A common distance measure is given by the *Levenshtein distance*, which allows the following three transformation operations: * **Insertion** (*ε→x*) of a single symbol *x* with **cost 1**, * **Deletion** (*x→ε*) of a single symbol *x* with **cost 1**, and * **Substitution** (*x→y*) of two single symbols *x, y* with **cost 1** if *x≠y* and with **cost 0** otherwise. When transforming a string by a sequence of operations, the costs of the single operations are added to obtain the (minimal) edit distance. For example, the string *Door* can be transformed by the operations *o→l*, *r→l*, *ε→s* to the string *Dolls*, which results in a minimum edit distance of 3. To avoid exponential time complexity, the minimum edit distance of two strings in the usual is computed using *dynamic programming*. For this in a matrix ```swift var matrix = [[Int]](repeating: [Int](repeating: 0, count: n + 1), count: m + 1) ``` already computed minimal edit distances of prefixes of *w* and *u* (of length *m* and *n*, respectively) are used to fill the matrix. In a first step the matrix is initialized by filling the first row and the first column as follows: ```swift // initialize matrix for index in 1...m { // the distance of any first string to an empty second string matrix[index][0] = index } for index in 1...n { // the distance of any second string to an empty first string matrix[0][index] = index } ``` Then in each cell the minimum of the cost of insertion, deletion, or substitution added to the already computed costs in the corresponding cells is chosen. In this way the matrix is filled iteratively: ```swift // compute Levenshtein distance for (i, selfChar) in self.enumerated() { for (j, otherChar) in other.enumerated() { if otherChar == selfChar { // substitution of equal symbols with cost 0 matrix[i + 1][j + 1] = matrix[i][j] } else { // minimum of the cost of insertion, deletion, or substitution // added to the already computed costs in the corresponding cells matrix[i + 1][j + 1] = Swift.min(matrix[i][j] + 1, matrix[i + 1][j] + 1, matrix[i][j + 1] + 1) } } } ``` After applying this algorithm, the minimal edit distance can be read from the rightmost bottom cell and is returned. ```swift return matrix[m][n] ``` This algorithm has a time complexity of Θ(*mn*). **TODO**: Other distance measures. *Written for Swift Algorithm Club by Luisa Herrmann* ================================================ FILE: Minimum Spanning Tree/Kruskal.swift ================================================ // // Kruskal.swift // // // Created by xiang xin on 16/3/17. // // func minimumSpanningTreeKruskal(graph: Graph) -> (cost: Int, tree: Graph) { var cost: Int = 0 var tree = Graph() let sortedEdgeListByWeight = graph.edgeList.sorted(by: { $0.weight < $1.weight }) var unionFind = UnionFind() for vertex in graph.vertices { unionFind.addSetWith(vertex) } for edge in sortedEdgeListByWeight { let v1 = edge.vertex1 let v2 = edge.vertex2 if !unionFind.inSameSet(v1, and: v2) { cost += edge.weight tree.addEdge(edge) unionFind.unionSetsContaining(v1, and: v2) } } return (cost: cost, tree: tree) } ================================================ FILE: Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift ================================================ /** The following code demonstrates getting MST of the graph below by both Kruskal's and Prim's algorithms. */ func minimumSpanningTreeKruskal(graph: Graph) -> (cost: Int, tree: Graph) { var cost: Int = 0 var tree = Graph() let sortedEdgeListByWeight = graph.edgeList.sorted(by: { $0.weight < $1.weight }) var unionFind = UnionFind() for vertex in graph.vertices { unionFind.addSetWith(vertex) } for edge in sortedEdgeListByWeight { let v1 = edge.vertex1 let v2 = edge.vertex2 if !unionFind.inSameSet(v1, and: v2) { cost += edge.weight tree.addEdge(edge) unionFind.unionSetsContaining(v1, and: v2) } } return (cost: cost, tree: tree) } func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) { var cost: Int = 0 var tree = Graph() guard let start = graph.vertices.first else { return (cost: cost, tree: tree) } var visited = Set() var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>( sort: { $0.weight < $1.weight }) priorityQueue.enqueue((vertex: start, weight: 0, parent: nil)) while let head = priorityQueue.dequeue() { let vertex = head.vertex if visited.contains(vertex) { continue } visited.insert(vertex) cost += head.weight if let prev = head.parent { tree.addEdge(vertex1: prev, vertex2: vertex, weight: head.weight) } if let neighbours = graph.adjList[vertex] { for neighbour in neighbours { let nextVertex = neighbour.vertex if !visited.contains(nextVertex) { priorityQueue.enqueue((vertex: nextVertex, weight: neighbour.weight, parent: vertex)) } } } } return (cost: cost, tree: tree) } /*: ![Graph](mst.png) */ var graph = Graph() graph.addEdge(vertex1: 1, vertex2: 2, weight: 6) graph.addEdge(vertex1: 1, vertex2: 3, weight: 1) graph.addEdge(vertex1: 1, vertex2: 4, weight: 5) graph.addEdge(vertex1: 2, vertex2: 3, weight: 5) graph.addEdge(vertex1: 2, vertex2: 5, weight: 3) graph.addEdge(vertex1: 3, vertex2: 4, weight: 5) graph.addEdge(vertex1: 3, vertex2: 5, weight: 6) graph.addEdge(vertex1: 3, vertex2: 6, weight: 4) graph.addEdge(vertex1: 4, vertex2: 6, weight: 2) graph.addEdge(vertex1: 5, vertex2: 6, weight: 6) print("===== Kruskal's =====") let result1 = minimumSpanningTreeKruskal(graph: graph) print("Minimum spanning tree total weight: \(result1.cost)") print("Minimum spanning tree:") print(result1.tree) print("===== Prim's =====") let result2 = minimumSpanningTreePrim(graph: graph) print("Minimum spanning tree total weight: \(result2.cost)") print("Minimum spanning tree:") print(result2.tree) ================================================ FILE: Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift ================================================ // Undirected edge public struct Edge: CustomStringConvertible { public let vertex1: T public let vertex2: T public let weight: Int public var description: String { return "[\(vertex1)-\(vertex2), \(weight)]" } } // Undirected weighted graph public struct Graph: CustomStringConvertible { public private(set) var edgeList: [Edge] public private(set) var vertices: Set public private(set) var adjList: [T: [(vertex: T, weight: Int)]] public init() { edgeList = [Edge]() vertices = Set() adjList = [T: [(vertex: T, weight: Int)]]() } public var description: String { var description = "" for edge in edgeList { description += edge.description + "\n" } return description } public mutating func addEdge(vertex1 v1: T, vertex2 v2: T, weight w: Int) { edgeList.append(Edge(vertex1: v1, vertex2: v2, weight: w)) vertices.insert(v1) vertices.insert(v2) adjList[v1] = adjList[v1] ?? [] adjList[v1]?.append((vertex: v2, weight: w)) adjList[v2] = adjList[v2] ?? [] adjList[v2]?.append((vertex: v1, weight: w)) } public mutating func addEdge(_ edge: Edge) { addEdge(vertex1: edge.vertex1, vertex2: edge.vertex2, weight: edge.weight) } } ================================================ FILE: Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift ================================================ // // Heap.swift // Written for the Swift Algorithm Club by Kevin Randrup and Matthijs Hollemans // public struct Heap { /** The array that stores the heap's nodes. */ var elements = [T]() /** Determines whether this is a max-heap (>) or min-heap (<). */ fileprivate var isOrderedBefore: (T, T) -> Bool /** * Creates an empty heap. * The sort function determines whether this is a min-heap or max-heap. * For integers, > makes a max-heap, < makes a min-heap. */ public init(sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort } /** * Creates a heap from an array. The order of the array does not matter; * the elements are inserted into the heap in the order determined by the * sort function. */ public init(array: [T], sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort buildHeap(fromArray: array) } /* // This version has O(n log n) performance. private mutating func buildHeap(array: [T]) { elements.reserveCapacity(array.count) for value in array { insert(value) } } */ /** * Converts an array to a max-heap or min-heap in a bottom-up manner. * Performance: This runs pretty much in O(n). */ fileprivate mutating func buildHeap(fromArray array: [T]) { elements = array for i in stride(from: (elements.count/2 - 1), through: 0, by: -1) { shiftDown(i, heapSize: elements.count) } } public var isEmpty: Bool { return elements.isEmpty } public var count: Int { return elements.count } /** * Returns the index of the parent of the element at index i. * The element at index 0 is the root of the tree and has no parent. */ @inline(__always) func parentIndex(ofIndex i: Int) -> Int { return (i - 1) / 2 } /** * Returns the index of the left child of the element at index i. * Note that this index can be greater than the heap size, in which case * there is no left child. */ @inline(__always) func leftChildIndex(ofIndex i: Int) -> Int { return 2*i + 1 } /** * Returns the index of the right child of the element at index i. * Note that this index can be greater than the heap size, in which case * there is no right child. */ @inline(__always) func rightChildIndex(ofIndex i: Int) -> Int { return 2*i + 2 } /** * Returns the maximum value in the heap (for a max-heap) or the minimum * value (for a min-heap). */ public func peek() -> T? { return elements.first } /** * Adds a new value to the heap. This reorders the heap so that the max-heap * or min-heap property still holds. Performance: O(log n). */ public mutating func insert(_ value: T) { elements.append(value) shiftUp(elements.count - 1) } public mutating func insert(_ sequence: S) where S.Iterator.Element == T { for value in sequence { insert(value) } } /** * Allows you to change an element. In a max-heap, the new element should be * larger than the old one; in a min-heap it should be smaller. */ public mutating func replace(index i: Int, value: T) { guard i < elements.count else { return } assert(isOrderedBefore(value, elements[i])) elements[i] = value shiftUp(i) } /** * Removes the root node from the heap. For a max-heap, this is the maximum * value; for a min-heap it is the minimum value. Performance: O(log n). */ @discardableResult public mutating func remove() -> T? { if elements.isEmpty { return nil } else if elements.count == 1 { return elements.removeLast() } else { // Use the last node to replace the first one, then fix the heap by // shifting this new first node into its proper position. let value = elements[0] elements[0] = elements.removeLast() shiftDown() return value } } /** * Removes an arbitrary node from the heap. Performance: O(log n). You need * to know the node's index, which may actually take O(n) steps to find. */ public mutating func removeAt(_ index: Int) -> T? { guard index < elements.count else { return nil } let size = elements.count - 1 if index != size { elements.swapAt(index,size) shiftDown(index, heapSize: size) shiftUp(index) } return elements.removeLast() } /** * Takes a child node and looks at its parents; if a parent is not larger * (max-heap) or not smaller (min-heap) than the child, we exchange them. */ mutating func shiftUp(_ index: Int) { var childIndex = index let child = elements[childIndex] var parentIndex = self.parentIndex(ofIndex: childIndex) while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { elements[childIndex] = elements[parentIndex] childIndex = parentIndex parentIndex = self.parentIndex(ofIndex: childIndex) } elements[childIndex] = child } mutating func shiftDown() { shiftDown(0, heapSize: elements.count) } /** * Looks at a parent node and makes sure it is still larger (max-heap) or * smaller (min-heap) than its childeren. */ mutating func shiftDown(_ index: Int, heapSize: Int) { var parentIndex = index while true { let leftChildIndex = self.leftChildIndex(ofIndex: parentIndex) let rightChildIndex = leftChildIndex + 1 // Figure out which comes first if we order them by the sort function: // the parent, the left child, or the right child. If the parent comes // first, we're done. If not, that element is out-of-place and we make // it "float down" the tree until the heap property is restored. var first = parentIndex if leftChildIndex < heapSize && isOrderedBefore(elements[leftChildIndex], elements[first]) { first = leftChildIndex } if rightChildIndex < heapSize && isOrderedBefore(elements[rightChildIndex], elements[first]) { first = rightChildIndex } if first == parentIndex { return } elements.swapAt(parentIndex,first) parentIndex = first } } } // MARK: - Searching extension Heap where T: Equatable { /** * Searches the heap for the given element. Performance: O(n). */ public func index(of element: T) -> Int? { return index(of: element, 0) } fileprivate func index(of element: T, _ i: Int) -> Int? { if i >= count { return nil } if isOrderedBefore(element, elements[i]) { return nil } if element == elements[i] { return i } if let j = index(of: element, self.leftChildIndex(ofIndex: i)) { return j } if let j = index(of: element, self.rightChildIndex(ofIndex: i)) { return j } return nil } } ================================================ FILE: Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift ================================================ /* Priority Queue, a queue where the most "important" items are at the front of the queue. The heap is a natural data structure for a priority queue, so this object simply wraps the Heap struct. All operations are O(lg n). Just like a heap can be a max-heap or min-heap, the queue can be a max-priority queue (largest element first) or a min-priority queue (smallest element first). */ public struct PriorityQueue { fileprivate var heap: Heap /* To create a max-priority queue, supply a > sort function. For a min-priority queue, use <. */ public init(sort: @escaping (T, T) -> Bool) { heap = Heap(sort: sort) } public var isEmpty: Bool { return heap.isEmpty } public var count: Int { return heap.count } public func peek() -> T? { return heap.peek() } public mutating func enqueue(_ element: T) { heap.insert(element) } public mutating func dequeue() -> T? { return heap.remove() } /* Allows you to change the priority of an element. In a max-priority queue, the new priority should be larger than the old one; in a min-priority queue it should be smaller. */ public mutating func changePriority(index i: Int, value: T) { return heap.replace(index: i, value: value) } } extension PriorityQueue where T: Equatable { public func index(of element: T) -> Int? { return heap.index(of: element) } } ================================================ FILE: Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift ================================================ /* Union-Find Data Structure Performance: adding new set is almost O(1) finding set of element is almost O(1) union sets is almost O(1) */ public struct UnionFind { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() public init() {} public mutating func addSetWith(_ element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } private mutating func setByIndex(_ index: Int) -> Int { if parent[index] == index { return index } else { parent[index] = setByIndex(parent[index]) return parent[index] } } public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { return nil } } public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { if firstSet != secondSet { if size[firstSet] < size[secondSet] { parent[firstSet] = secondSet size[secondSet] += size[firstSet] } else { parent[secondSet] = firstSet size[firstSet] += size[secondSet] } } } } public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false } } } ================================================ FILE: Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground ================================================ ================================================ FILE: Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Minimum Spanning Tree/Prim.swift ================================================ // // Prim.swift // // // Created by xiang xin on 16/3/17. // // func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) { var cost: Int = 0 var tree = Graph() guard let start = graph.vertices.first else { return (cost: cost, tree: tree) } var visited = Set() var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>( sort: { $0.weight < $1.weight }) priorityQueue.enqueue((vertex: start, weight: 0, parent: nil)) while let head = priorityQueue.dequeue() { let vertex = head.vertex if visited.contains(vertex) { continue } visited.insert(vertex) cost += head.weight if let prev = head.parent { tree.addEdge(vertex1: prev, vertex2: vertex, weight: head.weight) } if let neighbours = graph.adjList[vertex] { for neighbour in neighbours { let nextVertex = neighbour.vertex if !visited.contains(nextVertex) { priorityQueue.enqueue((vertex: nextVertex, weight: neighbour.weight, parent: vertex)) } } } } return (cost: cost, tree: tree) } ================================================ FILE: Minimum Spanning Tree/README.markdown ================================================ # Minimum Spanning Tree (Weighted Graph) > This topic has been tutorialized [here](https://www.raywenderlich.com/169392/swift-algorithm-club-minimum-spanning-tree-with-prims-algorithm) A [minimum spanning tree](https://en.wikipedia.org/wiki/Minimum_spanning_tree) (MST) of a connected undirected weighted graph has a subset of the edges from the original graph that connects all the vertices together, without any cycles and with the minimum possible total edge weight. There can be more than one MSTs of a graph. There are two popular algorithms to calculate MST of a graph - [Kruskal's algorithm](https://en.wikipedia.org/wiki/Kruskal's_algorithm) and [Prim's algorithm](https://en.wikipedia.org/wiki/Prim's_algorithm). Both algorithms have a total time complexity of `O(ElogE)` where `E` is the number of edges from the original graph. ### Kruskal's Algorithm Sort the edges base on weight. Greedily select the smallest one each time and add into the MST as long as it doesn't form a cycle. Kruskal's algoritm uses [Union Find](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Union-Find) data structure to check whether any additional edge causes a cycle. The logic is to put all connected vertices into the same set (in Union Find's concept). If the two vertices from a new edge do not belong to the same set, then it's safe to add that edge into the MST. The following graph demonstrates the steps: ![Graph](Images/kruskal.png) Preparation ```swift // Initialize the values to be returned and Union Find data structure. var cost: Int = 0 var tree = Graph() var unionFind = UnionFind() for vertex in graph.vertices { // Initially all vertices are disconnected. // Each of them belongs to it's individual set. unionFind.addSetWith(vertex) } ``` Sort the edges ```swift let sortedEdgeListByWeight = graph.edgeList.sorted(by: { $0.weight < $1.weight }) ``` Take one edge at a time and try to insert it into the MST. ```swift for edge in sortedEdgeListByWeight { let v1 = edge.vertex1 let v2 = edge.vertex2 // Same set means the two vertices of this edge were already connected in the MST. // Adding this one will cause a cycle. if !unionFind.inSameSet(v1, and: v2) { // Add the edge into the MST and update the final cost. cost += edge.weight tree.addEdge(edge) // Put the two vertices into the same set. unionFind.unionSetsContaining(v1, and: v2) } } ``` ### Prim's Algorithm Prim's algorithm doesn't pre-sort all edges. Instead, it uses a [Priority Queue](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Priority%20Queue) to maintain a running sorted next-possile vertices. Starting from one vertex, loop through all unvisited neighbours and enqueue a pair of values for each neighbour - the vertex and the weight of edge connecting current vertex to the neighbour. Each time it greedily select the top of the priority queue (the one with least weight value) and add the edge into the final MST if the enqueued neighbour hasn't been already visited. The following graph demonstrates the steps: ![Graph](Images/prim.png) Preparation ```swift // Initialize the values to be returned and Priority Queue data structure. var cost: Int = 0 var tree = Graph() var visited = Set() // In addition to the (neighbour vertex, weight) pair, parent is added for the purpose of printing out the MST later. // parent is basically current vertex. aka. the previous vertex before neigbour vertex gets visited. var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>(sort: { $0.weight < $1.weight }) ``` Start from any vertex ```swift priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil)) ``` ```swift // Take from the top of the priority queue ensures getting the least weight edge. while let head = priorityQueue.dequeue() { let vertex = head.vertex if visited.contains(vertex) { continue } // If the vertex hasn't been visited before, its edge (parent-vertex) is selected for MST. visited.insert(vertex) cost += head.weight if let prev = head.parent { // The first vertex doesn't have a parent. tree.addEdge(vertex1: prev, vertex2: vertex, weight: head.weight) } // Add all unvisted neighbours into the priority queue. if let neighbours = graph.adjList[vertex] { for neighbour in neighbours { let nextVertex = neighbour.vertex if !visited.contains(nextVertex) { priorityQueue.enqueue((vertex: nextVertex, weight: neighbour.weight, parent: vertex)) } } } } ``` ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift ================================================ func breadthFirstSearchMinimumSpanningTree(_ graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() var queue = Queue() let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label) queue.enqueue(sourceInMinimumSpanningTree) sourceInMinimumSpanningTree.visited = true while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { neighborNode.visited = true queue.enqueue(neighborNode) } else { current.remove(edge) } } } return minimumSpanningTree } /*: ![Graph](Minimum_Spanning_Tree.png) */ let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") let nodeC = graph.addNode("c") let nodeD = graph.addNode("d") let nodeE = graph.addNode("e") let nodeF = graph.addNode("f") let nodeG = graph.addNode("g") let nodeH = graph.addNode("h") let nodeI = graph.addNode("i") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeH) graph.addEdge(nodeB, neighbor: nodeA) graph.addEdge(nodeB, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeH) graph.addEdge(nodeC, neighbor: nodeB) graph.addEdge(nodeC, neighbor: nodeD) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeI) graph.addEdge(nodeD, neighbor: nodeC) graph.addEdge(nodeD, neighbor: nodeE) graph.addEdge(nodeD, neighbor: nodeF) graph.addEdge(nodeE, neighbor: nodeD) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeC) graph.addEdge(nodeF, neighbor: nodeD) graph.addEdge(nodeF, neighbor: nodeE) graph.addEdge(nodeF, neighbor: nodeG) graph.addEdge(nodeG, neighbor: nodeF) graph.addEdge(nodeG, neighbor: nodeH) graph.addEdge(nodeG, neighbor: nodeI) graph.addEdge(nodeH, neighbor: nodeA) graph.addEdge(nodeH, neighbor: nodeB) graph.addEdge(nodeH, neighbor: nodeG) graph.addEdge(nodeH, neighbor: nodeI) graph.addEdge(nodeI, neighbor: nodeC) graph.addEdge(nodeI, neighbor: nodeG) graph.addEdge(nodeI, neighbor: nodeH) let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graph, source: nodeA) print(minimumSpanningTree) ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Edge.swift ================================================ public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor } } public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift ================================================ public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { self.nodes = [] } public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } public var description: String { var description = "" for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { let duplicated = Graph() for node in nodes { _ = duplicated.addNode(node.label) } for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(node.label) let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } return duplicated } } public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift ================================================ public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String public var distance: Int? public var visited: Bool public init(label: String) { self.label = label neighbors = [] visited = false } public var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } public var hasDistance: Bool { return distance != nil } public func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift ================================================ public struct Queue { private var array: [T] public init() { array = [] } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public func peek() -> T? { return array.first } } ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/contents.xcplayground ================================================ ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift ================================================ func breadthFirstSearchMinimumSpanningTree(_ graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() var queue = Queue() let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label) queue.enqueue(sourceInMinimumSpanningTree) sourceInMinimumSpanningTree.visited = true while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { neighborNode.visited = true queue.enqueue(neighborNode) } else { current.remove(edge) } } } return minimumSpanningTree } ================================================ FILE: Minimum Spanning Tree (Unweighted)/README.markdown ================================================ # Minimum Spanning Tree (Unweighted Graph) A minimum spanning tree describes a path that contains the smallest number of edges that are needed to visit every node in the graph. Take a look at the following graph: ![Graph](Images/Graph.png) If we start from node `a` and want to visit every other node, then what is the most efficient path to do that? We can calculate this with the minimum spanning tree algorithm. Here is the minimum spanning tree for the graph. It is represented by the bold edges: ![Minimum spanning tree](Images/MinimumSpanningTree.png) Drawn as a more conventional tree it looks like this: ![An actual tree](Images/Tree.png) To calculate the minimum spanning tree on an unweighted graph, we can use the [breadth-first search](../Breadth-First%20Search/) algorithm. Breadth-first search starts at a source node and traverses the graph by exploring the immediate neighbor nodes first, before moving to the next level neighbors. If we tweak this algorithm by selectively removing edges, then it can convert the graph into the minimum spanning tree. Let's step through the example. We start with the source node `a`, add it to a queue and mark it as visited. ```swift queue.enqueue(a) a.visited = true ``` The queue is now `[ a ]`. As is usual with breadth-first search, we dequeue the node at the front of the queue, `a`, and enqueue its immediate neighbor nodes `b` and `h`. We mark them as visited too. ```swift queue.dequeue() // a queue.enqueue(b) b.visited = true queue.enqueue(h) h.visited = true ``` The queue is now `[ b, h ]`. Dequeue `b` and enqueue the neighbor node `c`. Mark it as visited. Remove the edge from `b` to `h` because `h` has already been visited. ```swift queue.dequeue() // b queue.enqueue(c) c.visited = true b.removeEdgeTo(h) ``` The queue is now `[ h, c ]`. Dequeue `h` and enqueue the neighbor nodes `g` and `i`, and mark them as visited. ```swift queue.dequeue() // h queue.enqueue(g) g.visited = true queue.enqueue(i) i.visited = true ``` The queue is now `[ c, g, i ]`. Dequeue `c` and enqueue the neighbor nodes `d` and `f`, and mark them as visited. Remove the edge between `c` and `i` because `i` has already been visited. ```swift queue.dequeue() // c queue.enqueue(d) d.visited = true queue.enqueue(f) f.visited = true c.removeEdgeTo(i) ``` The queue is now `[ g, i, d, f ]`. Dequeue `g`. All of its neighbors have been discovered already, so there is nothing to enqueue. Remove the edges from `g` to `f`, as well as `g` to `i`, because `f` and `i` have already been discovered. ```swift queue.dequeue() // g g.removeEdgeTo(f) g.removeEdgeTo(i) ``` The queue is now `[ i, d, f ]`. Dequeue `i`. Nothing else to do for this node. ```swift queue.dequeue() // i ``` The queue is now `[ d, f ]`. Dequeue `d` and enqueue the neighbor node `e`. Mark it as visited. Remove the edge from `d` to `f` because `f` has already been visited. ```swift queue.dequeue() // d queue.enqueue(e) e.visited = true d.removeEdgeTo(f) ``` The queue is now `[ f, e ]`. Dequeue `f`. Remove the edge between `f` and `e` because `e` has already been visited. ```swift queue.dequeue() // f f.removeEdgeTo(e) ``` The queue is now `[ e ]`. Dequeue `e`. ```swift queue.dequeue() // e ``` The queue is empty, which means the minimum spanning tree has been computed. Here's the code: ```swift func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() var queue = Queue() let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label) queue.enqueue(sourceInMinimumSpanningTree) sourceInMinimumSpanningTree.visited = true while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.visited { neighborNode.visited = true queue.enqueue(neighborNode) } else { current.remove(edge) } } } return minimumSpanningTree } ``` This function returns a new `Graph` object that describes just the minimum spanning tree. In the figure, that would be the graph containing just the bold edges. Put this code in a playground and test it like so: ```swift let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") let nodeC = graph.addNode("c") let nodeD = graph.addNode("d") let nodeE = graph.addNode("e") let nodeF = graph.addNode("f") let nodeG = graph.addNode("g") let nodeH = graph.addNode("h") let nodeI = graph.addNode("i") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeH) graph.addEdge(nodeB, neighbor: nodeA) graph.addEdge(nodeB, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeH) graph.addEdge(nodeC, neighbor: nodeB) graph.addEdge(nodeC, neighbor: nodeD) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeI) graph.addEdge(nodeD, neighbor: nodeC) graph.addEdge(nodeD, neighbor: nodeE) graph.addEdge(nodeD, neighbor: nodeF) graph.addEdge(nodeE, neighbor: nodeD) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeC) graph.addEdge(nodeF, neighbor: nodeD) graph.addEdge(nodeF, neighbor: nodeE) graph.addEdge(nodeF, neighbor: nodeG) graph.addEdge(nodeG, neighbor: nodeF) graph.addEdge(nodeG, neighbor: nodeH) graph.addEdge(nodeG, neighbor: nodeI) graph.addEdge(nodeH, neighbor: nodeA) graph.addEdge(nodeH, neighbor: nodeB) graph.addEdge(nodeH, neighbor: nodeG) graph.addEdge(nodeH, neighbor: nodeI) graph.addEdge(nodeI, neighbor: nodeC) graph.addEdge(nodeI, neighbor: nodeG) graph.addEdge(nodeI, neighbor: nodeH) let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graph, source: nodeA) print(minimumSpanningTree) // [node: a edges: ["b", "h"]] // [node: b edges: ["c"]] // [node: c edges: ["d", "f"]] // [node: d edges: ["e"]] // [node: h edges: ["g", "i"]] ``` > **Note:** On an unweighed graph, any spanning tree is always a minimal spanning tree. This means you can also use a [depth-first search](../Depth-First%20Search) to find the minimum spanning tree. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* ================================================ FILE: Minimum Spanning Tree (Unweighted)/Tests/Graph.swift ================================================ // MARK: - Edge public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor } } public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } // MARK: - Node public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String public var distance: Int? public var visited: Bool public init(label: String) { self.label = label neighbors = [] visited = false } public var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } public var hasDistance: Bool { return distance != nil } public func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { self.nodes = [] } public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } public var description: String { var description = "" for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { let duplicated = Graph() for node in nodes { _ = duplicated.addNode(node.label) } for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(node.label) let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } return duplicated } } public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } ================================================ FILE: Minimum Spanning Tree (Unweighted)/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Minimum Spanning Tree (Unweighted)/Tests/MinimumSpanningTreeTests.swift ================================================ import XCTest class MinimumSpanningTreeTests: XCTestCase { func testMinimumSpanningTreeReturnsSameTreeWhenGivenTree() { let tree = Graph() let nodeA = tree.addNode("a") let nodeB = tree.addNode("b") let nodeC = tree.addNode("c") let nodeD = tree.addNode("d") let nodeE = tree.addNode("e") let nodeF = tree.addNode("f") let nodeG = tree.addNode("g") let nodeH = tree.addNode("h") tree.addEdge(nodeA, neighbor: nodeB) tree.addEdge(nodeA, neighbor: nodeC) tree.addEdge(nodeB, neighbor: nodeD) tree.addEdge(nodeB, neighbor: nodeE) tree.addEdge(nodeC, neighbor: nodeF) tree.addEdge(nodeC, neighbor: nodeG) tree.addEdge(nodeE, neighbor: nodeH) let minimumSpanningTree = breadthFirstSearchMinimumSpanningTree(tree, source: nodeA) XCTAssertEqual(minimumSpanningTree, tree) } func testMinimumSpanningTreeReturnsMinimumSpanningTreeWhenGivenGraph() { let graphAndSourceNode = createGraph() let expectedMinimumSpanningTree = createMinimumSpanningTree() let actualMinimumSpanningTree = breadthFirstSearchMinimumSpanningTree(graphAndSourceNode.graph, source: graphAndSourceNode.source) XCTAssertEqual(actualMinimumSpanningTree, expectedMinimumSpanningTree) } func createGraph() -> (graph: Graph, source: Node) { let graph = Graph() let nodeA = graph.addNode("a") let nodeB = graph.addNode("b") let nodeC = graph.addNode("c") let nodeD = graph.addNode("d") let nodeE = graph.addNode("e") let nodeF = graph.addNode("f") let nodeG = graph.addNode("g") let nodeH = graph.addNode("h") let nodeI = graph.addNode("i") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeH) graph.addEdge(nodeB, neighbor: nodeA) graph.addEdge(nodeB, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeH) graph.addEdge(nodeC, neighbor: nodeB) graph.addEdge(nodeC, neighbor: nodeD) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeI) graph.addEdge(nodeD, neighbor: nodeC) graph.addEdge(nodeD, neighbor: nodeE) graph.addEdge(nodeD, neighbor: nodeF) graph.addEdge(nodeE, neighbor: nodeD) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeC) graph.addEdge(nodeF, neighbor: nodeD) graph.addEdge(nodeF, neighbor: nodeE) graph.addEdge(nodeF, neighbor: nodeG) graph.addEdge(nodeG, neighbor: nodeF) graph.addEdge(nodeG, neighbor: nodeH) graph.addEdge(nodeG, neighbor: nodeI) graph.addEdge(nodeH, neighbor: nodeA) graph.addEdge(nodeH, neighbor: nodeB) graph.addEdge(nodeH, neighbor: nodeG) graph.addEdge(nodeH, neighbor: nodeI) graph.addEdge(nodeI, neighbor: nodeC) graph.addEdge(nodeI, neighbor: nodeG) graph.addEdge(nodeI, neighbor: nodeH) return (graph, nodeA) } func createMinimumSpanningTree() -> Graph { let minimumSpanningTree = Graph() let nodeA = minimumSpanningTree.addNode("a") let nodeB = minimumSpanningTree.addNode("b") let nodeC = minimumSpanningTree.addNode("c") let nodeD = minimumSpanningTree.addNode("d") let nodeE = minimumSpanningTree.addNode("e") let nodeF = minimumSpanningTree.addNode("f") let nodeG = minimumSpanningTree.addNode("g") let nodeH = minimumSpanningTree.addNode("h") let nodeI = minimumSpanningTree.addNode("i") minimumSpanningTree.addEdge(nodeA, neighbor: nodeB) minimumSpanningTree.addEdge(nodeA, neighbor: nodeH) minimumSpanningTree.addEdge(nodeB, neighbor: nodeC) minimumSpanningTree.addEdge(nodeH, neighbor: nodeG) minimumSpanningTree.addEdge(nodeH, neighbor: nodeI) minimumSpanningTree.addEdge(nodeC, neighbor: nodeD) minimumSpanningTree.addEdge(nodeC, neighbor: nodeF) minimumSpanningTree.addEdge(nodeD, neighbor: nodeE) return minimumSpanningTree } } ================================================ FILE: Minimum Spanning Tree (Unweighted)/Tests/Queue.swift ================================================ public struct Queue { private var array: [T] public init() { array = [] } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public func peek() -> T? { return array.first } } ================================================ FILE: Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 83AACB421C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB411C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift */; }; 83F9C9691C84437C00B3A87F /* MinimumSpanningTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9661C84437C00B3A87F /* MinimumSpanningTree.swift */; }; 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9701C84449D00B3A87F /* Queue.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 83AACB411C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimumSpanningTreeTests.swift; sourceTree = SOURCE_ROOT; }; 83F9C9661C84437C00B3A87F /* MinimumSpanningTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MinimumSpanningTree.swift; path = ../MinimumSpanningTree.swift; sourceTree = SOURCE_ROOT; }; 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = SOURCE_ROOT; }; 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 83F9C9661C84437C00B3A87F /* MinimumSpanningTree.swift */, 83AACB411C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift */, 83F9C96E1C84449D00B3A87F /* Graph.swift */, 83F9C9701C84449D00B3A87F /* Queue.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 83AACB421C844CED00DDAFC7 /* MinimumSpanningTreeTests.swift in Sources */, 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, 83F9C9691C84437C00B3A87F /* MinimumSpanningTree.swift in Sources */, 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: MinimumCoinChange/LICENSE ================================================ MIT License Copyright (c) 2017 Jacopo Mangiavacchi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MinimumCoinChange/Package.swift ================================================ // swift-tools-version:3.1 import PackageDescription let package = Package( name: "MinimumCoinChange" ) ================================================ FILE: MinimumCoinChange/README.md ================================================ # Minimum Coin Change Minimum Coin Change problem algorithm implemented in Swift comparing dynamic programming algorithm design to traditional greedy approach. Written for Swift Algorithm Club by Jacopo Mangiavacchi ![Coins](eurocoins.gif) # Introduction In the traditional coin change problem you have to find all the different ways to change some given money in a particular amount of coins using a given amount of set of coins (i.e. 1 cent, 2 cents, 5 cents, 10 cents etc.). For example using Euro cents the total of 4 cents value of money can be changed in these possible ways: - Four 1 cent coins - Two 2 cent coins - One 2 cent coin and two 1 cent coins The minimum coin change problem is a variation of the generic coin change problem where you need to find the best option for changing the money returning the less number of coins. For example using Euro cents the best possible change for 4 cents are two 2 cent coins with a total of two coins. # Greedy Solution A simple approach for implementing the Minimum Coin Change algorithm in a very efficient way is to start subtracting from the input value the greater possible coin value from the given amount of set of coins available and iterate subtracting the next greater possible coin value on the resulting difference. For example from the total of 4 Euro cents of the example above you can subtract initially 2 cents as the other biggest coins value (from 5 cents to above) are to bigger for the current 4 Euro cent value. Once used the first 2 cents coin you iterate again with the same logic for the rest of 2 cents and select another 2 cents coin and finally return the two 2 cents coins as the best change. Most of the time the result for this greedy approach is optimal but for some set of coins the result will not be the optimal. Indeed, if we use the a set of these three different coins set with values 1, 3 and 4 and execute this greedy algorithm for asking the best change for the value 6 we will get one coin of 4 and two coins of 1 instead of two coins of 3. # Dynamic Programming Solution A classic dynamic programming strategy will iterate selecting in order a possible coin from the given amount of set of coins and finding using recursive calls the minimum coin change on the difference from the passed value and the selected coin. For any interaction the algorithm select from all possible combinations the one with the less number of coins used. The dynamic programming approach will always select the optimal change but it will require a number of steps that is at least quadratic in the goal amount to change. In this Swift implementation in order to optimize the overall performance we use an internal data structure for caching the result for best minimum coin change for previous values. ================================================ FILE: MinimumCoinChange/Sources/MinimumCoinChange.swift ================================================ // // Minimum Coin Change Problem Playground // Compare Greedy Algorithm and Dynamic Programming Algorithm in Swift // // Created by Jacopo Mangiavacchi on 04/03/17. // import Foundation public enum MinimumCoinChangeError: Error { case noRestPossibleForTheGivenValue } public struct MinimumCoinChange { internal let sortedCoinSet: [Int] public init(coinSet: [Int]) { self.sortedCoinSet = coinSet.sorted(by: { $0 > $1}) } //Greedy Algorithm public func changeGreedy(_ value: Int) throws -> [Int] { guard value > 0 else { return [] } var change: [Int] = [] var newValue = value for coin in sortedCoinSet { while newValue - coin >= 0 { change.append(coin) newValue -= coin } if newValue == 0 { break } } if newValue > 0 { throw MinimumCoinChangeError.noRestPossibleForTheGivenValue } return change } //Dynamic Programming Algorithm public func changeDynamic(_ value: Int) throws -> [Int] { guard value > 0 else { return [] } var cache: [Int : [Int]] = [:] func _changeDynamic(_ value: Int) -> [Int] { guard value > 0 else { return [] } if let cached = cache[value] { return cached } var potentialChangeArray: [[Int]] = [] for coin in sortedCoinSet { if value - coin >= 0 { var potentialChange: [Int] = [coin] potentialChange.append(contentsOf: _changeDynamic(value - coin)) if potentialChange.reduce(0, +) == value { potentialChangeArray.append(potentialChange) } } } if potentialChangeArray.count > 0 { let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) cache[value] = sortedPotentialChangeArray[0] return sortedPotentialChangeArray[0] } return [] } let change: [Int] = _changeDynamic(value) if change.reduce(0, +) != value { throw MinimumCoinChangeError.noRestPossibleForTheGivenValue } return change } } ================================================ FILE: MinimumCoinChange/Tests/LinuxMain.swift ================================================ import XCTest @testable import MinimumCoinChangeTests XCTMain([ testCase(MinimumCoinChangeTests.allTests), ]) ================================================ FILE: MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift ================================================ import XCTest @testable import MinimumCoinChange class MinimumCoinChangeTests: XCTestCase { func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testExample() { let mcc = MinimumCoinChange(coinSet: [1, 2, 5, 10, 20, 25]) print("Coin set: \(mcc.sortedCoinSet)") do { for i in 0..<100 { let greedy = try mcc.changeGreedy(i) let dynamic = try mcc.changeDynamic(i) XCTAssertEqual(greedy.reduce(0, +), dynamic.reduce(0, +), "Greedy and Dynamic return two different changes") if greedy.count != dynamic.count { print("\(i): greedy = \(greedy) dynamic = \(dynamic)") } } } catch { XCTFail("Test Failed: impossible to change with the given coin set") } } static var allTests = [ ("testExample", testExample), ] } ================================================ FILE: Monty Hall Problem/MontyHall.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation func random(_ n: Int) -> Int { return Int(arc4random_uniform(UInt32(n))) } let numberOfDoors = 3 var rounds = 0 var winOriginalChoice = 0 var winChangedMind = 0 func playRound() { // The door with the prize. let prizeDoor = random(numberOfDoors) // The door the player chooses. let chooseDoor = random(numberOfDoors) // The door that Monty opens. This must be empty and not the one the player chose. var openDoor = -1 repeat { openDoor = random(numberOfDoors) } while openDoor == prizeDoor || openDoor == chooseDoor // What happens when the player changes his mind and picks the other door. var changeMind = -1 repeat { changeMind = random(numberOfDoors) } while changeMind == openDoor || changeMind == chooseDoor // Figure out which choice was the winner. if chooseDoor == prizeDoor { winOriginalChoice += 1 } if changeMind == prizeDoor { winChangedMind += 1 } rounds += 1 } // Run the simulation a large number of times. for _ in 1...5000 { playRound() } let stubbornPct = Double(winOriginalChoice)/Double(rounds) let changedMindPct = Double(winChangedMind)/Double(rounds) print(String(format: "Played %d rounds, stubborn: %g%% vs changed mind: %g%%", rounds, stubbornPct, changedMindPct)) ================================================ FILE: Monty Hall Problem/MontyHall.playground/contents.xcplayground ================================================ ================================================ FILE: Monty Hall Problem/MontyHall.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Monty Hall Problem/README.markdown ================================================ # The Monty Hall Problem Congrats! You've reached the final round of the popular [Monty Hall game show](https://en.wikipedia.org/wiki/Let%27s_Make_a_Deal). Monty, the show host, gives you the choice between 3 doors. Behind one of the doors is a prize (a new car? a trip to Hawaii? a microwave oven?), the other two are empty. After you make your choice, Monty decides to make things a bit more interesting and opens one of the two doors that you didn't pick. Of course, the one he opens is empty. There are now two doors left, behind one of which is the coveted prize. Now Monty gives you the opportunity to change your mind. Should you stick with your original choice, should you pick the other door, or doesn't it matter? You'd think that changing your answer wouldn't improve your chances... but it does! This is a very nonintuitive result. Maybe you have trouble believing this is true. Don't worry, when this problem was first proposed many professional mathematicians didn't believe it either, so you're in good company. There's a simple way to verify this claim: we can write a program to test it out! We should be able to show who wins more often by playing the game a large number of times. Here's the code (see the [playground](MontyHall.playground/Contents.swift) for the full thing). First, we randomly choose the door that has the prize: ```swift let prizeDoor = random(3) ``` We also randomly pick the choice of the player: ```swift let chooseDoor = random(3) ``` Next, Monty opens one of the empty doors. Obviously, he won't choose the door that the player chose or the one with the prize. ```swift var openDoor = -1 repeat { openDoor = random(3) } while openDoor == prizeDoor || openDoor == chooseDoor ``` There are only two closed doors left, one of which has the prize. What happens when the player changes his mind and picks the other door? ```swift var changeMind = -1 repeat { changeMind = random(3) } while changeMind == openDoor || changeMind == chooseDoor ``` Now we see which choice was the right one: ```swift if chooseDoor == prizeDoor { winOriginalChoice += 1 } if changeMind == prizeDoor { winChangedMind += 1 } ``` If the prize is behind the player's original door choice, we increment `winOriginalChoice`. If the prize is behind the other door, then the player would have won if he changed his mind, and so we increment `winChangedMind`. And that's all there is to it. If you run the above code 1000 times or so, you'll find that the probability of choosing the prize without changing your mind is about 33%. But if you *do* change your mind, the probability of winning is 67% -- that is twice as large! Try it out in the playground if you still don't believe it. ;-) Here's why: When you first make a choice, your chances of picking the prize are 1 out of 3, or 33% After Monty opens one of the doors, this gives you new information. However, it doesn't change the probability of your original choice being the winner. That chance remains 33% because you made that choice when you didn't know yet what was behind this open door. Since probabilities always need to add up to 100%, the chance that the prize is behind the other door is now 100 - 33 = 67%. So, as strange as it may sound, you're better off switching doors! This is hard to wrap your head around, but easily shown using a simulation that runs a significant number of times. Probability is weird. By the way, you can simplify the code to this: ```swift let prizeDoor = random(3) let chooseDoor = random(3) if chooseDoor == prizeDoor { winOriginalChoice += 1 } else { winChangedMind += 1 } ``` Now it's no longer a simulation but the logic is equivalent. You can clearly see that the `chooseDoor` only wins 1/3rd of the time -- because it's a random number between 1 and 3 -- so changing your mind must win the other 2/3rds of the time. [Monty Hall Problem on Wikipedia](https://en.wikipedia.org/wiki/Monty_Hall_problem) *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Multiset/Multiset.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Cocoa var set = Multiset() set.add("Foo") set.add("Foo") set.add("Bar") set.add("Baz") set.count set.count(for: "Foo") set.allItems var set2 = Multiset() set2.add("Foo") set2.add("Foo") set2.isSubSet(of: set) // true set.isSubSet(of: set2) // false // Convenience constructor: pass a Collection of Hashables to the constructor var cacti = Multiset("cacti") cacti.allItems var tactical = Multiset("tactical") cacti.isSubSet(of: tactical) // true tactical.isSubSet(of: cacti) // false // Test ExpressibleByArrayLiteral protocol let set3: Multiset = ["foo", "bar"] set3.count(for: "foo") // Test Equatable protocol let set4 = Multiset(set3.allItems) set4 == set3 // true set4 == set // false ================================================ FILE: Multiset/Multiset.playground/Sources/Multiset.swift ================================================ // // Multiset.swift // Multiset // // Created by Simon Whitaker on 28/08/2017. // import Foundation public struct Multiset { private var storage: [T: UInt] = [:] public private(set) var count: UInt = 0 public init() {} public init(_ collection: C) where C.Element == T { for element in collection { self.add(element) } } public mutating func add (_ elem: T) { storage[elem, default: 0] += 1 count += 1 } public mutating func remove (_ elem: T) { if let currentCount = storage[elem] { if currentCount > 1 { storage[elem] = currentCount - 1 } else { storage.removeValue(forKey: elem) } count -= 1 } } public func isSubSet (of superset: Multiset) -> Bool { for (key, count) in storage { let supersetcount = superset.storage[key] ?? 0 if count > supersetcount { return false } } return true } public func count(for key: T) -> UInt { return storage[key] ?? 0 } public var allItems: [T] { var result = [T]() for (key, count) in storage { for _ in 0 ..< count { result.append(key) } } return result } } // MARK: - Equatable extension Multiset: Equatable { public static func == (lhs: Multiset, rhs: Multiset) -> Bool { if lhs.storage.count != rhs.storage.count { return false } for (lkey, lcount) in lhs.storage { let rcount = rhs.storage[lkey] ?? 0 if lcount != rcount { return false } } return true } } // MARK: - ExpressibleByArrayLiteral extension Multiset: ExpressibleByArrayLiteral { public init(arrayLiteral elements: T...) { self.init(elements) } } ================================================ FILE: Multiset/Multiset.playground/contents.xcplayground ================================================ ================================================ FILE: Multiset/README.markdown ================================================ # Multiset A multiset (also known as a bag) is a data structure similar to a regular set, but it can store multiple instances of the same element. For example, if I added the elements 1, 2, 2 to a regular set, the set would only contain two items, since adding 2 a second time has no effect. ``` var set = Set() set.add(1) // set is now [1] set.add(2) // set is now [1, 2] set.add(2) // set is still [1, 2] ``` By comparison, after adding the elements 1, 2, 2 to a multiset, it would contain three items. ``` var set = Multiset() set.add(1) // set is now [1] set.add(2) // set is now [1, 2] set.add(2) // set is now [1, 2, 2] ``` You might be thinking that this looks an awful lot like an array. So why would you use a multiset? Let's consider the differences between the two… - Ordering: arrays maintain the order of items added to them, multisets do not - Testing for membership: testing whether an element is a member of the collection is O(N) for arrays, O(1) for multisets. - Testing for subset: testing whether collection X is a subset of collection Y is a simple operation for a multiset, but complex for arrays Typical operations on a multiset are: - Add an element - Remove an element - Get the count for an element (the number of times it's been added) - Get the count for the whole set (the number of items that have been added) - Check whether it is a subset of another multiset One real-world use of multisets is to determine whether one string is a partial anagram of another. For example, the word "cacti" is a partial anagrams of "tactical". (In other words, I can rearrange the letters of "tactical" to make "cacti", with some letters left over.) ``` swift var cacti = Multiset("cacti") var tactical = Multiset("tactical") cacti.isSubSet(of: tactical) // true! ``` ## Implementation Under the hood, this implementation of Multiset uses a dictionary to store a mapping of elements to the number of times they've been added. Here's the essence of it: ``` swift public struct Multiset { private var storage: [Element: UInt] = [:] public init() {} ``` And here's how you'd use this class to create a multiset of strings: ``` swift var set = Multiset() ``` Adding an element is a case of incrementing the counter for that element, or setting it to 1 if it doesn't already exist: ``` swift public mutating func add (_ elem: Element) { storage[elem, default: 0] += 1 } ``` Here's how you'd use this method to add to the set we created earlier: ```swift set.add("foo") set.add("foo") set.allItems // returns ["foo", "foo"] ``` Our set now contains two elements, both the string "foo". Removing an element works much the same way as adding; decrement the counter for the element, or remove it from the underlying dictionary if its value is 1 before removal. ``` swift public mutating func remove (_ elem: Element) { if let currentCount = storage[elem] { if currentCount > 1 { storage[elem] = currentCount - 1 } else { storage.removeValue(forKey: elem) } } } ``` Getting the count for an item is simple: we just return the value for the given item in the internal dictionary. ``` swift public func count(for key: Element) -> UInt { return storage[key] ?? 0 } ``` *Written for the Swift Algorithm Club by Simon Whitaker* ================================================ FILE: Myers Difference Algorithm/MyersDifferenceAlgorithm.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation let shortestEditDistance: ([String], [String]) -> Int = MyersDifferenceAlgorithm.calculateShortestEditDistance(from:to:) /*** All elements are same, so any scripts do not need. So, the edit distance is 0 ***/ shortestEditDistance(["1", "2", "3"], ["1", "2", "3"]) /*** Last element "3" should be inserted. So, the edit distance is 1 ***/ shortestEditDistance(["1", "2"], ["1", "2", "3"]) /*** First, remove "1", then insert "1" after "2". So, the edit distance is 2 ***/ shortestEditDistance(["1", "2", "3"], ["2", "1", "3"]) ================================================ FILE: Myers Difference Algorithm/MyersDifferenceAlgorithm.playground/Sources/MyersDifferenceAlgorithm.swift ================================================ // // MyersDifferenceAlgorithm.swift // // Created by Yuya Horita on 2018/02/27. // Copyright © 2018年 hy. All rights reserved. // import Foundation public struct MyersDifferenceAlgorithm { public static func calculateShortestEditDistance(from fromArray: Array, to toArray: Array) -> Int { let fromCount = fromArray.count let toCount = toArray.count let totalCount = toCount + fromCount var furthestReaching = Array(repeating: 0, count: 2 * totalCount + 1) let isReachedAtSink: (Int, Int) -> Bool = { x, y in return x == fromCount && y == toCount } let snake: (Int, Int, Int) -> Int = { x, D, k in var _x = x while _x < fromCount && _x - k < toCount && fromArray[_x] == toArray[_x - k] { _x += 1 } return _x } for D in 0...totalCount { for k in stride(from: -D, through: D, by: 2) { let index = k + totalCount // (x, D, k) => the x position on the k_line where the number of scripts is D // scripts means insertion or deletion var x = 0 if D == 0 { } // k == -D, D will be the boundary k_line // when k == -D, moving right on the Edit Graph(is delete script) from k - 1_line where D - 1 is unavailable. // when k == D, moving bottom on the Edit Graph(is insert script) from k + 1_line where D - 1 is unavailable. // furthestReaching x position has higher calculating priority. (x, D - 1, k - 1), (x, D - 1, k + 1) else if k == -D || k != D && furthestReaching[index - 1] < furthestReaching[index + 1] { // Getting initial x position // ,using the furthestReaching X position on the k + 1_line where D - 1 // ,meaning get (x, D, k) by (x, D - 1, k + 1) + moving bottom + snake // this moving bottom on the edit graph is compatible with insert script x = furthestReaching[index + 1] } else { // Getting initial x position // ,using the futrhest X position on the k - 1_line where D - 1 // ,meaning get (x, D, k) by (x, D - 1, k - 1) + moving right + snake // this moving right on the edit graph is compatible with delete script x = furthestReaching[index - 1] + 1 } // snake // diagonal moving can be performed with 0 cost. // `same` script is needed ? let _x = snake(x, D, k) if isReachedAtSink(_x, _x - k) { return D } furthestReaching[index] = _x } } fatalError("Never comes here") } } ================================================ FILE: Myers Difference Algorithm/MyersDifferenceAlgorithm.playground/contents.xcplayground ================================================ ================================================ FILE: Myers Difference Algorithm/MyersDifferenceAlgorithm.swift ================================================ // // MyersDifferenceAlgorithm.swift // // Created by Yuya Horita on 2018/02/27. // Copyright © 2018年 hy. All rights reserved. // import Foundation public struct MyersDifferenceAlgorithm { public static func calculateShortestEditDistance(from fromArray: Array, to toArray: Array) -> Int { let fromCount = fromArray.count let toCount = toArray.count let totalCount = toCount + fromCount var furthestReaching = Array(repeating: 0, count: 2 * totalCount + 1) let isReachedAtSink: (Int, Int) -> Bool = { x, y in return x == fromCount && y == toCount } let snake: (Int, Int, Int) -> Int = { x, D, k in var _x = x while _x < fromCount && _x - k < toCount && fromArray[_x] == toArray[_x - k] { _x += 1 } return _x } for D in 0...totalCount { for k in stride(from: -D, through: D, by: 2) { let index = k + totalCount // (x, D, k) => the x position on the k_line where the number of scripts is D // scripts means insertion or deletion var x = 0 if D == 0 { } // k == -D, D will be the boundary k_line // when k == -D, moving right on the Edit Graph(is delete script) from k - 1_line where D - 1 is unavailable. // when k == D, moving bottom on the Edit Graph(is insert script) from k + 1_line where D - 1 is unavailable. // furthestReaching x position has higher calculating priority. (x, D - 1, k - 1), (x, D - 1, k + 1) else if k == -D || k != D && furthestReaching[index - 1] < furthestReaching[index + 1] { // Getting initial x position // ,using the furthestReaching X position on the k + 1_line where D - 1 // ,meaning get (x, D, k) by (x, D - 1, k + 1) + moving bottom + snake // this moving bottom on the edit graph is compatible with insert script x = furthestReaching[index + 1] } else { // Getting initial x position // ,using the futrhest X position on the k - 1_line where D - 1 // ,meaning get (x, D, k) by (x, D - 1, k - 1) + moving right + snake // this moving right on the edit graph is compatible with delete script x = furthestReaching[index - 1] + 1 } // snake // diagonal moving can be performed with 0 cost. // `same` script is needed ? let _x = snake(x, D, k) if isReachedAtSink(_x, _x - k) { return D } furthestReaching[index] = _x } } fatalError("Never comes here") } } ================================================ FILE: Myers Difference Algorithm/README.md ================================================ # Myers Difference Algorithm Myers Difference Algorithm(MDA) is an algorithm that finds a longest common subsequence(LCS) or shortest edit scripts(SES) of two sequences. The common subsequence of two sequences is the sequence of elements that appear in the same order in both sequences. For example, let's assume you have two arrays: ``` let firstArray = [1, 2, 3] let secondArray = [2, 3, 4] ``` The common subsequences of these two arrays are `[2]`, and `[2, 3]`. The longest common sequence in this case is `[2, 3]`. MDA can accomplish this in O(ND) time, where N is the sum of the lengths of the two sequences. ## Finding the length of the Longest Common Subsequence with Myers Algorithm on Edit Graph ### Edit Graph MDA uses an **Edit Graph** to solve the LCS/SES problem. Below is a illustration depicting an edit graph: The x-axis at the top of the graph represents one of the sequences, `X`. The y-axis at the left side of the graph represents the other sequence, `Y`. Hence, the two sequences in question is the following: ``` X = [A, B, C, A, B, B, A] Y = [C, B, A, B, A, C] ``` MDA generates the edit graph through the following steps: 1. Line the element of sequence `X` on the x axis. And do for `Y` on the y axis. 2. Make grid and vertex at each point in the grid (x, y), `x in [0, N] and y in [0, M]`. `N` is the length of sequence `X`, `M` is of `Y` 3. Line for `x - y = k`, this line called k-line. Black dot line is this and pink number is the value of k. 3. Check the points `(i, j)`, where `X[i] = Y[j]`, called match point, light green one. 4. Connect vertex `(i - 1, j - 1)` and vertex `(i, j)`, where `(i, j)` is match point, then diagonal edge appears. Each elements on the figure shows that, - `Red number and dotted lines`: The red number is the value of k and dotted lines are k-line. - `Green dots: The match points`, which is the point `(i, j)` where `X[i] == Y[j]` - `Blue line`: The shortest path from source to sink, which is the path we are going to find finally. > **Note:** Here, the sequences' start index is 1 not 0, so `X[1] = A`, `Y[1] = C` We discuss about which path is the shortest from `source` to `sink`. Can move on the edges on the graph. I mean we can move on the grid, horizontal and vertical edges, and the diagonal edges. The movements are compatible with the `Edit Scripts`, insert or delete. The word `Edit Scripts` appeared here, as referred at Introduction, SES is Shortest Edit Scripts. Let's get back on track. On this edit graph, the horizontal movement to vertex `(i, j)` is compatible with the script `delete at index i from X`, the vertical movement to vertex `(i, j)` is compatible with the script `insert the element of Y at index j to immediately after the element of X at index i`. How about for the diagonal movement?. This movement to vertex `(i, j)` means `X[i] = Y[j]`, so no script needs. - horizontal movement -> delete - vertical movement -> insert - diagonal movement -> no script because both are same. Next, add cost 1 for non-diagonal movement, because they can be compatible with script. And 0 for diagonal movement, same means no script. The total cost for the minimum path, exploring from `source` to `sink`, is the same as the length of the Longest Common Subsequence or Shortest Edit Script. So, LCS/SES problem can be solved by finding the shortest path from `source` to `sink`. ### Myers Algorithm As mentioned above, the problem of finding a shortest edit script can be reduced to finding a path from `source (0, 0)` to `sink (N, M)` with the fewest number of horizontal and vertical edges. Let `D-path` be a path starting at `source` that has exactly `D` non-diagonal edges, or must move non-diagonally D-times. For example, A 0-path consists solely of diagonal edges. This means both sequences are completely same. By a simple induction, D-path must consist of a (D-1)-path followed by a non-diagonal edge and then diagonal edges, which called `snake`. The minimum value of D is 0, both sequences being same. To the contrary, the maximum value of D is N + M because delete all elements from X and insert all elements from Y to X is the worst case edit scripts. For getting D, or the length of SES, running loop from 0 to N + M is enough. ```swift for D in 0...N + M ``` Next, thinking about, where is the furthest reaching point for D-path on k-line. Like below, moving horizontally from k-line reaches (k+1)-line, moving vertically from k-line reaches (k-1)-line. Red chalky line shows that. So, threre are several end points of D-path, or D-path can end on several k-line. We need the information to get the next path ((D+1)-path) as mentioned above. In fact, D-path must end on k-line, where k in { -D, -D + 2, ....., D - 2, D }. This is so simple, starting point, `source` is `(0, 0)` on (k=0)-line. D is the number of non-diagonal edges and non-diagonal movement changes current k-line to (kpm1)-line. Because 0 is even number, if D is even number D-path will end on (even_k)-line, if D is odd number D-path will end on (odd_k)-line. Searching loop outline will be below. ```swift for D in 0...N + M { for k in stride(from: -D, through: D, by: 2) { //Find the end point of the furthest reaching D-path in k-line. if furthestReachingX == N && furthestReachingY == M { // The D-path is the shortest path // D is the length of Shortest Edit Script return } } } ``` The D-path on k-line can be decomposed into - a furthest reaching (D-1)-path on (k-1)-line, followed by a horizontal edge, followed by `snake`. - a furthest reaching (D-1)-path on (k+1)-line, followed by a vertical edge, followed by `snake`. as discussed above. The Myers Algorithm key point are these. - D-path must end on k-line, where k in { -D, -D + 2, ....., D - 2, D } - The D-path on k-line can be decomposed into two patterns thanks for these, the number of calculation become less. ```swift public struct MyersDifferenceAlgorithm { public static func calculateShortestEditDistance(from fromArray: Array, to toArray: Array) -> Int { let fromCount = fromArray.count let toCount = toArray.count let totalCount = toCount + fromCount var furthestReaching = Array(repeating: 0, count: 2 * totalCount + 1) let isReachedAtSink: (Int, Int) -> Bool = { x, y in return x == fromCount && y == toCount } let snake: (Int, Int, Int) -> Int = { x, D, k in var _x = x while _x < fromCount && _x - k < toCount && fromArray[_x] == toArray[_x - k] { _x += 1 } return _x } for D in 0...totalCount { for k in stride(from: -D, through: D, by: 2) { let index = k + totalCount // (x, D, k) => the x position on the k_line where the number of scripts is D // scripts means insertion or deletion var x = 0 if D == 0 { } // k == -D, D will be the boundary k_line // when k == -D, moving right on the Edit Graph(is delete script) from k - 1_line where D - 1 is unavailable. // when k == D, moving bottom on the Edit Graph(is insert script) from k + 1_line where D - 1 is unavailable. // furthestReaching x position has higher calculating priority. (x, D - 1, k - 1), (x, D - 1, k + 1) else if k == -D || k != D && furthestReaching[index - 1] < furthestReaching[index + 1] { // Getting initial x position // ,using the furthestReaching X position on the k + 1_line where D - 1 // ,meaning get (x, D, k) by (x, D - 1, k + 1) + moving bottom + snake // this moving bottom on the edit graph is compatible with insert script x = furthestReaching[index + 1] } else { // Getting initial x position // ,using the futrhest X position on the k - 1_line where D - 1 // ,meaning get (x, D, k) by (x, D - 1, k - 1) + moving right + snake // this moving right on the edit graph is compatible with delete script x = furthestReaching[index - 1] + 1 } // snake // diagonal moving can be performed with 0 cost. // `same` script is needed ? let _x = snake(x, D, k) if isReachedAtSink(_x, _x - k) { return D } furthestReaching[index] = _x } } fatalError("Never comes here") } } ``` ================================================ FILE: Naive Bayes Classifier/NaiveBayes.playground/Contents.swift ================================================ import Foundation // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif /*: ## Naive Bayes Classifier This playground uses the given algorithm and utilizes its features with some example datasets ### Gaussian Naive Bayes - Note: When using Gaussian NB you have to have continuous features (Double). For this example we are going to use a famous dataset with different types of wine. The labels of the features can be viewed [here](https://gist.github.com/tijptjik/9408623) */ guard let wineCSV = Bundle.main.path(forResource: "wine", ofType: "csv") else { print("Resource could not be found!") exit(0) } guard let csv = try? String(contentsOfFile: wineCSV) else { print("File could not be read!") exit(0) } /*: Reading the .csv file line per line */ let rows = csv.characters.split(separator: "\r\n").map { String($0) } /*: Splitting on the ; sign and converting the value to a Double - Important: Do not force unwrap the mapped values in your real application. Carefully convert them! This is just for the sake of showing how the algorithm works. */ let wineData = rows.map { row -> [Double] in let split = row.characters.split(separator: ";") return split.map { Double(String($0))! } } /*: The algorithm wants the classes and the data seperated since this gives a huge performance boost. Also I haven't implemented this in the NB class itself since it is not in the scope of it. */ let rowOfClasses = 0 let classes = wineData.map { Int($0[rowOfClasses]) } let data = wineData.map { row in return row.enumerated().filter { $0.offset != rowOfClasses }.map { $0.element } } /*: Again use `guard` on the result of a `try?` or simply `do-try-catch` because this would crash your application if an error occured. The array in the `classifyProba` method I passed is a former entry in the .csv file which I removed in order to classify it. */ let wineBayes = try! NaiveBayes(type: .gaussian, data: data, classes: classes).train() let result = wineBayes.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015]) /*: I can assure you that ***class 1*** is the correct result and as you can see the classifier thinks that its ***99.99%*** likely too. ### Multinomial Naive Bayes - Note: When using Multinomial NB you have to have categorical features (Int). Now this dataset is commonly used to describe the classification problem and it is categorical which means you don't have real values you just have categorical data as stated before. The structure of this dataset is as follows. Outlook,Temperature,Humidity,Windy ***Outlook***: 0 = rainy, 1 = overcast, 2 = sunny ***Temperature***: 0 = hot, 1 = mild, 2 = cool ***Humidity***: 0 = high, 1 = normal ***Windy***: 0 = false, 1 = true The classes are either he will play golf or not depending on the weather conditions. (0 = won't play, 1 = will play) */ let golfData = [ [0, 0, 0, 0], [0, 0, 0, 1], [1, 0, 0, 0], [2, 1, 0, 0], [2, 2, 1, 0], [2, 2, 1, 1], [1, 2, 1, 1], [0, 1, 0, 0], [0, 2, 1, 0], [2, 1, 1, 0], [0, 1, 1, 1], [1, 1, 0, 1], [1, 0, 1, 0], [2, 1, 0, 1] ] let golfClasses = [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0] let golfNaive = try! NaiveBayes(type: .multinomial, data: golfData, classes: golfClasses).train() /*: The weather conditions is as follows now: Outlook=rainy, Temperature=cool, Humidity=high, Windy=true */ let golfResult = golfNaive.classifyProba(with: [0, 2, 0, 1]) /*: Naive Bayes tells us that the golf player will ***not*** play with a likelihood of almost ***80%***. Which is true of course. */ ================================================ FILE: Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv ================================================ 1;14.23;1.71;2.43;15.6;127;2.8;3.06;.28;2.29;5.64;1.04;3.92;1065 1;13.2;1.78;2.14;11.2;100;2.65;2.76;.26;1.28;4.38;1.05;3.4;1050 1;13.16;2.36;2.67;18.6;101;2.8;3.24;.3;2.81;5.68;1.03;3.17;1185 1;14.37;1.95;2.5;16.8;113;3.85;3.49;.24;2.18;7.8;.86;3.45;1480 1;13.24;2.59;2.87;21;118;2.8;2.69;.39;1.82;4.32;1.04;2.93;735 1;14.2;1.76;2.45;15.2;112;3.27;3.39;.34;1.97;6.75;1.05;2.85;1450 1;14.39;1.87;2.45;14.6;96;2.5;2.52;.3;1.98;5.25;1.02;3.58;1290 1;14.06;2.15;2.61;17.6;121;2.6;2.51;.31;1.25;5.05;1.06;3.58;1295 1;14.83;1.64;2.17;14;97;2.8;2.98;.29;1.98;5.2;1.08;2.85;1045 1;13.86;1.35;2.27;16;98;2.98;3.15;.22;1.85;7.22;1.01;3.55;1045 1;14.1;2.16;2.3;18;105;2.95;3.32;.22;2.38;5.75;1.25;3.17;1510 1;14.12;1.48;2.32;16.8;95;2.2;2.43;.26;1.57;5;1.17;2.82;1280 1;13.75;1.73;2.41;16;89;2.6;2.76;.29;1.81;5.6;1.15;2.9;1320 1;14.75;1.73;2.39;11.4;91;3.1;3.69;.43;2.81;5.4;1.25;2.73;1150 1;14.38;1.87;2.38;12;102;3.3;3.64;.29;2.96;7.5;1.2;3;1547 1;13.63;1.81;2.7;17.2;112;2.85;2.91;.3;1.46;7.3;1.28;2.88;1310 1;14.3;1.92;2.72;20;120;2.8;3.14;.33;1.97;6.2;1.07;2.65;1280 1;13.83;1.57;2.62;20;115;2.95;3.4;.4;1.72;6.6;1.13;2.57;1130 1;14.19;1.59;2.48;16.5;108;3.3;3.93;.32;1.86;8.7;1.23;2.82;1680 1;13.64;3.1;2.56;15.2;116;2.7;3.03;.17;1.66;5.1;.96;3.36;845 1;14.06;1.63;2.28;16;126;3;3.17;.24;2.1;5.65;1.09;3.71;780 1;12.93;3.8;2.65;18.6;102;2.41;2.41;.25;1.98;4.5;1.03;3.52;770 1;13.71;1.86;2.36;16.6;101;2.61;2.88;.27;1.69;3.8;1.11;4;1035 1;13.5;1.81;2.61;20;96;2.53;2.61;.28;1.66;3.52;1.12;3.82;845 1;13.05;2.05;3.22;25;124;2.63;2.68;.47;1.92;3.58;1.13;3.2;830 1;13.39;1.77;2.62;16.1;93;2.85;2.94;.34;1.45;4.8;.92;3.22;1195 1;13.3;1.72;2.14;17;94;2.4;2.19;.27;1.35;3.95;1.02;2.77;1285 1;13.87;1.9;2.8;19.4;107;2.95;2.97;.37;1.76;4.5;1.25;3.4;915 1;14.02;1.68;2.21;16;96;2.65;2.33;.26;1.98;4.7;1.04;3.59;1035 1;13.73;1.5;2.7;22.5;101;3;3.25;.29;2.38;5.7;1.19;2.71;1285 1;13.58;1.66;2.36;19.1;106;2.86;3.19;.22;1.95;6.9;1.09;2.88;1515 1;13.68;1.83;2.36;17.2;104;2.42;2.69;.42;1.97;3.84;1.23;2.87;990 1;13.76;1.53;2.7;19.5;132;2.95;2.74;.5;1.35;5.4;1.25;3;1235 1;13.51;1.8;2.65;19;110;2.35;2.53;.29;1.54;4.2;1.1;2.87;1095 1;13.48;1.81;2.41;20.5;100;2.7;2.98;.26;1.86;5.1;1.04;3.47;920 1;13.28;1.64;2.84;15.5;110;2.6;2.68;.34;1.36;4.6;1.09;2.78;880 1;13.05;1.65;2.55;18;98;2.45;2.43;.29;1.44;4.25;1.12;2.51;1105 1;13.07;1.5;2.1;15.5;98;2.4;2.64;.28;1.37;3.7;1.18;2.69;1020 1;14.22;3.99;2.51;13.2;128;3;3.04;.2;2.08;5.1;.89;3.53;760 1;13.56;1.71;2.31;16.2;117;3.15;3.29;.34;2.34;6.13;.95;3.38;795 1;13.41;3.84;2.12;18.8;90;2.45;2.68;.27;1.48;4.28;.91;3;1035 1;13.88;1.89;2.59;15;101;3.25;3.56;.17;1.7;5.43;.88;3.56;1095 1;13.24;3.98;2.29;17.5;103;2.64;2.63;.32;1.66;4.36;.82;3;680 1;13.05;1.77;2.1;17;107;3;3;.28;2.03;5.04;.88;3.35;885 1;14.21;4.04;2.44;18.9;111;2.85;2.65;.3;1.25;5.24;.87;3.33;1080 1;14.38;3.59;2.28;16;102;3.25;3.17;.27;2.19;4.9;1.04;3.44;1065 1;13.9;1.68;2.12;16;101;3.1;3.39;.21;2.14;6.1;.91;3.33;985 1;14.1;2.02;2.4;18.8;103;2.75;2.92;.32;2.38;6.2;1.07;2.75;1060 1;13.94;1.73;2.27;17.4;108;2.88;3.54;.32;2.08;8.90;1.12;3.1;1260 1;13.05;1.73;2.04;12.4;92;2.72;3.27;.17;2.91;7.2;1.12;2.91;1150 1;13.83;1.65;2.6;17.2;94;2.45;2.99;.22;2.29;5.6;1.24;3.37;1265 1;13.82;1.75;2.42;14;111;3.88;3.74;.32;1.87;7.05;1.01;3.26;1190 1;13.77;1.9;2.68;17.1;115;3;2.79;.39;1.68;6.3;1.13;2.93;1375 1;13.74;1.67;2.25;16.4;118;2.6;2.9;.21;1.62;5.85;.92;3.2;1060 1;13.56;1.73;2.46;20.5;116;2.96;2.78;.2;2.45;6.25;.98;3.03;1120 1;14.22;1.7;2.3;16.3;118;3.2;3;.26;2.03;6.38;.94;3.31;970 1;13.29;1.97;2.68;16.8;102;3;3.23;.31;1.66;6;1.07;2.84;1270 1;13.72;1.43;2.5;16.7;108;3.4;3.67;.19;2.04;6.8;.89;2.87;1285 2;12.37;.94;1.36;10.6;88;1.98;.57;.28;.42;1.95;1.05;1.82;520 2;12.33;1.1;2.28;16;101;2.05;1.09;.63;.41;3.27;1.25;1.67;680 2;12.64;1.36;2.02;16.8;100;2.02;1.41;.53;.62;5.75;.98;1.59;450 2;13.67;1.25;1.92;18;94;2.1;1.79;.32;.73;3.8;1.23;2.46;630 2;12.37;1.13;2.16;19;87;3.5;3.1;.19;1.87;4.45;1.22;2.87;420 2;12.17;1.45;2.53;19;104;1.89;1.75;.45;1.03;2.95;1.45;2.23;355 2;12.37;1.21;2.56;18.1;98;2.42;2.65;.37;2.08;4.6;1.19;2.3;678 2;13.11;1.01;1.7;15;78;2.98;3.18;.26;2.28;5.3;1.12;3.18;502 2;12.37;1.17;1.92;19.6;78;2.11;2;.27;1.04;4.68;1.12;3.48;510 2;13.34;.94;2.36;17;110;2.53;1.3;.55;.42;3.17;1.02;1.93;750 2;12.21;1.19;1.75;16.8;151;1.85;1.28;.14;2.5;2.85;1.28;3.07;718 2;12.29;1.61;2.21;20.4;103;1.1;1.02;.37;1.46;3.05;906;1.82;870 2;13.86;1.51;2.67;25;86;2.95;2.86;.21;1.87;3.38;1.36;3.16;410 2;13.49;1.66;2.24;24;87;1.88;1.84;.27;1.03;3.74;.98;2.78;472 2;12.99;1.67;2.6;30;139;3.3;2.89;.21;1.96;3.35;1.31;3.5;985 2;11.96;1.09;2.3;21;101;3.38;2.14;.13;1.65;3.21;.99;3.13;886 2;11.66;1.88;1.92;16;97;1.61;1.57;.34;1.15;3.8;1.23;2.14;428 2;13.03;.9;1.71;16;86;1.95;2.03;.24;1.46;4.6;1.19;2.48;392 2;11.84;2.89;2.23;18;112;1.72;1.32;.43;.95;2.65;.96;2.52;500 2;12.33;.99;1.95;14.8;136;1.9;1.85;.35;2.76;3.4;1.06;2.31;750 2;12.7;3.87;2.4;23;101;2.83;2.55;.43;1.95;2.57;1.19;3.13;463 2;12;.92;2;19;86;2.42;2.26;.3;1.43;2.5;1.38;3.12;278 2;12.72;1.81;2.2;18.8;86;2.2;2.53;.26;1.77;3.9;1.16;3.14;714 2;12.08;1.13;2.51;24;78;2;1.58;.4;1.4;2.2;1.31;2.72;630 2;13.05;3.86;2.32;22.5;85;1.65;1.59;.61;1.62;4.8;.84;2.01;515 2;11.84;.89;2.58;18;94;2.2;2.21;.22;2.35;3.05;.79;3.08;520 2;12.67;.98;2.24;18;99;2.2;1.94;.3;1.46;2.62;1.23;3.16;450 2;12.16;1.61;2.31;22.8;90;1.78;1.69;.43;1.56;2.45;1.33;2.26;495 2;11.65;1.67;2.62;26;88;1.92;1.61;.4;1.34;2.6;1.36;3.21;562 2;11.64;2.06;2.46;21.6;84;1.95;1.69;.48;1.35;2.8;1;2.75;680 2;12.08;1.33;2.3;23.6;70;2.2;1.59;.42;1.38;1.74;1.07;3.21;625 2;12.08;1.83;2.32;18.5;81;1.6;1.5;.52;1.64;2.4;1.08;2.27;480 2;12;1.51;2.42;22;86;1.45;1.25;.5;1.63;3.6;1.05;2.65;450 2;12.69;1.53;2.26;20.7;80;1.38;1.46;.58;1.62;3.05;.96;2.06;495 2;12.29;2.83;2.22;18;88;2.45;2.25;.25;1.99;2.15;1.15;3.3;290 2;11.62;1.99;2.28;18;98;3.02;2.26;.17;1.35;3.25;1.16;2.96;345 2;12.47;1.52;2.2;19;162;2.5;2.27;.32;3.28;2.6;1.16;2.63;937 2;11.81;2.12;2.74;21.5;134;1.6;.99;.14;1.56;2.5;.95;2.26;625 2;12.29;1.41;1.98;16;85;2.55;2.5;.29;1.77;2.9;1.23;2.74;428 2;12.37;1.07;2.1;18.5;88;3.52;3.75;.24;1.95;4.5;1.04;2.77;660 2;12.29;3.17;2.21;18;88;2.85;2.99;.45;2.81;2.3;1.42;2.83;406 2;12.08;2.08;1.7;17.5;97;2.23;2.17;.26;1.4;3.3;1.27;2.96;710 2;12.6;1.34;1.9;18.5;88;1.45;1.36;.29;1.35;2.45;1.04;2.77;562 2;12.34;2.45;2.46;21;98;2.56;2.11;.34;1.31;2.8;.8;3.38;438 2;11.82;1.72;1.88;19.5;86;2.5;1.64;.37;1.42;2.06;.94;2.44;415 2;12.51;1.73;1.98;20.5;85;2.2;1.92;.32;1.48;2.94;1.04;3.57;672 2;12.42;2.55;2.27;22;90;1.68;1.84;.66;1.42;2.7;.86;3.3;315 2;12.25;1.73;2.12;19;80;1.65;2.03;.37;1.63;3.4;1;3.17;510 2;12.72;1.75;2.28;22.5;84;1.38;1.76;.48;1.63;3.3;.88;2.42;488 2;12.22;1.29;1.94;19;92;2.36;2.04;.39;2.08;2.7;.86;3.02;312 2;11.61;1.35;2.7;20;94;2.74;2.92;.29;2.49;2.65;.96;3.26;680 2;11.46;3.74;1.82;19.5;107;3.18;2.58;.24;3.58;2.9;.75;2.81;562 2;12.52;2.43;2.17;21;88;2.55;2.27;.26;1.22;2;.9;2.78;325 2;11.76;2.68;2.92;20;103;1.75;2.03;.6;1.05;3.8;1.23;2.5;607 2;11.41;.74;2.5;21;88;2.48;2.01;.42;1.44;3.08;1.1;2.31;434 2;12.08;1.39;2.5;22.5;84;2.56;2.29;.43;1.04;2.9;.93;3.19;385 2;11.03;1.51;2.2;21.5;85;2.46;2.17;.52;2.01;1.9;1.71;2.87;407 2;11.82;1.47;1.99;20.8;86;1.98;1.6;.3;1.53;1.95;.95;3.33;495 2;12.42;1.61;2.19;22.5;108;2;2.09;.34;1.61;2.06;1.06;2.96;345 2;12.77;3.43;1.98;16;80;1.63;1.25;.43;.83;3.4;.7;2.12;372 2;12;3.43;2;19;87;2;1.64;.37;1.87;1.28;.93;3.05;564 2;11.45;2.4;2.42;20;96;2.9;2.79;.32;1.83;3.25;.8;3.39;625 2;11.56;2.05;3.23;28.5;119;3.18;5.08;.47;1.87;6;.93;3.69;465 2;12.42;4.43;2.73;26.5;102;2.2;2.13;.43;1.71;2.08;.92;3.12;365 2;13.05;5.8;2.13;21.5;86;2.62;2.65;.3;2.01;2.6;.73;3.1;380 2;11.87;4.31;2.39;21;82;2.86;3.03;.21;2.91;2.8;.75;3.64;380 2;12.07;2.16;2.17;21;85;2.6;2.65;.37;1.35;2.76;.86;3.28;378 2;12.43;1.53;2.29;21.5;86;2.74;3.15;.39;1.77;3.94;.69;2.84;352 2;11.79;2.13;2.78;28.5;92;2.13;2.24;.58;1.76;3;.97;2.44;466 2;12.37;1.63;2.3;24.5;88;2.22;2.45;.4;1.9;2.12;.89;2.78;342 2;12.04;4.3;2.38;22;80;2.1;1.75;.42;1.35;2.6;.79;2.57;580 3;12.86;1.35;2.32;18;122;1.51;1.25;.21;.94;4.1;.76;1.29;630 3;12.88;2.99;2.4;20;104;1.3;1.22;.24;.83;5.4;.74;1.42;530 3;12.81;2.31;2.4;24;98;1.15;1.09;.27;.83;5.7;.66;1.36;560 3;12.7;3.55;2.36;21.5;106;1.7;1.2;.17;.84;5;.78;1.29;600 3;12.51;1.24;2.25;17.5;85;2;.58;.6;1.25;5.45;.75;1.51;650 3;12.6;2.46;2.2;18.5;94;1.62;.66;.63;.94;7.1;.73;1.58;695 3;12.25;4.72;2.54;21;89;1.38;.47;.53;.8;3.85;.75;1.27;720 3;12.53;5.51;2.64;25;96;1.79;.6;.63;1.1;5;.82;1.69;515 3;13.49;3.59;2.19;19.5;88;1.62;.48;.58;.88;5.7;.81;1.82;580 3;12.84;2.96;2.61;24;101;2.32;.6;.53;.81;4.92;.89;2.15;590 3;12.93;2.81;2.7;21;96;1.54;.5;.53;.75;4.6;.77;2.31;600 3;13.36;2.56;2.35;20;89;1.4;.5;.37;.64;5.6;.7;2.47;780 3;13.52;3.17;2.72;23.5;97;1.55;.52;.5;.55;4.35;.89;2.06;520 3;13.62;4.95;2.35;20;92;2;.8;.47;1.02;4.4;.91;2.05;550 3;12.25;3.88;2.2;18.5;112;1.38;.78;.29;1.14;8.21;.65;2;855 3;13.16;3.57;2.15;21;102;1.5;.55;.43;1.3;4;.6;1.68;830 3;13.88;5.04;2.23;20;80;.98;.34;.4;.68;4.9;.58;1.33;415 3;12.87;4.61;2.48;21.5;86;1.7;.65;.47;.86;7.65;.54;1.86;625 3;13.32;3.24;2.38;21.5;92;1.93;.76;.45;1.25;8.42;.55;1.62;650 3;13.08;3.9;2.36;21.5;113;1.41;1.39;.34;1.14;9.40;.57;1.33;550 3;13.5;3.12;2.62;24;123;1.4;1.57;.22;1.25;8.60;.59;1.3;500 3;12.79;2.67;2.48;22;112;1.48;1.36;.24;1.26;10.8;.48;1.47;480 3;13.11;1.9;2.75;25.5;116;2.2;1.28;.26;1.56;7.1;.61;1.33;425 3;13.23;3.3;2.28;18.5;98;1.8;.83;.61;1.87;10.52;.56;1.51;675 3;12.58;1.29;2.1;20;103;1.48;.58;.53;1.4;7.6;.58;1.55;640 3;13.17;5.19;2.32;22;93;1.74;.63;.61;1.55;7.9;.6;1.48;725 3;13.84;4.12;2.38;19.5;89;1.8;.83;.48;1.56;9.01;.57;1.64;480 3;12.45;3.03;2.64;27;97;1.9;.58;.63;1.14;7.5;.67;1.73;880 3;14.34;1.68;2.7;25;98;2.8;1.31;.53;2.7;13;.57;1.96;660 3;13.48;1.67;2.64;22.5;89;2.6;1.1;.52;2.29;11.75;.57;1.78;620 3;12.36;3.83;2.38;21;88;2.3;.92;.5;1.04;7.65;.56;1.58;520 3;13.69;3.26;2.54;20;107;1.83;.56;.5;.8;5.88;.96;1.82;680 3;12.85;3.27;2.58;22;106;1.65;.6;.6;.96;5.58;.87;2.11;570 3;12.96;3.45;2.35;18.5;106;1.39;.7;.4;.94;5.28;.68;1.75;675 3;13.78;2.76;2.3;22;90;1.35;.68;.41;1.03;9.58;.7;1.68;615 3;13.73;4.36;2.26;22.5;88;1.28;.47;.52;1.15;6.62;.78;1.75;520 3;13.45;3.7;2.6;23;111;1.7;.92;.43;1.46;10.68;.85;1.56;695 3;12.82;3.37;2.3;19.5;88;1.48;.66;.4;.97;10.26;.72;1.75;685 3;13.58;2.58;2.69;24.5;105;1.55;.84;.39;1.54;8.66;.74;1.8;750 3;13.4;4.6;2.86;25;112;1.98;.96;.27;1.11;8.5;.67;1.92;630 3;12.2;3.03;2.32;19;96;1.25;.49;.4;.73;5.5;.66;1.83;510 3;12.77;2.39;2.28;19.5;86;1.39;.51;.48;.64;9.899999;.57;1.63;470 3;14.16;2.51;2.48;20;91;1.68;.7;.44;1.24;9.7;.62;1.71;660 3;13.71;5.65;2.45;20.5;95;1.68;.61;.52;1.06;7.7;.64;1.74;740 3;13.4;3.91;2.48;23;102;1.8;.75;.43;1.41;7.3;.7;1.56;750 3;13.27;4.28;2.26;20;120;1.59;.69;.43;1.35;10.2;.59;1.56;835 3;13.17;2.59;2.37;20;120;1.65;.68;.53;1.46;9.3;.6;1.62;840 3;14.13;4.1;2.74;24.5;96;2.05;.76;.56;1.35;9.2;.61;1.6;560 ================================================ FILE: Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift ================================================ // // NaiveBayes.swift // NaiveBayes // // Created by Philipp Gabriel on 14.04.17. // Copyright © 2017 ph1ps. All rights reserved. // import Foundation extension String: Error {} extension Array where Element == Double { func mean() -> Double { return self.reduce(0, +) / Double(count) } func standardDeviation() -> Double { let calculatedMean = mean() let sum = self.reduce(0.0) { (previous, next) in return previous + pow(next - calculatedMean, 2) } return sqrt(sum / Double(count - 1)) } } extension Array where Element == Int { func uniques() -> Set { return Set(self) } } public enum NBType { case gaussian case multinomial //case bernoulli --> TODO func calcLikelihood(variables: [Any], input: Any) -> Double? { if case .gaussian = self { guard let input = input as? Double else { return nil } guard let mean = variables[0] as? Double else { return nil } guard let stDev = variables[1] as? Double else { return nil } let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) let distribution = eulerPart / sqrt(2 * .pi) / stDev return distribution } else if case .multinomial = self { guard let variables = variables as? [(category: Int, probability: Double)] else { return nil } guard let input = input as? Int else { return nil } return variables.first { variable in return variable.category == input }?.probability } return nil } func train(values: [Any]) -> [Any]? { if case .gaussian = self { guard let values = values as? [Double] else { return nil } return [values.mean(), values.standardDeviation()] } else if case .multinomial = self { guard let values = values as? [Int] else { return nil } let count = values.count let categoryProba = values.uniques().map { value -> (Int, Double) in return (value, Double(values.filter { $0 == value }.count) / Double(count)) } return categoryProba } return nil } } public class NaiveBayes { var variables: [Int: [(feature: Int, variables: [Any])]] var type: NBType var data: [[T]] var classes: [Int] public init(type: NBType, data: [[T]], classes: [Int]) throws { self.type = type self.data = data self.classes = classes self.variables = [Int: [(Int, [Any])]]() if case .gaussian = type, T.self != Double.self { throw "When using Gaussian NB you have to have continuous features (Double)" } else if case .multinomial = type, T.self != Int.self { throw "When using Multinomial NB you have to have categorical features (Int)" } } public func train() throws -> Self { for `class` in classes.uniques() { variables[`class`] = [(Int, [Any])]() let classDependent = data.enumerated().filter { (offset, _) in return classes[offset] == `class` } for feature in 0.. Int { let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } guard let `class` = likelihoods?.0 else { return -1 } return `class` } public func classifyProba(with input: [T]) -> [(Int, Double)] { var probaClass = [Int: Double]() let amount = classes.count classes.forEach { `class` in let individual = classes.filter { $0 == `class` }.count probaClass[`class`] = Double(individual) / Double(amount) } let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in let distribution = value.map { (feature, variables) -> Double in return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 } return (`class`, distribution) } let likelihoods = classesAndFeatures.map { (`class`, distribution) in return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) } let sum = likelihoods.map { $0.1 }.reduce(0, +) let normalized = likelihoods.map { (`class`, likelihood) in return (`class`, likelihood / sum) } return normalized } } ================================================ FILE: Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground ================================================ ================================================ FILE: Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline ================================================ ================================================ FILE: Naive Bayes Classifier/NaiveBayes.swift ================================================ // // NaiveBayes.swift // NaiveBayes // // Created by Philipp Gabriel on 14.04.17. // Copyright © 2017 ph1ps. All rights reserved. // import Foundation extension String: Error {} extension Array where Element == Double { func mean() -> Double { return self.reduce(0, +) / Double(count) } func standardDeviation() -> Double { let calculatedMean = mean() let sum = self.reduce(0.0) { (previous, next) in return previous + pow(next - calculatedMean, 2) } return sqrt(sum / Double(count - 1)) } } extension Array where Element == Int { func uniques() -> Set { return Set(self) } } enum NBType { case gaussian case multinomial //case bernoulli --> TODO func calcLikelihood(variables: [Any], input: Any) -> Double? { if case .gaussian = self { guard let input = input as? Double else { return nil } guard let mean = variables[0] as? Double else { return nil } guard let stDev = variables[1] as? Double else { return nil } let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) let distribution = eulerPart / sqrt(2 * .pi) / stDev return distribution } else if case .multinomial = self { guard let variables = variables as? [(category: Int, probability: Double)] else { return nil } guard let input = input as? Int else { return nil } return variables.first { variable in return variable.category == input }?.probability } return nil } func train(values: [Any]) -> [Any]? { if case .gaussian = self { guard let values = values as? [Double] else { return nil } return [values.mean(), values.standardDeviation()] } else if case .multinomial = self { guard let values = values as? [Int] else { return nil } let count = values.count let categoryProba = values.uniques().map { value -> (Int, Double) in return (value, Double(values.filter { $0 == value }.count) / Double(count)) } return categoryProba } return nil } } class NaiveBayes { var variables: [Int: [(feature: Int, variables: [Any])]] var type: NBType var data: [[T]] var classes: [Int] init(type: NBType, data: [[T]], classes: [Int]) throws { self.type = type self.data = data self.classes = classes self.variables = [Int: [(Int, [Any])]]() if case .gaussian = type, T.self != Double.self { throw "When using Gaussian NB you have to have continuous features (Double)" } else if case .multinomial = type, T.self != Int.self { throw "When using Multinomial NB you have to have categorical features (Int)" } } func train() throws -> Self { for `class` in classes.uniques() { variables[`class`] = [(Int, [Any])]() let classDependent = data.enumerated().filter { (offset, _) in return classes[offset] == `class` } for feature in 0.. Int { let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } guard let `class` = likelihoods?.0 else { return -1 } return `class` } func classifyProba(with input: [T]) -> [(Int, Double)] { var probaClass = [Int: Double]() let amount = classes.count classes.forEach { `class` in let individual = classes.filter { $0 == `class` }.count probaClass[`class`] = Double(individual) / Double(amount) } let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in let distribution = value.map { (feature, variables) -> Double in return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 } return (`class`, distribution) } let likelihoods = classesAndFeatures.map { (`class`, distribution) in return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) } let sum = likelihoods.map { $0.1 }.reduce(0, +) let normalized = likelihoods.map { (`class`, likelihood) in return (`class`, likelihood / sum) } return normalized } } ================================================ FILE: Naive Bayes Classifier/README.md ================================================ # Naive Bayes Classifier > ***Disclaimer:*** Do not get scared of complicated formulas or terms, I will describe them right after I use them. Also the math skills you need to understand this are very basic. The goal of a classifier is to predict the class of a given data entry based on previously fed data and its features. Now what is a class or a feature? The best I can do is to describe it with a table. This is a dataset that uses height, weight and foot size of a person to illustrate the relationship between those values and the sex. | Sex | height (feet) | weight(lbs) | foot size (inches) | | ------------- |:-------------:|:-----:|:---:| | male | 6 | 180 | 12 | | male | 5.92 | 190 | 11 | | male | 5.58 | 170 | 12 | | male | 5.92 | 165 | 10 | | female | 5 | 100 | 6 | | female | 5.5 | 150 | 8 | | female | 5.42 | 130 | 7 | | female | 5.75 | 150 | 9 | The ***classes*** of this table is the data in the sex column (male/female). You "classify" the rest of the data and bind them to a sex. The ***features*** of this table are the labels of the other columns (height, weight, foot size) and the numbers right under the labels. Now that I've told you what a classifier is I will tell you what exactly a ***Naive Bayes classifier*** is. There are a lot of other classifiers out there but what's so special about this specific is that it only needs a very small dataset to get good results. The others like Random Forests normally need a very large dataset. Why isn't this algorithm used more you might ask (or not). Because it is normally ***outperformed*** in accuracy by ***Random Forests*** or ***Boosted Trees***. ## Theory The Naive Bayes classifier utilizes the ***Bayes Theorem*** (as its name suggests) which looks like this. ![](images/bayes.gif) ***P*** always means the probability of something. ***A*** is the class, ***B*** is the data depending on a feature and the ***pipe*** symbol means given. P(A | B) therefore is: probability of the class given the data (which is dependent on the feature). This is all you have to know about the Bayes Theorem. The important thing for us is now how to calculate all those variables, plug them into this formula and you are ready to classify data. ### **P(A)** This is the probability of the class. To get back to the example I gave before: Let's say we want to classify this data entry: | height (feet) | weight(lbs) | foot size (inches) | |:-------------:|:-----:|:---:| | 6 | 130 | 8 | What Naive Bayes classifier now does: it checks the probability for every class possible which is in our case either male or female. Look back at the original table and count the male and the female entries. Then divide them by the overall count of data entries. P(male) = 4 / 8 = 0.5 P(female) = 4 / 8 = 0.5 This should be a very easy task to do. Basically just the probability of all classes. ### **P(B)** This variable is not needed in a Naive Bayes classifier. It is the probability of the data. It does not change, therefore it is a constant. And what can you do with a constant? Exactly! Discard it. This saves time and code. ### **P(B | A)** This is the probability of the data given the class. To calculate this I have to introduce you to the subtypes of NB. You have to decide which you use depending on your data which you want to classify. ### **Gaussian Naive Bayes** If you have a dataset like the one I showed you before (continuous features -> `Double`s) you have to use this subtype. There are 3 formulas you need for Gaussian NB to calculate P(B | A). ![mean](images/mean.gif) ![standard deviation](images/standard_deviation.gif) ![normal distribution](images/normal_distribution.gif) and **P(x | y) = P(B | A)** Again, very complicated looking formulas but they are very easy. The first formula with µ is just the mean of the data (adding all data points and dividing them by the count). The second with σ is the standard deviation. You might have heard of it somewhen in school. It is just the sum of all values minus the mean, squared and that divided by the count of the data minus 1 and a sqaure root around it. The third equation is the Gaussian or normal distribution if you want to read more about it I suggest reading [this](https://en.wikipedia.org/wiki/Normal_distribution). Why the Gaussian distribution? Because we assume that the continuous values associated with each class are distributed according to the Gaussian distribution. Simple as that. ### **Multinomial Naive Bayes** What do we do if we have this for examples: ![tennis or golf](images/tennis_dataset.png) We can't just calculate the mean of sunny, overcast and rainy. This is why we need the categorical model which is the multinomial NB. This is the last formula, I promise! ![multinomial](images/multinomial.gif) Now this is the number of times feature **i** appears in a sample **N** of class **y** in the data set divided by the count of the sample just depending on the class **y**. That θ is also just a fancy way of writing P(B | A). You might have noticed that there is still the α in this formula. This solves a problem called "zero-frequency-problem". Because what happens if there is no sample with feature **i** and class **y**? The whole equation would result in 0 (because 0 / something is always 0). This is a huge problem but there is a simple solution to this. Just add 1 to any count of the sample (α = 1). ## Those formulas in action Enough talking! This is the code. If you want a deeper explanation of how the code works just look at the Playground I provided. ![code example](images/code_example.png) *Written for Swift Algorithm Club by Philipp Gabriel* ================================================ FILE: Octree/Octree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import UIKit import simd let boxMin = vector_double3(0, 2, 6) let boxMax = vector_double3(5, 10, 9) let box = Box(boxMin: boxMin, boxMax: boxMax) var octree = Octree(boundingBox: box, minimumCellSize: 5.0) var five = octree.add(5, at: vector_double3(3,4,8)) octree.add(8, at: vector_double3(3,4,8.2)) octree.add(10, at: vector_double3(3,4,8.2)) octree.add(7, at: vector_double3(2,5,8)) octree.add(2, at: vector_double3(1,6,7)) var cont = octree.elements(at: vector_double3(3,4,8.2)) octree.remove(8) octree.elements(at: vector_double3(3,4,8)) let boxMin2 = vector_double3(1,3,7) let boxMax2 = vector_double3(4,9,8) let box2 = Box(boxMin: boxMin2, boxMax: boxMax2) box.isContained(in: box2) box.intersects(box2) let boxMin3 = vector_double3(3,8,8) let boxMax3 = vector_double3(10,12,20) let box3 = Box(boxMin: boxMin3, boxMax: boxMax3) box3.intersects(box3) octree.elements(in: box) octree.elements(in: box2) print(octree) ================================================ FILE: Octree/Octree.playground/Sources/Octree.swift ================================================ import Foundation import simd public struct Box: CustomStringConvertible { public var boxMin: vector_double3 public var boxMax: vector_double3 public init(boxMin: vector_double3, boxMax: vector_double3) { self.boxMin = boxMin self.boxMax = boxMax } public var boxSize: vector_double3 { return boxMax - boxMin } var halfBoxSize: vector_double3 { return boxSize/2 } var frontLeftTop: Box { let boxMin = self.boxMin + vector_double3(0, halfBoxSize.y, halfBoxSize.z) let boxMax = self.boxMax - vector_double3(halfBoxSize.x, 0, 0) return Box(boxMin: boxMin, boxMax: boxMax) } var frontLeftBottom: Box { let boxMin = self.boxMin + vector_double3(0, 0, halfBoxSize.z) let boxMax = self.boxMax - vector_double3(halfBoxSize.x, halfBoxSize.y, 0) return Box(boxMin: boxMin, boxMax: boxMax) } var frontRightTop: Box { let boxMin = self.boxMin + vector_double3(halfBoxSize.x, halfBoxSize.y, halfBoxSize.z) let boxMax = self.boxMax - vector_double3(0, 0, 0) return Box(boxMin: boxMin, boxMax: boxMax) } var frontRightBottom: Box { let boxMin = self.boxMin + vector_double3(halfBoxSize.x, 0, halfBoxSize.z) let boxMax = self.boxMax - vector_double3(0, halfBoxSize.y, 0) return Box(boxMin: boxMin, boxMax: boxMax) } var backLeftTop: Box { let boxMin = self.boxMin + vector_double3(0, halfBoxSize.y, 0) let boxMax = self.boxMax - vector_double3(halfBoxSize.x, 0, halfBoxSize.z) return Box(boxMin: boxMin, boxMax: boxMax) } var backLeftBottom: Box { let boxMin = self.boxMin + vector_double3(0, 0, 0) let boxMax = self.boxMax - vector_double3(halfBoxSize.x, halfBoxSize.y, halfBoxSize.z) return Box(boxMin: boxMin, boxMax: boxMax) } var backRightTop: Box { let boxMin = self.boxMin + vector_double3(halfBoxSize.x, halfBoxSize.y, 0) let boxMax = self.boxMax - vector_double3(0, 0, halfBoxSize.z) return Box(boxMin: boxMin, boxMax: boxMax) } var backRightBottom: Box { let boxMin = self.boxMin + vector_double3(halfBoxSize.x, 0, 0) let boxMax = self.boxMax - vector_double3(0, halfBoxSize.y, halfBoxSize.z) return Box(boxMin: boxMin, boxMax: boxMax) } public func contains(_ point: vector_double3) -> Bool { return (boxMin.x <= point.x && point.x <= boxMax.x) && (boxMin.y <= point.y && point.y <= boxMax.y) && (boxMin.z <= point.z && point.z <= boxMax.z) } public func contains(_ box: Box) -> Bool { return self.boxMin.x <= box.boxMin.x && self.boxMin.y <= box.boxMin.y && self.boxMin.z <= box.boxMin.z && self.boxMax.x >= box.boxMax.x && self.boxMax.y >= box.boxMax.y && self.boxMax.z >= box.boxMax.z } public func isContained(in box: Box) -> Bool { return self.boxMin.x >= box.boxMin.x && self.boxMin.y >= box.boxMin.y && self.boxMin.z >= box.boxMin.z && self.boxMax.x <= box.boxMax.x && self.boxMax.y <= box.boxMax.y && self.boxMax.z <= box.boxMax.z } /* This intersect function does not handle all possibilities such as two beams of different diameter crossing each other half way. But it does cover all cases needed for an octree as the bounding box has to contain the given intersect box */ public func intersects(_ box: Box) -> Bool { let corners = [ vector_double3(boxMin.x, boxMax.y, boxMax.z), //frontLeftTop vector_double3(boxMin.x, boxMin.y, boxMax.z), //frontLeftBottom vector_double3(boxMax.x, boxMax.y, boxMax.z), //frontRightTop vector_double3(boxMax.x, boxMin.y, boxMax.z), //frontRightBottom vector_double3(boxMin.x, boxMax.y, boxMin.z), //backLeftTop vector_double3(boxMin.x, boxMin.y, boxMin.z), //backLeftBottom vector_double3(boxMax.x, boxMax.y, boxMin.z), //backRightTop vector_double3(boxMax.x, boxMin.y, boxMin.z) //backRightBottom ] for corner in corners { if box.contains(corner) { return true } } return false } public var description: String { return "Box from:\(boxMin) to:\(boxMax)" } } public class OctreeNode: CustomStringConvertible { let box: Box var point: vector_double3! var elements: [T]! var type: NodeType = .leaf enum NodeType { case leaf case `internal`(children: Children) } public var description: String { switch type { case .leaf: return "leaf node with \(box) elements: \(elements)" case .internal: return "internal node with \(box)" } } var recursiveDescription: String { return recursiveDescription(withTabCount: 0) } private func recursiveDescription(withTabCount count: Int) -> String { let indent = String(repeating: "\t", count: count) var result = "\(indent)" + description + "\n" switch type { case .internal(let children): for child in children { result += child.recursiveDescription(withTabCount: count + 1) } default: break } return result } struct Children: Sequence { let frontLeftTop: OctreeNode let frontLeftBottom: OctreeNode let frontRightTop: OctreeNode let frontRightBottom: OctreeNode let backLeftTop: OctreeNode let backLeftBottom: OctreeNode let backRightTop: OctreeNode let backRightBottom: OctreeNode init(parentNode: OctreeNode) { frontLeftTop = OctreeNode(box: parentNode.box.frontLeftTop) frontLeftBottom = OctreeNode(box: parentNode.box.frontLeftBottom) frontRightTop = OctreeNode(box: parentNode.box.frontRightTop) frontRightBottom = OctreeNode(box: parentNode.box.frontRightBottom) backLeftTop = OctreeNode(box: parentNode.box.backLeftTop) backLeftBottom = OctreeNode(box: parentNode.box.backLeftBottom) backRightTop = OctreeNode(box: parentNode.box.backRightTop) backRightBottom = OctreeNode(box: parentNode.box.backRightBottom) } struct ChildrenIterator: IteratorProtocol { var index = 0 let children: Children init(children: Children) { self.children = children } mutating func next() -> OctreeNode? { defer { index += 1 } switch index { case 0: return children.frontLeftTop case 1: return children.frontLeftBottom case 2: return children.frontRightTop case 3: return children.frontRightBottom case 4: return children.backLeftTop case 5: return children.backLeftBottom case 6: return children.backRightTop case 7: return children.backRightBottom default: return nil } } } func makeIterator() -> ChildrenIterator { return ChildrenIterator(children: self) } } init(box: Box) { self.box = box } @discardableResult func add(_ element: T, at point: vector_double3) -> OctreeNode { return tryAdd(element, at: point)! } private func tryAdd(_ element: T, at point: vector_double3) -> OctreeNode? { if !box.contains(point) { return nil } switch type { case .internal(let children): // pass the point to one of the children for child in children { if let child = child.tryAdd(element, at: point) { return child } } fatalError("box.contains evaluted to true, but none of the children added the point") case .leaf: if self.point != nil { // leaf already has an asigned point if self.point == point { self.elements.append(element) return self } else { return subdivide(adding: element, at: point) } } else { self.elements = [element] self.point = point return self } } } func add(_ elements: [T], at point: vector_double3) { for element in elements { self.add(element, at: point) } } @discardableResult func remove(_ element: T) -> Bool { switch type { case .leaf: if let elements = self.elements { // leaf contains one ore more elements if let index = elements.index(of: element) { // leaf contains the element we want to remove self.elements.remove(at: index) // if elements is now empty remove it if self.elements.isEmpty { self.elements = nil } return true } } return false case .internal(let children): for child in children { if child.remove(element) { return true } } return false } } func elements(at point: vector_double3) -> [T]? { switch type { case .leaf: if self.point == point { return self.elements } case .internal(let children): for child in children { if child.box.contains(point) { return child.elements(at: point) } } } // tree does not contain given point return nil } func elements(in box: Box) -> [T]? { var values: [T] = [] switch type { case .leaf: // check if leaf has an assigned point if let point = self.point { // check if point is inside given box if box.contains(point) { values += elements ?? [] } } case .internal(let children): for child in children { if child.box.isContained(in: box) { // child is contained in box // add all children of child values += child.elements(in: child.box) ?? [] } else if child.box.contains(box) || child.box.intersects(box) { // child contains at least part of box values += child.elements(in: box) ?? [] } // child does not contain any part of given box } } if values.isEmpty { return nil } return values } private func subdivide(adding element: T, at point: vector_double3) -> OctreeNode? { precondition(self.elements != nil, "Subdividing while leaf does not contain a element") precondition(self.point != nil, "Subdividing while leaf does not contain a point") switch type { case .leaf: type = .internal(children: Children(parentNode: self)) // add element previously contained in leaf to children self.add(self.elements, at: self.point) self.elements = nil self.point = nil // add new element to children return self.add(element, at: point) case .internal: preconditionFailure("Calling subdivide on an internal node") } } } public class Octree: CustomStringConvertible { var root: OctreeNode public var description: String { return "Octree\n" + root.recursiveDescription } public init(boundingBox: Box, minimumCellSize: Double) { root = OctreeNode(box: boundingBox) } @discardableResult public func add(_ element: T, at point: vector_double3) -> OctreeNode { return root.add(element, at: point) } @discardableResult public func remove(_ element: T, using node: OctreeNode) -> Bool { return node.remove(element) } @discardableResult public func remove(_ element: T) -> Bool { return root.remove(element) } public func elements(at point: vector_double3) -> [T]? { return root.elements(at: point) } public func elements(in box: Box) -> [T]? { precondition(root.box.contains(box), "box is outside of octree bounds") return root.elements(in: box) } } ================================================ FILE: Octree/Octree.playground/contents.xcplayground ================================================ ================================================ FILE: Octree/Octree.playground/timeline.xctimeline ================================================ ================================================ FILE: Octree/README.md ================================================ # OcTree An octree is a [tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Tree) in which each internal (not leaf) node has eight children. Often used for collision detection in games for example. ### Problem Consider the following problem: your need to store a number of objects in 3D space (each at a certain location with `X`, `Y` and `Z` coordinates) and then you need to answer which objects lie in a certain 3D region. A naive solution would be to store the points inside an array and then iterate over the points and check each one individually. This solution runs in O(n) though. ### A Better Approach Octrees are most commonly used to partition a three-dimensional space by recursively subdividing it into 8 regions. Let's see how we can use an Octree to store some values. Each node in the tree represents a box-like region. Leaf nodes store a single point in that region with an array of objects assigned to that point. Once an object within the same region (but at a different point) is added the leaf node turns into an internal node and 8 child nodes (leaves) are added to it. All points previously contained in the node are passed to its corresponding children and stored. Thus only leaves contain actual points and values. To find the points that lie in a given region we can now traverse the tree from top to bottom and collect the suitable points from nodes. Both adding a point and searching can still take up to O(n) in the worst case, since the tree isn't balanced in any way. However, on average it runs significantly faster (something comparable to O(log n)). ### See also More info on [Wiki](https://en.wikipedia.org/wiki/Octree) Apple's implementation of [GKOctree](https://developer.apple.com/documentation/gameplaykit/gkoctree) *Written for Swift Algorithm Club by Jaap Wijnen* *Heavily inspired by Timur Galimov's Quadtree implementation and Apple's GKOctree implementation ================================================ FILE: Ordered Array/OrderedArray.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play public struct OrderedArray { fileprivate var array = [T]() public init(array: [T]) { self.array = array.sorted() } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public subscript(index: Int) -> T { return array[index] } public mutating func removeAtIndex(index: Int) -> T { return array.remove(at: index) } public mutating func removeAll() { array.removeAll() } public mutating func insert(_ newElement: T) -> Int { let i = findInsertionPoint(newElement) array.insert(newElement, at: i) return i } /* // Slow version that looks at every element in the array. private func findInsertionPoint(newElement: T) -> Int { for i in 0.. Int { var startIndex = 0 var endIndex = array.count while startIndex < endIndex { let midIndex = startIndex + (endIndex - startIndex) / 2 if array[midIndex] == newElement { return midIndex } else if array[midIndex] < newElement { startIndex = midIndex + 1 } else { endIndex = midIndex } } return startIndex } } extension OrderedArray: CustomStringConvertible { public var description: String { return array.description } } var a = OrderedArray(array: [5, 1, 3, 9, 7, -1]) a // [-1, 1, 3, 5, 7, 9] a.insert(4) // inserted at index 3 a // [-1, 1, 3, 4, 5, 7, 9] a.insert(-2) // inserted at index 0 a.insert(10) // inserted at index 8 a // [-2, -1, 1, 3, 4, 5, 7, 9, 10] ================================================ FILE: Ordered Array/OrderedArray.playground/contents.xcplayground ================================================ ================================================ FILE: Ordered Array/OrderedArray.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Ordered Array/OrderedArray.swift ================================================ /* An ordered array. When you add a new item to this array, it is inserted in sorted position. */ public struct OrderedArray { private var array = [T]() public init(array: [T]) { self.array = array.sort() } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public subscript(index: Int) -> T { return array[index] } public mutating func removeAtIndex(index: Int) -> T { return array.removeAtIndex(index) } public mutating func removeAll() { array.removeAll() } public mutating func insert(newElement: T) -> Int { let i = findInsertionPoint(newElement) array.insert(newElement, atIndex: i) return i } private func findInsertionPoint(newElement: T) -> Int { var range = 0.. { fileprivate var array = [T]() public init(array: [T]) { self.array = array.sorted() } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public subscript(index: Int) -> T { return array[index] } public mutating func removeAtIndex(index: Int) -> T { return array.remove(at: index) } public mutating func removeAll() { array.removeAll() } } extension OrderedArray: CustomStringConvertible { public var description: String { return array.description } } ``` As you can see, all these methods simply call the corresponding method on the internal `array` variable. What remains is the `insert()` function. Here is an initial stab at it: ```swift public mutating func insert(_ newElement: T) -> Int { let i = findInsertionPoint(newElement) array.insert(newElement, at: i) return i } private func findInsertionPoint(_ newElement: T) -> Int { for i in 0.. **Note:** Quite conveniently, `array.insert(... atIndex: array.count)` adds the new object to the end of the array, so if no suitable insertion point was found we can simply return `array.count` as the index. Here's how you can test it in a playground: ```swift var a = OrderedArray(array: [5, 1, 3, 9, 7, -1]) a // [-1, 1, 3, 5, 7, 9] a.insert(4) // inserted at index 3 a // [-1, 1, 3, 4, 5, 7, 9] a.insert(-2) // inserted at index 0 a.insert(10) // inserted at index 8 a // [-2, -1, 1, 3, 4, 5, 7, 9, 10] ``` The array's contents will always be sorted from low to high, now matter what. Unfortunately, the current `findInsertionPoint()` function is a bit slow. In the worst case, it needs to scan through the entire array. We can speed this up by using a [binary search](../Binary%20Search) to find the insertion point. Here is the new version: ```swift private func findInsertionPoint(_ newElement: T) -> Int { var startIndex = 0 var endIndex = array.count while startIndex < endIndex { let midIndex = startIndex + (endIndex - startIndex) / 2 if array[midIndex] == newElement { return midIndex } else if array[midIndex] < newElement { startIndex = midIndex + 1 } else { endIndex = midIndex } } return startIndex } ``` The big difference with a regular binary search is that this doesn't return `nil` when the value can't be found, but the array index where the element would have been. That's where we insert the new object. Note that using binary search doesn't change the worst-case running time complexity of `insert()`. The binary search itself takes only **O(log n)** time, but inserting a new object in the middle of an array still involves shifting all remaining elements in memory. So overall, the time complexity is still **O(n)**. But in practice this new version definitely is a lot faster, especially on large arrays. A more complete and production ready [SortedArray](https://github.com/ole/SortedArray) is avalible from [Ole Begemann](https://github.com/ole). The [accompanying article](https://oleb.net/blog/2017/02/sorted-array/) explains the advantages and tradeoffs. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Ordered Set/OrderedSet.playground/Contents.swift ================================================ let s = OrderedSet() s.add(1) s.add(2) s.add(-1) s.add(0) s.insert(4, at: 3) print(s.all()) // [1, 2, -1, 4, 0] s.set(-1, at: 0) // We already have -1 in index: 2, so we will do nothing here print(s.all()) // [1, 2, -1, 4, 0] s.remove(-1) print(s.all()) // [1, 2, 4, 0] print(s.object(at: 1)) // 2 print(s.object(at: 2)) // 4 ================================================ FILE: Ordered Set/OrderedSet.playground/Sources/OrderedSet.swift ================================================ public class OrderedSet { private var objects: [T] = [] private var indexOfKey: [T: Int] = [:] public init() {} // O(1) public func add(_ object: T) { guard indexOfKey[object] == nil else { return } objects.append(object) indexOfKey[object] = objects.count - 1 } // O(n) public func insert(_ object: T, at index: Int) { assert(index < objects.count, "Index should be smaller than object count") assert(index >= 0, "Index should be bigger than 0") guard indexOfKey[object] == nil else { return } objects.insert(object, at: index) indexOfKey[object] = index for i in index+1.. T { assert(index < objects.count, "Index should be smaller than object count") assert(index >= 0, "Index should be bigger than 0") return objects[index] } // O(1) public func set(_ object: T, at index: Int) { assert(index < objects.count, "Index should be smaller than object count") assert(index >= 0, "Index should be bigger than 0") guard indexOfKey[object] == nil else { return } indexOfKey.removeValue(forKey: objects[index]) indexOfKey[object] = index objects[index] = object } // O(1) public func indexOf(_ object: T) -> Int { return indexOfKey[object] ?? -1 } // O(n) public func remove(_ object: T) { guard let index = indexOfKey[object] else { return } indexOfKey.removeValue(forKey: object) objects.remove(at: index) for i in index.. [T] { return objects } } ================================================ FILE: Ordered Set/OrderedSet.playground/contents.xcplayground ================================================ ================================================ FILE: Ordered Set/OrderedSet.swift ================================================ public class OrderedSet { private var objects: [T] = [] private var indexOfKey: [T: Int] = [:] public init() {} // O(1) public func add(_ object: T) { guard indexOfKey[object] == nil else { return } objects.append(object) indexOfKey[object] = objects.count - 1 } // O(n) public func insert(_ object: T, at index: Int) { assert(index < objects.count, "Index should be smaller than object count") assert(index >= 0, "Index should be bigger than 0") guard indexOfKey[object] == nil else { return } objects.insert(object, at: index) indexOfKey[object] = index for i in index+1.. T { assert(index < objects.count, "Index should be smaller than object count") assert(index >= 0, "Index should be bigger than 0") return objects[index] } // O(1) public func set(_ object: T, at index: Int) { assert(index < objects.count, "Index should be smaller than object count") assert(index >= 0, "Index should be bigger than 0") guard indexOfKey[object] == nil else { return } indexOfKey.removeValue(forKey: objects[index]) indexOfKey[object] = index objects[index] = object } // O(1) public func indexOf(_ object: T) -> Int { return indexOfKey[object] ?? -1 } // O(n) public func remove(_ object: T) { guard let index = indexOfKey[object] else { return } indexOfKey.removeValue(forKey: object) objects.remove(at: index) for i in index.. [T] { return objects } } ================================================ FILE: Ordered Set/README.markdown ================================================ # Ordered Set Let's look into how to implement [Ordered Set](https://developer.apple.com/documentation/foundation/nsorderedset). Here is the example about how it works ```swift let s = AppleOrderedSet() s.add(1) s.add(2) s.add(-1) s.add(0) s.insert(4, at: 3) print(s.all()) // [1, 2, -1, 4, 0] s.set(-1, at: 0) // We already have -1 in index: 2, so we will do nothing here print(s.all()) // [1, 2, -1, 4, 0] s.remove(-1) print(s.all()) // [1, 2, 4, 0] print(s.object(at: 1)) // 2 print(s.object(at: 2)) // 4 ``` The significant difference is the the array is not sorted. The elements in the array are the same when insert them. Image the array without duplicates and with `O(logn)` or `O(1)` search time. The idea here is using a data structure to provide `O(1)` or `O(logn)` time complexity, so it's easy to think about hash table. ```swift var indexOfKey: [T: Int] var objects: [T] ``` `indexOfKey` is used to track the index of the element. `objects` is array holding elements. We will go through some key functions details here. ### Add Update `indexOfKey` and insert element in the end of `objects` ```swift // O(1) public func add(_ object: T) { guard indexOfKey[object] == nil else { return } objects.append(object) indexOfKey[object] = objects.count - 1 } ``` ### Insert Insert in a random place of the array will cost `O(n)` time. ```swift // O(n) public func insert(_ object: T, at index: Int) { assert(index < objects.count, "Index should be smaller than object count") assert(index >= 0, "Index should be bigger than 0") guard indexOfKey[object] == nil else { return } objects.insert(object, at: index) indexOfKey[object] = index for i in index+1..= 0, "Index should be bigger than 0") guard indexOfKey[object] == nil else { return } indexOfKey.removeValue(forKey: objects[index]) indexOfKey[object] = index objects[index] = object } ``` ### Remove Remove element in the array will cost `O(n)`. At the same time, we need to update all elements's index after the removed element. ```swift // O(n) public func remove(_ object: T) { guard let index = indexOfKey[object] else { return } indexOfKey.removeValue(forKey: object) objects.remove(at: index) for i in index.. Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.count if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } return false } /** Compares a strings left side character against right side character following - parameter str: The string to compare characters of - parameter left: Index of left side to compare, must be less than or equal to right - parameter right: Index of right side to compare, must be greater than or equal to left - returns: `true` if left side and right side have all been compared and they all match, `false` if a left and right aren't equal */ private func palindrome(_ str: String, left: Int, right: Int) -> Bool { if left >= right { return true } let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { return false } return palindrome(str, left: left + 1, right: right - 1) } ================================================ FILE: Palindromes/Palindromes.playground/contents.xcplayground ================================================ ================================================ FILE: Palindromes/Palindromes.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Palindromes/Palindromes.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Palindromes/README.markdown ================================================ # Palindromes A palindrome is a word or phrase that is spelled the exact same when reading it forwards or backward. Palindromes are allowed to be lowercase or uppercase, contain spaces, punctuation, and word dividers. Algorithms that check for palindromes are a common programming interview question. ## Example The word racecar is a valid palindrome, as it is a word spelled the same when backgrounds and forwards. The examples below shows valid cases of the palindrome `racecar`. ``` raceCar r a c e c a r r?a?c?e?c?a?r? RACEcar ``` ## Algorithm To check for palindromes, a string's characters are compared starting from the beginning and end then moving inward toward the middle of the string while maintaining the same distance apart. In this implementation of a palindrome algorithm, recursion is used to check each of the characters on the left-hand side and right-hand side moving inward. ## The code Here is a recursive implementation of this in Swift: ```swift func isPalindrome(_ str: String) -> Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.count if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } return false } private func palindrome(_ str: String, left: Int, right: Int) -> Bool { if left >= right { return true } let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { return false } return palindrome(str, left: left + 1, right: right - 1) } ``` This algorithm has a two-step process. 1. The first step is to pass the string to validate as a palindrome into the `isPalindrome` method. This method first removes occurrences of non-word pattern matches `\W` [Regex reference](http://regexr.com). It is written with two \\ to escape the \ in the String literal. ```swift let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) ``` The length of the string is then checked to make sure that the string after being stripped of non-word characters is still in a valid length. It is then passed into the next step after being lowercased. 2. The second step is to pass the string in a recursive method. This method takes a string, a left index, and a right index. The method checks the characters of the string using the indexes to compare each character on both sides. The method checks if the left is greater or equal to the right if so the entire string has been run through without returning false so the string is equal on both sides thus returning true. ```swift if left >= right { return true } ``` If the check doesn't pass it continues to get the characters at the specified indexes and compare each. If they are not the same the method returns false and exits. ```swift let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { return false } ``` If they are the same the method calls itself again and updates the indexes accordingly to continue to check the rest of the string. ```swift return palindrome(str, left: left + 1, right: right - 1) ``` Step 1: `race?C ar -> raceCar -> racecar` Step 2: ``` | | racecar -> r == r | | racecar -> a == a | | racecar -> c == c | racecar -> left index == right index -> return true ``` ## Additional Resources [Palindrome Wikipedia](https://en.wikipedia.org/wiki/Palindrome) *Written by [Joshua Alvarado](https://github.com/lostatseajoshua)* ================================================ FILE: Palindromes/Test/Palindrome.swift ================================================ import Foundation func isPalindrome(_ str: String) -> Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.count if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } return false } private func palindrome(_ str: String, left: Int, right: Int) -> Bool { if left >= right { return true } let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { return false } return palindrome(str, left: left + 1, right: right - 1) } ================================================ FILE: Palindromes/Test/Test/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Palindromes/Test/Test/Test.swift ================================================ // // PalindromeTests.swift // Test // // Created by Joshua Alvarado on 12/23/16. // Copyright © 2016 Joshua Alvarado. All rights reserved. // import XCTest class PalindromeTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testExample() { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. } func testPerformanceExample() { // This is an example of a performance test case. self.measure { // Put the code you want to measure the time of here. _ = isPalindrome("abbcbba") _ = isPalindrome("asdkfaksjdfasjkdfhaslkjdfakjsdfhakljsdhflkjasdfhkasdjhfklajsdfhkljasdf") _ = isPalindrome("abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa") } } func testPalindromeWord() { XCTAssertTrue(isPalindrome("abbcbba")) XCTAssertTrue(isPalindrome("racecar")) } func testPalindromeSentence() { XCTAssertTrue(isPalindrome("A man, a plan, a canal, Panama!")) XCTAssertTrue(isPalindrome("Madam, I'm Adam")) XCTAssertTrue(isPalindrome("Madam in Eden, I'm Adam")) XCTAssertTrue(isPalindrome("In girum imus nocte et consumimur igni")) XCTAssertTrue(isPalindrome("Never odd or even")) } func testPalindromeNumber() { XCTAssertTrue(isPalindrome("5885")) XCTAssertTrue(isPalindrome("5 8 8 5")) XCTAssertTrue(isPalindrome("58 85")) } func testSpecialCharacters() { XCTAssertTrue(isPalindrome("৯৯")) } func testNonPalindromes() { XCTAssertFalse(isPalindrome("\\\\")) XCTAssertFalse(isPalindrome("desserts")) XCTAssertFalse(isPalindrome("😀😀")) XCTAssertFalse(isPalindrome("")) XCTAssertFalse(isPalindrome("a")) XCTAssertFalse(isPalindrome("power")) } } ================================================ FILE: Palindromes/Test/Test.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 9437D8841E0D960A00A38FB8 /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437D8831E0D960A00A38FB8 /* Test.swift */; }; 9437D88B1E0D969500A38FB8 /* Palindrome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437D8791E0D948A00A38FB8 /* Palindrome.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 9437D8791E0D948A00A38FB8 /* Palindrome.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palindrome.swift; sourceTree = ""; }; 9437D8811E0D960A00A38FB8 /* Test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Test.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 9437D8831E0D960A00A38FB8 /* Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Test.swift; sourceTree = ""; }; 9437D8851E0D960A00A38FB8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 9437D87E1E0D960A00A38FB8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 9437D8651E0D945200A38FB8 = { isa = PBXGroup; children = ( 9437D8791E0D948A00A38FB8 /* Palindrome.swift */, 9437D8821E0D960A00A38FB8 /* Test */, 9437D86F1E0D945200A38FB8 /* Products */, ); sourceTree = ""; }; 9437D86F1E0D945200A38FB8 /* Products */ = { isa = PBXGroup; children = ( 9437D8811E0D960A00A38FB8 /* Test.xctest */, ); name = Products; sourceTree = ""; }; 9437D8821E0D960A00A38FB8 /* Test */ = { isa = PBXGroup; children = ( 9437D8831E0D960A00A38FB8 /* Test.swift */, 9437D8851E0D960A00A38FB8 /* Info.plist */, ); path = Test; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 9437D8801E0D960A00A38FB8 /* Test */ = { isa = PBXNativeTarget; buildConfigurationList = 9437D8861E0D960A00A38FB8 /* Build configuration list for PBXNativeTarget "Test" */; buildPhases = ( 9437D87D1E0D960A00A38FB8 /* Sources */, 9437D87E1E0D960A00A38FB8 /* Frameworks */, 9437D87F1E0D960A00A38FB8 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Test; productName = Test; productReference = 9437D8811E0D960A00A38FB8 /* Test.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 9437D8661E0D945200A38FB8 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0820; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Joshua Alvarado"; TargetAttributes = { 9437D8801E0D960A00A38FB8 = { CreatedOnToolsVersion = 8.2; LastSwiftMigration = 1000; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 9437D8691E0D945200A38FB8 /* Build configuration list for PBXProject "Test" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 9437D8651E0D945200A38FB8; productRefGroup = 9437D86F1E0D945200A38FB8 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 9437D8801E0D960A00A38FB8 /* Test */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 9437D87F1E0D960A00A38FB8 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 9437D87D1E0D960A00A38FB8 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 9437D88B1E0D969500A38FB8 /* Palindrome.swift in Sources */, 9437D8841E0D960A00A38FB8 /* Test.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 9437D8721E0D945200A38FB8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; 9437D8731E0D945200A38FB8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; }; name = Release; }; 9437D8871E0D960A00A38FB8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Test/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_BUNDLE_IDENTIFIER = self.edu.Test; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Debug; }; 9437D8881E0D960A00A38FB8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Test/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_BUNDLE_IDENTIFIER = self.edu.Test; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 9437D8691E0D945200A38FB8 /* Build configuration list for PBXProject "Test" */ = { isa = XCConfigurationList; buildConfigurations = ( 9437D8721E0D945200A38FB8 /* Debug */, 9437D8731E0D945200A38FB8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 9437D8861E0D960A00A38FB8 /* Build configuration list for PBXNativeTarget "Test" */ = { isa = XCConfigurationList; buildConfigurations = ( 9437D8871E0D960A00A38FB8 /* Debug */, 9437D8881E0D960A00A38FB8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 9437D8661E0D945200A38FB8 /* Project object */; } ================================================ FILE: Palindromes/Test/Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Palindromes/Test/Test.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme ================================================ ================================================ FILE: Points Lines Planes/Points Lines Planes/2D/Line2D.swift ================================================ // // Line2D.swift // Points Lines Planes // // Created by Jaap Wijnen on 24-10-17. // struct Line2D: Equatable { var slope: Slope var offset: Double var direction: Direction enum Slope: Equatable { case finite(slope: Double) case infinite(offset: Double) } enum Direction: Equatable { case increasing case decreasing } init(from p1: Point2D, to p2: Point2D) { if p1 == p2 { fatalError("Points can not be equal when creating a line between them") } if p1.x == p2.x { self.slope = .infinite(offset: p1.x) self.offset = 0 self.direction = p1.y < p2.y ? .increasing : .decreasing return } let slope = (p1.y - p2.y)/(p1.x - p2.x) self.slope = .finite(slope: slope) offset = (p1.y + p2.y - slope * (p1.x + p2.x))/2 if slope >= 0 { // so a horizontal line going left to right is called increasing self.direction = p1.x < p2.x ? .increasing : .decreasing } else { self.direction = p1.x < p2.x ? .decreasing : .increasing } } fileprivate init(slope: Slope, offset: Double, direction: Direction) { self.slope = slope self.offset = offset self.direction = direction } // returns y coordinate on line for given x func y(at x: Double) -> Double { switch self.slope { case .finite(let slope): return slope * x + self.offset case .infinite: fatalError("y can be anywhere on vertical line") } } // returns x coordinate on line for given y func x(at y: Double) -> Double { switch self.slope { case .finite(let slope): if slope == 0 { fatalError("x can be anywhere on horizontal line") } return (y - self.offset)/slope case .infinite(let offset): return offset } } // finds intersection point between two lines. returns nil when lines don't intersect or lie on top of each other. func intersect(with line: Line2D) -> Point2D? { if self == line { return nil } switch (self.slope, line.slope) { case (.infinite, .infinite): // lines are either parallel or on top of each other. return nil case (.finite(let slope1), .finite(let slope2)): if slope1 == slope2 { return nil } // lines are parallel // lines are not parallel calculate intersection point let x = (line.offset - self.offset)/(slope1 - slope2) let y = (slope1 + slope2) * x + self.offset + line.offset return Point2D(x: x, y: y) case (.infinite(let offset), .finite): // one line is vertical so we only check what y value the other line has at that point let x = offset let y = line.y(at: x) return Point2D(x: x, y: y) case (.finite, .infinite(let offset)): // one line is vertical so we only check what y value the other line has at that point // lines are switched with respect to case above this one let x = offset let y = self.y(at: x) return Point2D(x: x, y: y) } } // returns a line perpendicular to self at the given y coordinate // direction of perpendicular lines always changes clockwise func perpendicularLineAt(y: Double) -> Line2D { return perpendicularLineAt(p: Point2D(x: self.x(at: y), y: y)) } // returns a line perpendicular to self at the given x coordinate // direction of perpendicular lines always changes clockwise func perpendicularLineAt(x: Double) -> Line2D { return perpendicularLineAt(p: Point2D(x: x, y: self.y(at: x))) } private func perpendicularLineAt(p: Point2D) -> Line2D { switch self.slope { case .finite(let slope): if slope == 0 { // line is horizontal so new line will be vertical let dir: Direction = self.direction == .increasing ? .decreasing : .increasing return Line2D(slope: .infinite(offset: p.x), offset: 0, direction: dir) } // line is neither horizontal nor vertical // we make a new line through the point p with new slope -1/slope let offset = (slope + 1/slope)*p.x + self.offset // determine direction of new line based on direction of the old line and its slope let dir: Direction switch self.direction { case .increasing: dir = slope > 0 ? .decreasing : .increasing case .decreasing: dir = slope > 0 ? .increasing : .decreasing } return Line2D(slope: .finite(slope: -1/slope), offset: offset, direction: dir) case .infinite: // line is vertical so new line will be horizontal let dir: Direction = self.direction == .increasing ? .increasing : .decreasing return Line2D(slope: .finite(slope: 0), offset: p.y, direction: dir) } } } ================================================ FILE: Points Lines Planes/Points Lines Planes/2D/Point2D.swift ================================================ // // Point2D.swift // Points Lines Planes // // Created by Jaap Wijnen on 24-10-17. // struct Point2D: Equatable { var x: Double var y: Double // returns true if point is on or right of line func isRight(of line: Line2D) -> Bool { switch line.slope { case .finite: let y = line.y(at: self.x) switch line.direction { case .increasing: return y >= self.y case .decreasing: return y <= self.y } case .infinite(let offset): switch line.direction { case .increasing: return self.x >= offset case .decreasing: return self.x <= offset } } } func isLeft(of line: Line2D) -> Bool { return !self.isRight(of: line) } } ================================================ FILE: Points Lines Planes/Points Lines Planes/main.swift ================================================ // // main.swift // Points Lines Planes // // Created by Jaap Wijnen on 23-10-17. // let p0 = Point2D(x: 0, y: 2) let p1 = Point2D(x: 1, y: 1) let p2 = Point2D(x: 1, y: 3) let p3 = Point2D(x: 3, y: 1) let p4 = Point2D(x: 3, y: 3) let horLine = Line2D(from: p1, to: p3) let verLine = Line2D(from: p1, to: p2) let line45 = Line2D(from: p1, to: p4) print(horLine.intersect(with: verLine)) print(p0.isRight(of: line45)) print(p0.isRight(of: horLine)) print(p0.isRight(of: verLine)) let lineperp = horLine.perpendicularLineAt(x: 2) print(lineperp) ================================================ FILE: Points Lines Planes/Points Lines Planes.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 48; objects = { /* Begin PBXBuildFile section */ 8EA8A3BB1F9F7B6300FD8BC0 /* Point2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EA8A3BA1F9F7B6300FD8BC0 /* Point2D.swift */; }; 8EA8A3BD1F9F7B7100FD8BC0 /* Line2D.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EA8A3BC1F9F7B7100FD8BC0 /* Line2D.swift */; }; 8EF612481F9E00E000267358 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EF612471F9E00E000267358 /* main.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 8EF612421F9E00E000267358 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 8EA8A3BA1F9F7B6300FD8BC0 /* Point2D.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Point2D.swift; sourceTree = ""; }; 8EA8A3BC1F9F7B7100FD8BC0 /* Line2D.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line2D.swift; sourceTree = ""; }; 8EF612441F9E00E000267358 /* Points Lines Planes */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "Points Lines Planes"; sourceTree = BUILT_PRODUCTS_DIR; }; 8EF612471F9E00E000267358 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 8EF612411F9E00E000267358 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 8EA8A3C21F9F7C9000FD8BC0 /* 2D */ = { isa = PBXGroup; children = ( 8EA8A3BA1F9F7B6300FD8BC0 /* Point2D.swift */, 8EA8A3BC1F9F7B7100FD8BC0 /* Line2D.swift */, ); path = 2D; sourceTree = ""; }; 8EF6123B1F9E00DF00267358 = { isa = PBXGroup; children = ( 8EF612461F9E00E000267358 /* Points Lines Planes */, 8EF612451F9E00E000267358 /* Products */, ); sourceTree = ""; }; 8EF612451F9E00E000267358 /* Products */ = { isa = PBXGroup; children = ( 8EF612441F9E00E000267358 /* Points Lines Planes */, ); name = Products; sourceTree = ""; }; 8EF612461F9E00E000267358 /* Points Lines Planes */ = { isa = PBXGroup; children = ( 8EF612471F9E00E000267358 /* main.swift */, 8EA8A3C21F9F7C9000FD8BC0 /* 2D */, ); path = "Points Lines Planes"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 8EF612431F9E00E000267358 /* Points Lines Planes */ = { isa = PBXNativeTarget; buildConfigurationList = 8EF6124B1F9E00E000267358 /* Build configuration list for PBXNativeTarget "Points Lines Planes" */; buildPhases = ( 8EF612401F9E00E000267358 /* Sources */, 8EF612411F9E00E000267358 /* Frameworks */, 8EF612421F9E00E000267358 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = "Points Lines Planes"; productName = "Points Lines Planes"; productReference = 8EF612441F9E00E000267358 /* Points Lines Planes */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 8EF6123C1F9E00DF00267358 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0900; LastUpgradeCheck = 0900; ORGANIZATIONNAME = Workmoose; TargetAttributes = { 8EF612431F9E00E000267358 = { CreatedOnToolsVersion = 9.0.1; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 8EF6123F1F9E00DF00267358 /* Build configuration list for PBXProject "Points Lines Planes" */; compatibilityVersion = "Xcode 8.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 8EF6123B1F9E00DF00267358; productRefGroup = 8EF612451F9E00E000267358 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 8EF612431F9E00E000267358 /* Points Lines Planes */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 8EF612401F9E00E000267358 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 8EA8A3BB1F9F7B6300FD8BC0 /* Point2D.swift in Sources */, 8EF612481F9E00E000267358 /* main.swift in Sources */, 8EA8A3BD1F9F7B7100FD8BC0 /* Line2D.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 8EF612491F9E00E000267358 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.13; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 8EF6124A1F9E00E000267358 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.13; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 8EF6124C1F9E00E000267358 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 7C4LVS3ZVC; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; }; 8EF6124D1F9E00E000267358 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 7C4LVS3ZVC; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 8EF6123F1F9E00DF00267358 /* Build configuration list for PBXProject "Points Lines Planes" */ = { isa = XCConfigurationList; buildConfigurations = ( 8EF612491F9E00E000267358 /* Debug */, 8EF6124A1F9E00E000267358 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 8EF6124B1F9E00E000267358 /* Build configuration list for PBXNativeTarget "Points Lines Planes" */ = { isa = XCConfigurationList; buildConfigurations = ( 8EF6124C1F9E00E000267358 /* Debug */, 8EF6124D1F9E00E000267358 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 8EF6123C1F9E00DF00267358 /* Project object */; } ================================================ FILE: Points Lines Planes/Points Lines Planes.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Points Lines Planes/README.md ================================================ # Points Lines (Planes) This implements data structures for points lines and planes(not yet) in (for now) 2D space and a few functions to play around with them. This was originally written to improve on the Convex Hull algorithm but I thought it might be a nice addition in itself. Im planning to add 3D implementations as well. # implementation Two `struct`s are implemented the `Point2D` and `Line2D`. ``` struct Point2D: { var x: Double var y: double } ``` ``` struct Line2D { var slope: Slope var offset: Double var direction: Direction } ``` Here `Slope` is an enum to account for vertical lines. slope is infinite for vertical lines, offset is the x coordinate where the line crosses the line `y=0`. slope is finite for any other line and contains a double with the actual value of the slope. ``` enum Slope { case finite(slope: Double) case infinite(offset: Double) } ``` `Line2D` also contains a `Direction` enum. This is introduced in order to make lines directional in order to be able to determine what is left and right of a certain line. It is `.increasing` if the line points in positive y direction and `.decreasing` if it points in the negative y direction. `Line2D`'s offset is the the y-coordinate where the line crosses the vertical `x=0` line. *Written for the Swift Algorithm Club by Jaap Wijnen.* ================================================ FILE: Priority Queue/PriorityQueue.swift ================================================ /* Priority Queue, a queue where the most "important" items are at the front of the queue. The heap is a natural data structure for a priority queue, so this object simply wraps the Heap struct. All operations are O(lg n). Just like a heap can be a max-heap or min-heap, the queue can be a max-priority queue (largest element first) or a min-priority queue (smallest element first). */ public struct PriorityQueue { fileprivate var heap: Heap /* To create a max-priority queue, supply a > sort function. For a min-priority queue, use <. */ public init(sort: @escaping (T, T) -> Bool) { heap = Heap(sort: sort) } public var isEmpty: Bool { return heap.isEmpty } public var count: Int { return heap.count } public func peek() -> T? { return heap.peek() } public mutating func enqueue(_ element: T) { heap.insert(element) } public mutating func dequeue() -> T? { return heap.remove() } /* Allows you to change the priority of an element. In a max-priority queue, the new priority should be larger than the old one; in a min-priority queue it should be smaller. */ public mutating func changePriority(index i: Int, value: T) { return heap.replace(index: i, value: value) } } extension PriorityQueue where T: Equatable { public func index(of element: T) -> Int? { return heap.index(of: element) } } ================================================ FILE: Priority Queue/README.markdown ================================================ # Priority Queue A priority queue is a [queue](../Queue/) where the most important element is always at the front. The queue can be a *max-priority* queue (largest element first) or a *min-priority* queue (smallest element first). ## Why use a priority queue? Priority queues are useful for algorithms that need to process a (large) number of items and where you repeatedly need to identify which one is now the biggest or smallest -- or however you define "most important". Examples of algorithms that can benefit from a priority queue: - Event-driven simulations. Each event is given a timestamp and you want events to be performed in order of their timestamps. The priority queue makes it easy to find the next event that needs to be simulated. - Dijkstra's algorithm for graph searching uses a priority queue to calculate the minimum cost. - [Huffman coding](../Huffman%20Coding/) for data compression. This algorithm builds up a compression tree. It repeatedly needs to find the two nodes with the smallest frequencies that do not have a parent node yet. - A* pathfinding for artificial intelligence. - Lots of other places! With a regular queue or plain old array you'd need to scan the entire sequence over and over to find the next largest item. A priority queue is optimized for this sort of thing. ## What can you do with a priority queue? Common operations on a priority queue: - **Enqueue**: inserts a new element into the queue. - **Dequeue**: removes and returns the queue's most important element. - **Find Minimum** or **Find Maximum**: returns the most important element but does not remove it. - **Change Priority**: for when your algorithm decides that an element has become more important while it's already in the queue. ## How to implement a priority queue There are different ways to implement priority queues: - As a [sorted array](../Ordered%20Array/). The most important item is at the end of the array. Downside: inserting new items is slow because they must be inserted in sorted order. - As a balanced [binary search tree](../Binary%20Search%20Tree/). This is great for making a double-ended priority queue because it implements both "find minimum" and "find maximum" efficiently. - As a [heap](../Heap/). The heap is a natural data structure for a priority queue. In fact, the two terms are often used as synonyms. A heap is more efficient than a sorted array because a heap only has to be partially sorted. All heap operations are **O(log n)**. Here's a Swift priority queue based on a heap: ```swift public struct PriorityQueue { fileprivate var heap: Heap public init(sort: (T, T) -> Bool) { heap = Heap(sort: sort) } public var isEmpty: Bool { return heap.isEmpty } public var count: Int { return heap.count } public func peek() -> T? { return heap.peek() } public mutating func enqueue(element: T) { heap.insert(element) } public mutating func dequeue() -> T? { return heap.remove() } public mutating func changePriority(index i: Int, value: T) { return heap.replace(index: i, value: value) } } ``` As you can see, there's nothing much to it. Making a priority queue is easy if you have a [heap](../Heap/) because a heap *is* pretty much a priority queue. ## See also [Priority Queue on Wikipedia](https://en.wikipedia.org/wiki/Priority_queue) *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Priority Queue/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Priority Queue/Tests/PriorityQueueTests.swift ================================================ import Foundation import XCTest private struct Message { let text: String let priority: Int } private func < (m1: Message, m2: Message) -> Bool { return m1.priority < m2.priority } class PriorityQueueTest: XCTestCase { func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testEmpty() { var queue = PriorityQueue(sort: <) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.peek()) XCTAssertNil(queue.dequeue()) } func testOneElement() { var queue = PriorityQueue(sort: <) queue.enqueue(Message(text: "hello", priority: 100)) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.peek()!.priority, 100) let result = queue.dequeue() XCTAssertEqual(result!.priority, 100) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.peek()) } func testTwoElementsInOrder() { var queue = PriorityQueue(sort: <) queue.enqueue(Message(text: "hello", priority: 100)) queue.enqueue(Message(text: "world", priority: 200)) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 2) XCTAssertEqual(queue.peek()!.priority, 100) let result1 = queue.dequeue() XCTAssertEqual(result1!.priority, 100) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.peek()!.priority, 200) let result2 = queue.dequeue() XCTAssertEqual(result2!.priority, 200) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.peek()) } func testTwoElementsOutOfOrder() { var queue = PriorityQueue(sort: <) queue.enqueue(Message(text: "world", priority: 200)) queue.enqueue(Message(text: "hello", priority: 100)) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 2) XCTAssertEqual(queue.peek()!.priority, 100) let result1 = queue.dequeue() XCTAssertEqual(result1!.priority, 100) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.peek()!.priority, 200) let result2 = queue.dequeue() XCTAssertEqual(result2!.priority, 200) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertNil(queue.peek()) } } ================================================ FILE: Priority Queue/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3FC1C77A658003CECC7 /* PriorityQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3FB1C77A658003CECC7 /* PriorityQueue.swift */; }; 7B80C3FE1C77A65E003CECC7 /* PriorityQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3FD1C77A65E003CECC7 /* PriorityQueueTests.swift */; }; 7B80C4001C77A67B003CECC7 /* Heap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3FF1C77A67B003CECC7 /* Heap.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3FB1C77A658003CECC7 /* PriorityQueue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PriorityQueue.swift; path = ../PriorityQueue.swift; sourceTree = SOURCE_ROOT; }; 7B80C3FD1C77A65E003CECC7 /* PriorityQueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PriorityQueueTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3FF1C77A67B003CECC7 /* Heap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Heap.swift; path = ../../Heap/Heap.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3FF1C77A67B003CECC7 /* Heap.swift */, 7B80C3FB1C77A658003CECC7 /* PriorityQueue.swift */, 7B80C3FD1C77A65E003CECC7 /* PriorityQueueTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0820; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C4001C77A67B003CECC7 /* Heap.swift in Sources */, 7B80C3FE1C77A65E003CECC7 /* PriorityQueueTests.swift in Sources */, 7B80C3FC1C77A658003CECC7 /* PriorityQueue.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Priority Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: QuadTree/QuadTree.playground/Contents.swift ================================================ import Foundation let tree = QuadTree(rect: Rect(origin: Point(0, 0), size: Size(xLength: 10, yLength: 10))) for _ in 0..<40 { let randomX = Double(arc4random_uniform(100)) / 10 let randomY = Double(arc4random_uniform(100)) / 10 let point = Point(randomX, randomY) tree.add(point: point) } print(tree) print(tree.points(inRect: Rect(origin: Point(1, 1), size: Size(xLength: 5, yLength: 5)))) ================================================ FILE: QuadTree/QuadTree.playground/Sources/QuadTree.swift ================================================ public struct Point { let x: Double let y: Double public init(_ x: Double, _ y: Double) { self.x = x self.y = y } } extension Point: CustomStringConvertible { public var description: String { return "Point(\(x), \(y))" } } public struct Size: CustomStringConvertible { var xLength: Double var yLength: Double public init(xLength: Double, yLength: Double) { precondition(xLength >= 0, "xLength can not be negative") precondition(yLength >= 0, "yLength can not be negative") self.xLength = xLength self.yLength = yLength } var half: Size { return Size(xLength: xLength / 2, yLength: yLength / 2) } public var description: String { return "Size(\(xLength), \(yLength))" } } public struct Rect { // left top vertice var origin: Point var size: Size public init(origin: Point, size: Size) { self.origin = origin self.size = size } var minX: Double { return origin.x } var minY: Double { return origin.y } var maxX: Double { return origin.x + size.xLength } var maxY: Double { return origin.y + size.yLength } func containts(point: Point) -> Bool { return (minX <= point.x && point.x <= maxX) && (minY <= point.y && point.y <= maxY) } var leftTopRect: Rect { return Rect(origin: origin, size: size.half) } var leftBottomRect: Rect { return Rect(origin: Point(origin.x, origin.y + size.half.yLength), size: size.half) } var rightTopRect: Rect { return Rect(origin: Point(origin.x + size.half.xLength, origin.y), size: size.half) } var rightBottomRect: Rect { return Rect(origin: Point(origin.x + size.half.xLength, origin.y + size.half.yLength), size: size.half) } func intersects(rect: Rect) -> Bool { func lineSegmentsIntersect(lStart: Double, lEnd: Double, rStart: Double, rEnd: Double) -> Bool { return max(lStart, rStart) <= min(lEnd, rEnd) } // to intersect, both horizontal and vertical projections need to intersect // horizontal if !lineSegmentsIntersect(lStart: minX, lEnd: maxX, rStart: rect.minX, rEnd: rect.maxX) { return false } // vertical return lineSegmentsIntersect(lStart: minY, lEnd: maxY, rStart: rect.minY, rEnd: rect.maxY) } } extension Rect: CustomStringConvertible { public var description: String { return "Rect(\(origin), \(size))" } } protocol PointsContainer { func add(point: Point) -> Bool func points(inRect rect: Rect) -> [Point] } class QuadTreeNode { enum NodeType { case leaf case `internal`(children: Children) } struct Children: Sequence { let leftTop: QuadTreeNode let leftBottom: QuadTreeNode let rightTop: QuadTreeNode let rightBottom: QuadTreeNode init(parentNode: QuadTreeNode) { leftTop = QuadTreeNode(rect: parentNode.rect.leftTopRect) leftBottom = QuadTreeNode(rect: parentNode.rect.leftBottomRect) rightTop = QuadTreeNode(rect: parentNode.rect.rightTopRect) rightBottom = QuadTreeNode(rect: parentNode.rect.rightBottomRect) } struct ChildrenIterator: IteratorProtocol { private var index = 0 private let children: Children init(children: Children) { self.children = children } mutating func next() -> QuadTreeNode? { defer { index += 1 } switch index { case 0: return children.leftTop case 1: return children.leftBottom case 2: return children.rightTop case 3: return children.rightBottom default: return nil } } } public func makeIterator() -> ChildrenIterator { return ChildrenIterator(children: self) } } var points: [Point] = [] let rect: Rect var type: NodeType = .leaf static let maxPointCapacity = 3 init(rect: Rect) { self.rect = rect } var recursiveDescription: String { return recursiveDescription(withTabCount: 0) } private func recursiveDescription(withTabCount count: Int) -> String { let indent = String(repeating: "\t", count: count) var result = "\(indent)" + description + "\n" switch type { case .internal(let children): for child in children { result += child.recursiveDescription(withTabCount: count + 1) } default: break } return result } } extension QuadTreeNode: PointsContainer { @discardableResult func add(point: Point) -> Bool { if !rect.containts(point: point) { return false } switch type { case .internal(let children): // pass the point to one of the children for child in children { if child.add(point: point) { return true } } fatalError("rect.containts evaluted to true, but none of the children added the point") case .leaf: points.append(point) // if the max capacity was reached, become an internal node if points.count == QuadTreeNode.maxPointCapacity { subdivide() } } return true } private func subdivide() { switch type { case .leaf: type = .internal(children: Children(parentNode: self)) case .internal: preconditionFailure("Calling subdivide on an internal node") } } func points(inRect rect: Rect) -> [Point] { // if the node's rect and the given rect don't intersect, return an empty array, // because there can't be any points that lie the node's (or its children's) rect and // in the given rect if !self.rect.intersects(rect: rect) { return [] } var result: [Point] = [] // collect the node's points that lie in the rect for point in points { if rect.containts(point: point) { result.append(point) } } switch type { case .leaf: break case .internal(let children): // recursively add children's points that lie in the rect for childNode in children { result.append(contentsOf: childNode.points(inRect: rect)) } } return result } } extension QuadTreeNode: CustomStringConvertible { var description: String { switch type { case .leaf: return "leaf \(rect) Points: \(points)" case .internal: return "parent \(rect) Points: \(points)" } } } public class QuadTree: PointsContainer { let root: QuadTreeNode public init(rect: Rect) { self.root = QuadTreeNode(rect: rect) } @discardableResult public func add(point: Point) -> Bool { return root.add(point: point) } public func points(inRect rect: Rect) -> [Point] { return root.points(inRect: rect) } } extension QuadTree: CustomStringConvertible { public var description: String { return "Quad tree\n" + root.recursiveDescription } } ================================================ FILE: QuadTree/QuadTree.playground/contents.xcplayground ================================================ ================================================ FILE: QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: QuadTree/README.md ================================================ # QuadTree A quadtree is a [tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Tree) in which each internal (not leaf) node has four children. ### Problem Consider the following problem: your need to store a number of points (each point is a pair of `X` and `Y` coordinates) and then you need to answer which points lie in a certain rectangular region. A naive solution would be to store the points inside an array and then iterate over the points and check each one individually. This solution runs in O(n) though. ### A Better Approach Quadtrees are most commonly used to partition a two-dimensional space by recursively subdividing it into four regions(quadrants). Let's see how we can use a Quadtree to store the points. Each node in the tree represents a rectangular region and stores a limited number(`maxPointCapacity`) of points that all lie in its region. ```swift class QuadTreeNode { enum NodeType { case leaf case `internal`(children: Children) } struct Children { let leftTop: QuadTreeNode let leftBottom: QuadTreeNode let rightTop: QuadTreeNode let rightBottom: QuadTreeNode ... } var points: [Point] = [] let rect: Rect var type: NodeType = .leaf static let maxPointCapacity = 3 init(rect: Rect) { self.rect = rect } ... } ``` Once the limit in a leaf node is reached, four child nodes are added to the node and they represent `topLeft`, `topRight`, `bottomLeft`, `bottomRight` quadrants of the node's rect; each of the consequent points in the rect will be passed to one of the children. Thus, new points are always added to leaf nodes. ```swift extension QuadTreeNode { @discardableResult func add(point: Point) -> Bool { if !rect.contains(point: point) { return false } switch type { case .internal(let children): // pass the point to one of the children for child in children { if child.add(point: point) { return true } } return false // should never happen case .leaf: points.append(point) // if the max capacity was reached, become an internal node if points.count == QuadTreeNode.maxPointCapacity { subdivide() } } return true } private func subdivide() { switch type { case .leaf: type = .internal(children: Children(parentNode: self)) case .internal: preconditionFailure("Calling subdivide on an internal node") } } } extension Children { init(parentNode: QuadTreeNode) { leftTop = QuadTreeNode(rect: parentNode.rect.leftTopRect) leftBottom = QuadTreeNode(rect: parentNode.rect.leftBottomRect) rightTop = QuadTreeNode(rect: parentNode.rect.rightTopRect) rightBottom = QuadTreeNode(rect: parentNode.rect.rightBottomRect) } } ``` To find the points that lie in a given region we can now traverse the tree from top to bottom and collect the suitable points from nodes. ```swift class QuadTree { ... let root: QuadTreeNode public func points(inRect rect: Rect) -> [Point] { return root.points(inRect: rect) } } extension QuadTreeNode { func points(inRect rect: Rect) -> [Point] { // if the node's rect and the given rect don't intersect, return an empty array, // because there can't be any points that lie the node's (or its children's) rect and // in the given rect if !self.rect.intersects(rect: rect) { return [] } var result: [Point] = [] // collect the node's points that lie in the rect for point in points { if rect.contains(point: point) { result.append(point) } } switch type { case .leaf: break case .internal(children: let children): // recursively add children's points that lie in the rect for childNode in children { result.append(contentsOf: childNode.points(inRect: rect)) } } return result } } ``` Both adding a point and searching can still take up to O(n) in the worst case, since the tree isn't balanced in any way. However, on average it runs significantly faster (something comparable to O(log n)). ### See also Displaying a large amount of objects in a MapView - a great use case for a Quadtree ([Thoughtbot Article](https://robots.thoughtbot.com/how-to-handle-large-amounts-of-data-on-maps)) More info on [Wikipedia](https://en.wikipedia.org/wiki/Quadtree) *Written for Swift Algorithm Club by Timur Galimov* ================================================ FILE: QuadTree/Tests/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: QuadTree/Tests/Tests/Tests.swift ================================================ // // Tests.swift // Tests // // Created by Timur Galimov on 12/02/2017. // // import XCTest extension Point: Equatable { } public func == (lhs: Point, rhs: Point) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } class Tests: XCTestCase { func testRectContains() { let rect = Rect(origin: Point(0, 0), size: Size(xLength: 3, yLength: 3)) XCTAssertTrue(rect.containts(point: Point(1, 1))) XCTAssertTrue(rect.containts(point: Point(0, 0))) XCTAssertTrue(rect.containts(point: Point(0, 3))) XCTAssertTrue(rect.containts(point: Point(3, 3))) XCTAssertFalse(rect.containts(point: Point(-1, 1))) XCTAssertFalse(rect.containts(point: Point(-0.1, 0.1))) XCTAssertFalse(rect.containts(point: Point(0, 3.1))) XCTAssertFalse(rect.containts(point: Point(-4, 1))) } func testIntersects() { let rect = Rect(origin: Point(0, 0), size: Size(xLength: 5, yLength: 5)) let rect2 = Rect(origin: Point(1, 1), size: Size(xLength: 1, yLength: 1)) XCTAssertTrue(rect.intersects(rect: rect2)) let rect3 = Rect(origin: Point(1, 0), size: Size(xLength: 1, yLength: 10)) let rect4 = Rect(origin: Point(0, 1), size: Size(xLength: 10, yLength: 1)) XCTAssertTrue(rect3.intersects(rect: rect4)) let rect5 = Rect(origin: Point(0, 0), size: Size(xLength: 4, yLength: 4)) let rect6 = Rect(origin: Point(2, 2), size: Size(xLength: 4, yLength: 4)) XCTAssertTrue(rect5.intersects(rect: rect6)) let rect7 = Rect(origin: Point(0, 0), size: Size(xLength: 4, yLength: 4)) let rect8 = Rect(origin: Point(4, 4), size: Size(xLength: 1, yLength: 1)) XCTAssertTrue(rect7.intersects(rect: rect8)) let rect9 = Rect(origin: Point(-1, -1), size: Size(xLength: 0.5, yLength: 0.5)) let rect10 = Rect(origin: Point(0, 0), size: Size(xLength: 1, yLength: 1)) XCTAssertFalse(rect9.intersects(rect: rect10)) let rect11 = Rect(origin: Point(0, 0), size: Size(xLength: 2, yLength: 1)) let rect12 = Rect(origin: Point(3, 0), size: Size(xLength: 1, yLength: 1)) XCTAssertFalse(rect11.intersects(rect: rect12)) } func testQuadTree() { let rect = Rect(origin: Point(0, 0), size: Size(xLength: 5, yLength: 5)) let qt = QuadTree(rect: rect) XCTAssertTrue(qt.points(inRect: rect) == [Point]()) XCTAssertFalse(qt.add(point: Point(-0.1, 0.1))) XCTAssertTrue(qt.points(inRect: rect) == [Point]()) XCTAssertTrue(qt.add(point: Point(1, 1))) XCTAssertTrue(qt.add(point: Point(3, 3))) XCTAssertTrue(qt.add(point: Point(4, 4))) XCTAssertTrue(qt.add(point: Point(0.5, 0.5))) XCTAssertFalse(qt.add(point: Point(5.5, 0))) XCTAssertFalse(qt.add(point: Point(5.5, 1))) XCTAssertFalse(qt.add(point: Point(5.5, 2))) XCTAssertTrue(qt.add(point: Point(1.5, 1.5))) let rect2 = Rect(origin: Point(0, 0), size: Size(xLength: 2, yLength: 2)) XCTAssertTrue(qt.points(inRect: rect2) == [Point(1, 1), Point(0.5, 0.5), Point(1.5, 1.5)]) } } ================================================ FILE: QuadTree/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 82EF3AAE1E50E77800013ECB /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82EF3AAD1E50E77800013ECB /* Tests.swift */; }; 82EF3AB51E50E82400013ECB /* QuadTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82EF3AB41E50E82400013ECB /* QuadTree.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 82EF3AAA1E50E77800013ECB /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 82EF3AAD1E50E77800013ECB /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 82EF3AAF1E50E77800013ECB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 82EF3AB41E50E82400013ECB /* QuadTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = QuadTree.swift; path = ../QuadTree.playground/Sources/QuadTree.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 82EF3AA71E50E77800013ECB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 82EF3A9F1E50E74900013ECB = { isa = PBXGroup; children = ( 82EF3AB41E50E82400013ECB /* QuadTree.swift */, 82EF3AAC1E50E77800013ECB /* Tests */, 82EF3AAB1E50E77800013ECB /* Products */, ); sourceTree = ""; }; 82EF3AAB1E50E77800013ECB /* Products */ = { isa = PBXGroup; children = ( 82EF3AAA1E50E77800013ECB /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 82EF3AAC1E50E77800013ECB /* Tests */ = { isa = PBXGroup; children = ( 82EF3AAD1E50E77800013ECB /* Tests.swift */, 82EF3AAF1E50E77800013ECB /* Info.plist */, ); path = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 82EF3AA91E50E77800013ECB /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 82EF3AB01E50E77800013ECB /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 82EF3AA61E50E77800013ECB /* Sources */, 82EF3AA71E50E77800013ECB /* Frameworks */, 82EF3AA81E50E77800013ECB /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = 82EF3AAA1E50E77800013ECB /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 82EF3AA01E50E74900013ECB /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0820; LastUpgradeCheck = 0820; TargetAttributes = { 82EF3AA91E50E77800013ECB = { CreatedOnToolsVersion = 8.2.1; DevelopmentTeam = 34BUG46ZSN; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 82EF3AA31E50E74900013ECB /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 82EF3A9F1E50E74900013ECB; productRefGroup = 82EF3AAB1E50E77800013ECB /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 82EF3AA91E50E77800013ECB /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 82EF3AA81E50E77800013ECB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 82EF3AA61E50E77800013ECB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 82EF3AB51E50E82400013ECB /* QuadTree.swift in Sources */, 82EF3AAE1E50E77800013ECB /* Tests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 82EF3AA41E50E74900013ECB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Debug; }; 82EF3AA51E50E74900013ECB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Release; }; 82EF3AB11E50E77800013ECB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 34BUG46ZSN; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; }; name = Debug; }; 82EF3AB21E50E77800013ECB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 34BUG46ZSN; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = com.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 82EF3AA31E50E74900013ECB /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 82EF3AA41E50E74900013ECB /* Debug */, 82EF3AA51E50E74900013ECB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 82EF3AB01E50E77800013ECB /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 82EF3AB11E50E77800013ECB /* Debug */, 82EF3AB21E50E77800013ECB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 82EF3AA01E50E74900013ECB /* Project object */; } ================================================ FILE: QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Queue/Queue-Optimized.swift ================================================ /* First-in first-out queue (FIFO) New elements are added to the end of the queue. Dequeuing pulls elements from the front of the queue. Enqueuing and dequeuing are O(1) operations. */ public struct Queue { fileprivate var array = [T?]() fileprivate var head = 0 public var isEmpty: Bool { return count == 0 } public var count: Int { return array.count - head } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { guard let element = array[guarded: head] else { return nil } array[head] = nil head += 1 let percentage = Double(head)/Double(array.count) if array.count > 50 && percentage > 0.25 { array.removeFirst(head) head = 0 } return element } public var front: T? { if isEmpty { return nil } else { return array[head] } } } extension Array { subscript(guarded idx: Int) -> Element? { guard (startIndex.. { fileprivate var array = [T]() public var count: Int { return array.count } public var isEmpty: Bool { return array.isEmpty } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public var front: T? { return array.first } } ================================================ FILE: Queue/Queue.playground/Contents.swift ================================================ /* Queue A queue is a list where you can only insert new items at the back and remove items from the front. This ensures that the first item you enqueue is also the first item you dequeue. First come, first serve! A queue gives you a FIFO or first-in, first-out order. The element you inserted first is also the first one to come out again. It's only fair! In this implementation, enqueuing is an O(1) operation, dequeuing is O(n). */ public struct Queue { fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public var front: T? { return array.first } } // Create a queue and put some elements on it already. var queueOfNames = Queue(array: ["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) // Adds an element to the end of the queue. queueOfNames.enqueue("Mike") // Queue is now ["Carl", "Lisa", "Stephanie", "Jeff", "Wade", "Mike"] print(queueOfNames.array) // Remove and return the first element in the queue. This returns "Carl". queueOfNames.dequeue() // Return the first element in the queue. // Returns "Lisa" since "Carl" was dequeued on the previous line. queueOfNames.front // Check to see if the queue is empty. // Returns "false" since the queue still has elements in it. queueOfNames.isEmpty ================================================ FILE: Queue/Queue.playground/contents.xcplayground ================================================ ================================================ FILE: Queue/Queue.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Queue/Queue.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Queue/README.markdown ================================================ # Queue > This topic has been tutorialized [here](https://www.raywenderlich.com/148141/swift-algorithm-club-swift-queue-data-structure) A queue is a list where you can only insert new items at the back and remove items from the front. This ensures that the first item you enqueue is also the first item you dequeue. First come, first serve! Why would you need this? Well, in many algorithms you want to add objects to a temporary list and pull them off this list later. Often the order in which you add and remove these objects matters. A queue gives you a FIFO or first-in, first-out order. The element you inserted first is the first one to come out. It is only fair! (A similar data structure, the [stack](../Stack/), is LIFO or last-in first-out.) Here is an example to enqueue a number: ```swift queue.enqueue(10) ``` The queue is now `[ 10 ]`. Add the next number to the queue: ```swift queue.enqueue(3) ``` The queue is now `[ 10, 3 ]`. Add one more number: ```swift queue.enqueue(57) ``` The queue is now `[ 10, 3, 57 ]`. Let's dequeue to pull the first element off the front of the queue: ```swift queue.dequeue() ``` This returns `10` because that was the first number we inserted. The queue is now `[ 3, 57 ]`. Everyone moved up by one place. ```swift queue.dequeue() ``` This returns `3`, the next dequeue returns `57`, and so on. If the queue is empty, dequeuing returns `nil` or in some implementations it gives an error message. > **Note:** A queue is not always the best choice. If the order in which the items are added and removed from the list is not important, you can use a [stack](../Stack/) instead of a queue. Stacks are simpler and faster. ## The code Here is a simplistic implementation of a queue in Swift. It is a wrapper around an array to enqueue, dequeue, and peek at the front-most item: ```swift public struct Queue { fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public var front: T? { return array.first } } ``` This queue works well, but it is not optimal. Enqueuing is an **O(1)** operation because adding to the end of an array always takes the same amount of time regardless of the size of the array. You might be wondering why appending items to an array is **O(1)** or a constant-time operation. That is because an array in Swift always has some empty space at the end. If we do the following: ```swift var queue = Queue() queue.enqueue("Ada") queue.enqueue("Steve") queue.enqueue("Tim") ``` then the array might actually look like this: [ "Ada", "Steve", "Tim", xxx, xxx, xxx ] where `xxx` is memory that is reserved but not filled in yet. Adding a new element to the array overwrites the next unused spot: [ "Ada", "Steve", "Tim", "Grace", xxx, xxx ] This results by copying memory from one place to another which is a constant-time operation. There are only a limited number of unused spots at the end of the array. When the last `xxx` gets used, and you want to add another item, the array needs to resize to make more room. Resizing includes allocating new memory and copying all the existing data over to the new array. This is an **O(n)** process which is relatively slow. Since it happens occasionally, the time for appending a new element to the end of the array is still **O(1)** on average or **O(1)** "amortized". The story for dequeueing is different. To dequeue, we remove the element from the *beginning* of the array. This is always an **O(n)** operation because it requires all remaining array elements to be shifted in memory. In our example, dequeuing the first element `"Ada"` copies `"Steve"` in the place of `"Ada"`, `"Tim"` in the place of `"Steve"`, and `"Grace"` in the place of `"Tim"`: before [ "Ada", "Steve", "Tim", "Grace", xxx, xxx ] / / / / / / / / / / / / after [ "Steve", "Tim", "Grace", xxx, xxx, xxx ] Moving all these elements in memory is always an **O(n)** operation. So with our simple implementation of a queue, enqueuing is efficient, but dequeueing leaves something to be desired... ## A more efficient queue To make dequeuing efficient, we can also reserve some extra free space but this time at the front of the array. We must write this code ourselves because the built-in Swift array does not support it. The main idea is whenever we dequeue an item, we do not shift the contents of the array to the front (slow) but mark the item's position in the array as empty (fast). After dequeuing `"Ada"`, the array is: [ xxx, "Steve", "Tim", "Grace", xxx, xxx ] After dequeuing `"Steve"`, the array is: [ xxx, xxx, "Tim", "Grace", xxx, xxx ] Because these empty spots at the front never get reused, you can periodically trim the array by moving the remaining elements to the front: [ "Tim", "Grace", xxx, xxx, xxx, xxx ] This trimming procedure involves shifting memory which is an **O(n)** operation. Because this only happens once in a while, dequeuing is **O(1)** on average. Here is how you can implement this version of `Queue`: ```swift public struct Queue { fileprivate var array = [T?]() fileprivate var head = 0 public var isEmpty: Bool { return count == 0 } public var count: Int { return array.count - head } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func dequeue() -> T? { guard head < array.count, let element = array[head] else { return nil } array[head] = nil head += 1 let percentage = Double(head)/Double(array.count) if array.count > 50 && percentage > 0.25 { array.removeFirst(head) head = 0 } return element } public var front: T? { if isEmpty { return nil } else { return array[head] } } } ``` The array now stores objects of type `T?` instead of just `T` because we need to mark array elements as being empty. The `head` variable is the index in the array of the front-most object. Most of the new functionality sits in `dequeue()`. When we dequeue an item, we first set `array[head]` to `nil` to remove the object from the array. Then, we increment `head` because the next item has become the front one. We go from this: [ "Ada", "Steve", "Tim", "Grace", xxx, xxx ] head to this: [ xxx, "Steve", "Tim", "Grace", xxx, xxx ] head It is like if in a supermarket the people in the checkout lane do not shuffle forward towards the cash register, but the cash register moves up the queue. If we never remove those empty spots at the front then the array will keep growing as we enqueue and dequeue elements. To periodically trim down the array, we do the following: ```swift let percentage = Double(head)/Double(array.count) if array.count > 50 && percentage > 0.25 { array.removeFirst(head) head = 0 } ``` This calculates the percentage of empty spots at the beginning as a ratio of the total array size. If more than 25% of the array is unused, we chop off that wasted space. However, if the array is small we do not resize it all the time, so there must be at least 50 elements in the array before we try to trim it. > **Note:** I just pulled these numbers out of thin air -- you may need to tweak them based on the behavior of your app in a production environment. To test this in a playground, do the following: ```swift var q = Queue() q.array // [] empty array q.enqueue("Ada") q.enqueue("Steve") q.enqueue("Tim") q.array // [{Some "Ada"}, {Some "Steve"}, {Some "Tim"}] q.count // 3 q.dequeue() // "Ada" q.array // [nil, {Some "Steve"}, {Some "Tim"}] q.count // 2 q.dequeue() // "Steve" q.array // [nil, nil, {Some "Tim"}] q.count // 1 q.enqueue("Grace") q.array // [nil, nil, {Some "Tim"}, {Some "Grace"}] q.count // 2 ``` To test the trimming behavior, replace the line, ```swift if array.count > 50 && percentage > 0.25 { ``` with: ```swift if head > 2 { ``` Now if you dequeue another object, the array will look as follows: ```swift q.dequeue() // "Tim" q.array // [{Some "Grace"}] q.count // 1 ``` The `nil` objects at the front have been removed, and the array is no longer wasting space. This new version of `Queue` is not more complicated than the first one but dequeuing is now also an **O(1)** operation, just because we were aware about how we used the array. ## See also There are many ways to create a queue. Alternative implementations use a [linked list](../Linked%20List/), a [circular buffer](../Ring%20Buffer/), or a [heap](../Heap/). Variations on this theme are [deque](../Deque/), a double-ended queue where you can enqueue and dequeue at both ends, and [priority queue](../Priority%20Queue/), a sorted queue where the "most important" item is always at the front. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Queue/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Queue/Tests/QueueTests.swift ================================================ import Foundation import XCTest class QueueTest: XCTestCase { func testEmpty() { var queue = Queue() XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertEqual(queue.front, nil) XCTAssertNil(queue.dequeue()) } func testOneElement() { var queue = Queue() queue.enqueue(123) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.front, 123) let result = queue.dequeue() XCTAssertEqual(result, 123) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertEqual(queue.front, nil) } func testTwoElements() { var queue = Queue() queue.enqueue(123) queue.enqueue(456) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 2) XCTAssertEqual(queue.front, 123) let result1 = queue.dequeue() XCTAssertEqual(result1, 123) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.front, 456) let result2 = queue.dequeue() XCTAssertEqual(result2, 456) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertEqual(queue.front, nil) } func testMakeEmpty() { var queue = Queue() queue.enqueue(123) queue.enqueue(456) XCTAssertNotNil(queue.dequeue()) XCTAssertNotNil(queue.dequeue()) XCTAssertNil(queue.dequeue()) queue.enqueue(789) XCTAssertEqual(queue.count, 1) XCTAssertEqual(queue.front, 789) let result = queue.dequeue() XCTAssertEqual(result, 789) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) XCTAssertEqual(queue.front, nil) } } ================================================ FILE: Queue/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C4021C77A6BF003CECC7 /* Queue-Optimized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4011C77A6BF003CECC7 /* Queue-Optimized.swift */; }; 7B80C4041C77A6C5003CECC7 /* QueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C4011C77A6BF003CECC7 /* Queue-Optimized.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Queue-Optimized.swift"; path = "../Queue-Optimized.swift"; sourceTree = SOURCE_ROOT; }; 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C4011C77A6BF003CECC7 /* Queue-Optimized.swift */, 7B80C4031C77A6C5003CECC7 /* QueueTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 1000; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C4021C77A6BF003CECC7 /* Queue-Optimized.swift in Sources */, 7B80C4041C77A6C5003CECC7 /* QueueTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Queue/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Queue/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Quicksort/Quicksort.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation // *** Simple but inefficient version of quicksort *** func quicksort(_ a: [T]) -> [T] { guard a.count > 1 else { return a } let pivot = a[a.count/2] let less = a.filter { $0 < pivot } let equal = a.filter { $0 == pivot } let greater = a.filter { $0 > pivot } // Uncomment this following line to see in detail what the // pivot is in each step and how the subarrays are partitioned. //print(pivot, less, equal, greater) return quicksort(less) + equal + quicksort(greater) return quicksort(less) + equal + quicksort(greater) } let list1 = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] quicksort(list1) // *** Using Lomuto partitioning *** /* Lomuto's partitioning algorithm. The return value is the index of the pivot element in the new array. The left partition is [low...p-1]; the right partition is [p+1...high], where p is the return value. */ func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[high] var i = low for j in low..(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionLomuto(&a, low: low, high: high) quicksortLomuto(&a, low: low, high: p - 1) quicksortLomuto(&a, low: p + 1, high: high) } } quicksortLomuto(&list2, low: 0, high: list2.count - 1) // *** Hoare partitioning *** /* Hoare's partitioning scheme. The return value is NOT necessarily the index of the pivot element in the new array. Instead, the array is partitioned into [low...p] and [p+1...high], where p is the return value. The pivot value is placed somewhere inside one of the two partitions, but the algorithm doesn't tell you which one or where. */ func partitionHoare(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 while true { repeat { j -= 1 } while a[j] > pivot repeat { i += 1 } while a[i] < pivot if i < j { a.swapAt(i, j) } else { return j } } } var list3 = [ 8, 0, 3, 9, 2, 14, 10, 27, 1, 5, 8, -1, 26 ] partitionHoare(&list3, low: 0, high: list3.count - 1) list3 func quicksortHoare(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionHoare(&a, low: low, high: high) quicksortHoare(&a, low: low, high: p) quicksortHoare(&a, low: p + 1, high: high) } } quicksortHoare(&list3, low: 0, high: list3.count - 1) // *** Randomized sorting *** /* Returns a random integer in the range min...max, inclusive. */ public func random(min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } func quicksortRandom(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) (a[pivotIndex], a[high]) = (a[high], a[pivotIndex]) let p = partitionLomuto(&a, low: low, high: high) quicksortRandom(&a, low: low, high: p - 1) quicksortRandom(&a, low: p + 1, high: high) } } var list4 = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] quicksortRandom(&list4, low: 0, high: list4.count - 1) list4 // *** Dutch national flag partioning *** /* Swift's swap() doesn't like it if the items you're trying to swap refer to the same memory location. This little wrapper simply ignores such swaps. */ public func swap(_ a: inout [T], _ i: Int, _ j: Int) { if i != j { a.swapAt(i, j) } } /* Dutch national flag partitioning. Returns a tuple with the start and end index of the middle area. */ func partitionDutchFlag(_ a: inout [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { let pivot = a[pivotIndex] var smaller = low var equal = low var larger = high while equal <= larger { if a[equal] < pivot { swap(&a, smaller, equal) smaller += 1 equal += 1 } else if a[equal] == pivot { equal += 1 } else { swap(&a, equal, larger) larger -= 1 } } return (smaller, larger) } var list5 = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] partitionDutchFlag(&list5, low: 0, high: list5.count - 1, pivotIndex: 10) list5 func quicksortDutchFlag(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) let (p, q) = partitionDutchFlag(&a, low: low, high: high, pivotIndex: pivotIndex) quicksortDutchFlag(&a, low: low, high: p - 1) quicksortDutchFlag(&a, low: q + 1, high: high) } } quicksortDutchFlag(&list5, low: 0, high: list5.count - 1) ================================================ FILE: Quicksort/Quicksort.playground/contents.xcplayground ================================================ ================================================ FILE: Quicksort/Quicksort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Quicksort/Quicksort.swift ================================================ import Foundation /* Easy to understand but not very efficient. */ func quicksort(_ a: [T]) -> [T] { guard a.count > 1 else { return a } let pivot = a[a.count/2] let less = a.filter { $0 < pivot } let equal = a.filter { $0 == pivot } let greater = a.filter { $0 > pivot } return quicksort(less) + equal + quicksort(greater) } // MARK: - Lomuto /* Lomuto's partitioning algorithm. This is conceptually simpler than Hoare's original scheme but less efficient. The return value is the index of the pivot element in the new array. The left partition is [low...p-1]; the right partition is [p+1...high], where p is the return value. The left partition includes all values smaller than or equal to the pivot, so if the pivot value occurs more than once, its duplicates will be found in the left partition. */ func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int { // We always use the highest item as the pivot. let pivot = a[high] // This loop partitions the array into four (possibly empty) regions: // [low ... i] contains all values <= pivot, // [i+1 ... j-1] contains all values > pivot, // [j ... high-1] are values we haven't looked at yet, // [high ] is the pivot value. var i = low for j in low.. regions and the // array is properly partitioned. (a[i], a[high]) = (a[high], a[i]) return i } /* Recursive, in-place version that uses Lomuto's partioning scheme. */ func quicksortLomuto(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionLomuto(&a, low: low, high: high) quicksortLomuto(&a, low: low, high: p - 1) quicksortLomuto(&a, low: p + 1, high: high) } } // MARK: - Hoare partitioning /* Hoare's partitioning scheme. The return value is NOT necessarily the index of the pivot element in the new array. Instead, the array is partitioned into [low...p] and [p+1...high], where p is the return value. The pivot value is placed somewhere inside one of the two partitions, but the algorithm doesn't tell you which one or where. If the pivot value occurs more than once, then some instances may appear in the left partition and others may appear in the right partition. Hoare scheme is more efficient than Lomuto's partition scheme; it performs fewer swaps. */ func partitionHoare(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 while true { repeat { j -= 1 } while a[j] > pivot repeat { i += 1 } while a[i] < pivot if i < j { a.swapAt(i, j) } else { return j } } } /* Recursive, in-place version that uses Hoare's partioning scheme. Because of the choice of pivot, this performs badly if the array is already sorted. */ func quicksortHoare(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionHoare(&a, low: low, high: high) quicksortHoare(&a, low: low, high: p) quicksortHoare(&a, low: p + 1, high: high) } } // MARK: - Randomized sort /* Returns a random integer in the range min...max, inclusive. */ public func random(min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } /* Uses a random pivot index. On average, this results in a well-balanced split of the input array. */ func quicksortRandom(_ a: inout [T], low: Int, high: Int) { if low < high { // Create a random pivot index in the range [low...high]. let pivotIndex = random(min: low, max: high) // Because the Lomuto scheme expects a[high] to be the pivot entry, swap // a[pivotIndex] with a[high] to put the pivot element at the end. (a[pivotIndex], a[high]) = (a[high], a[pivotIndex]) let p = partitionLomuto(&a, low: low, high: high) quicksortRandom(&a, low: low, high: p - 1) quicksortRandom(&a, low: p + 1, high: high) } } // MARK: - Dutch national flag partitioning /* Swift's swap() doesn't like it if the items you're trying to swap refer to the same memory location. This little wrapper simply ignores such swaps. */ public func swap(_ a: inout [T], _ i: Int, _ j: Int) { if i != j { a.swapAt(i, j) } } /* Dutch national flag partitioning Partitions the array into three sections: all element smaller than the pivot, all elements equal to the pivot, and all larger elements. This makes for a more efficient Quicksort if the array contains many duplicate elements. Returns a tuple with the start and end index of the middle area. For example, on [0,1,2,3,3,3,4,5] it returns (3, 5). Note: These indices are relative to 0, not to "low"! The number of occurrences of the pivot is: result.1 - result.0 + 1 Time complexity is O(n), space complexity is O(1). */ func partitionDutchFlag(_ a: inout [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { let pivot = a[pivotIndex] var smaller = low var equal = low var larger = high // This loop partitions the array into four (possibly empty) regions: // [low ...smaller-1] contains all values < pivot, // [smaller... equal-1] contains all values == pivot, // [equal ... larger] contains all values > pivot, // [larger ... high] are values we haven't looked at yet. while equal <= larger { if a[equal] < pivot { swap(&a, smaller, equal) smaller += 1 equal += 1 } else if a[equal] == pivot { equal += 1 } else { swap(&a, equal, larger) larger -= 1 } } return (smaller, larger) } /* Uses Dutch national flag partitioning and a random pivot index. */ func quicksortDutchFlag(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) let (p, q) = partitionDutchFlag(&a, low: low, high: high, pivotIndex: pivotIndex) quicksortDutchFlag(&a, low: low, high: p - 1) quicksortDutchFlag(&a, low: q + 1, high: high) } } ================================================ FILE: Quicksort/README.markdown ================================================ # Quicksort Goal: Sort an array from low to high (or high to low). Quicksort is one of the most famous algorithms in history. It was invented way back in 1959 by Tony Hoare, at a time when recursion was still a fairly nebulous concept. Here's an implementation in Swift that should be easy to understand: ```swift func quicksort(_ a: [T]) -> [T] { guard a.count > 1 else { return a } let pivot = a[a.count/2] let less = a.filter { $0 < pivot } let equal = a.filter { $0 == pivot } let greater = a.filter { $0 > pivot } return quicksort(less) + equal + quicksort(greater) } ``` Put this code in a playground and test it like so: ```swift let list = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] quicksort(list) ``` Here's how it works. When given an array, `quicksort()` splits it up into three parts based on a "pivot" variable. Here, the pivot is taken to be the element in the middle of the array (later on you'll see other ways to choose the pivot). All the elements less than the pivot go into a new array called `less`. All the elements equal to the pivot go into the `equal` array. And you guessed it, all elements greater than the pivot go into the third array, `greater`. This is why the generic type `T` must be `Comparable`, so we can compare the elements with `<`, `==`, and `>`. Once we have these three arrays, `quicksort()` recursively sorts the `less` array and the `greater` array, then glues those sorted subarrays back together with the `equal` array to get the final result. ## An example Let's walk through the example. The array is initially: [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] First, we pick the pivot element. That is `8` because it's in the middle of the array. Now we split the array into the less, equal, and greater parts: less: [ 0, 3, 2, 1, 5, -1 ] equal: [ 8, 8 ] greater: [ 10, 9, 14, 27, 26 ] This is a good split because `less` and `greater` roughly contain the same number of elements. So we've picked a good pivot that chopped the array right down the middle. Note that the `less` and `greater` arrays aren't sorted yet, so we call `quicksort()` again to sort those two subarrays. That does the exact same thing: pick a pivot and split the subarray into three even smaller parts. Let's just take a look at the `less` array: [ 0, 3, 2, 1, 5, -1 ] The pivot element is the one in the middle, `1`. (You could also have picked `2`, it doesn't matter.) Again, we create three subarrays around the pivot: less: [ 0, -1 ] equal: [ 1 ] greater: [ 3, 2, 5 ] We're not done yet and `quicksort()` again is called recursively on the `less` and `greater` arrays. Let's look at `less` again: [ 0, -1 ] As pivot we pick `-1`. Now the subarrays are: less: [ ] equal: [ -1 ] greater: [ 0 ] The `less` array is empty because there was no value smaller than `-1`; the other arrays contain a single element each. That means we're done at this level of the recursion, and we go back up to sort the previous `greater` array. That `greater` array was: [ 3, 2, 5 ] This works just the same way as before: we pick the middle element `2` as the pivot and fill up the subarrays: less: [ ] equal: [ 2 ] greater: [ 3, 5 ] Note that here it would have been better to pick `3` as the pivot -- we would have been done sooner. But now we have to recurse into the `greater` array again to make sure it is sorted. This is why picking a good pivot is important. When you pick too many "bad" pivots, quicksort actually becomes really slow. More on that below. When we partition the `greater` subarray, we find: less: [ 3 ] equal: [ 5 ] greater: [ ] And now we're done at this level of the recursion because we can't split up the arrays any further. This process repeats until all the subarrays have been sorted. In a picture: ![Example](Images/Example.png) Now if you read the colored boxes from left to right, you get the sorted array: [ -1, 0, 1, 2, 3, 5, 8, 8, 9, 10, 14, 26, 27 ] This shows that `8` was a good initial pivot because it appears in the middle of the sorted array too. I hope this makes the basic principle clear of how quicksort works. Unfortunately, this version of quicksort isn't very quick, because we `filter()` the same array three times. There are more clever ways to split up the array. ## Partitioning Dividing the array around the pivot is called *partitioning* and there are a few different partitioning schemes. If the array is, [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] and we choose the middle element `8` as a pivot then after partitioning the array will look like this: [ 0, 3, 2, 1, 5, -1, 8, 8, 10, 9, 14, 27, 26 ] ----------------- ----------------- all elements < 8 all elements > 8 The key thing to realize is that after partitioning the pivot element is in its final sorted place already. The rest of the numbers are not sorted yet, they are simply partitioned around the pivot value. Quicksort partitions the array many times over, until all the values are in their final places. There is no guarantee that partitioning keeps the elements in the same relative order, so after partitioning around pivot `8` you could also end up with something like this: [ 3, 0, 5, 2, -1, 1, 8, 8, 14, 26, 10, 27, 9 ] The only guarantee is that to the left of the pivot are all the smaller elements and to the right are all the larger elements. Because partitioning can change the original order of equal elements, quicksort does not produce a "stable" sort (unlike [merge sort](../Merge%20Sort/), for example). Most of the time that's not a big deal. ## Lomuto's partitioning scheme In the first example of quicksort I showed you, partitioning was done by calling Swift's `filter()` function three times. That is not very efficient. So let's look at a smarter partitioning algorithm that works *in place*, i.e. by modifying the original array. Here's an implementation of Lomuto's partitioning scheme in Swift: ```swift func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[high] var i = low for j in low.. pivot 3. `a[j...high-1]` are values we haven't looked at yet 4. `a[high]` is the pivot value In ASCII art the array is divided up like this: [ values <= pivot | values > pivot | not looked at yet | pivot ] low i i+1 j-1 j high-1 high The loop looks at each element from `low` to `high-1` in turn. If the value of the current element is less than or equal to the pivot, it is moved into the first region using a swap. > **Note:** In Swift, the notation `(x, y) = (y, x)` is a convenient way to perform a swap between the values of `x` and `y`. You can also write `swap(&x, &y)`. After the loop is over, the pivot is still the last element in the array. So we swap it with the first element that is greater than the pivot. Now the pivot sits between the <= and > regions and the array is properly partitioned. Let's step through the example. The array we're starting with is: [| 10, 0, 3, 9, 2, 14, 26, 27, 1, 5, 8, -1 | 8 ] low high i j Initially, the "not looked at" region stretches from index 0 to 11. The pivot is at index 12. The "values <= pivot" and "values > pivot" regions are empty, because we haven't looked at any values yet. Look at the first value, `10`. Is this smaller than the pivot? No, skip to the next element. [| 10 | 0, 3, 9, 2, 14, 26, 27, 1, 5, 8, -1 | 8 ] low high i j Now the "not looked at" region goes from index 1 to 11, the "values > pivot" region contains the number `10`, and "values <= pivot" is still empty. Look at the second value, `0`. Is this smaller than the pivot? Yes, so swap `10` with `0` and move `i` ahead by one. [ 0 | 10 | 3, 9, 2, 14, 26, 27, 1, 5, 8, -1 | 8 ] low high i j Now "not looked at" goes from index 2 to 11, "values > pivot" still contains `10`, and "values <= pivot" contains the number `0`. Look at the third value, `3`. This is smaller than the pivot, so swap it with `10` to get: [ 0, 3 | 10 | 9, 2, 14, 26, 27, 1, 5, 8, -1 | 8 ] low high i j The "values <= pivot" region is now `[ 0, 3 ]`. Let's do one more... `9` is greater than the pivot, so simply skip ahead: [ 0, 3 | 10, 9 | 2, 14, 26, 27, 1, 5, 8, -1 | 8 ] low high i j Now the "values > pivot" region contains `[ 10, 9 ]`. If we keep going this way, then eventually we end up with: [ 0, 3, 2, 1, 5, 8, -1 | 27, 9, 10, 14, 26 | 8 ] low high i j The final thing to do is to put the pivot into place by swapping `a[i]` with `a[high]`: [ 0, 3, 2, 1, 5, 8, -1 | 8 | 9, 10, 14, 26, 27 ] low high i j And we return `i`, the index of the pivot element. > **Note:** If you're still not entirely clear on how the algorithm works, I suggest you play with this in the playground to see exactly how the loop creates these four regions. Let's use this partitioning scheme to build quicksort. Here's the code: ```swift func quicksortLomuto(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionLomuto(&a, low: low, high: high) quicksortLomuto(&a, low: low, high: p - 1) quicksortLomuto(&a, low: p + 1, high: high) } } ``` This is now super simple. We first call `partitionLomuto()` to reorder the array around the pivot (which is always the last element from the array). And then we call `quicksortLomuto()` recursively to sort the left and right partitions. Try it out: ```swift var list = [ 10, 0, 3, 9, 2, 14, 26, 27, 1, 5, 8, -1, 8 ] quicksortLomuto(&list, low: 0, high: list.count - 1) ``` Lomuto's isn't the only partitioning scheme but it's probably the easiest to understand. It's not as efficient as Hoare's scheme, which requires fewer swap operations. ## Hoare's partitioning scheme This partitioning scheme is by Hoare, the inventor of quicksort. Here is the code: ```Swift func partitionHoare(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 while true { repeat { j -= 1 } while a[j] > pivot repeat { i += 1 } while a[i] < pivot if i < j { a.swapAt(i, j) } else { return j } } } ``` To test this in a playground, do: ```swift var list = [ 8, 0, 3, 9, 2, 14, 10, 27, 1, 5, 8, -1, 26 ] let p = partitionHoare(&list, low: 0, high: list.count - 1) list // show the results ``` Note that with Hoare's scheme, the pivot is always expected to be the *first* element in the array, `a[low]`. Again, we're using `8` as the pivot element. The result is: [ -1, 0, 3, 8, 2, 5, 1, 27, 10, 14, 9, 8, 26 ] Note that this time the pivot isn't in the middle at all. Unlike with Lomuto's scheme, the return value is not necessarily the index of the pivot element in the new array. Instead, the array is partitioned into the regions `[low...p]` and `[p+1...high]`. Here, the return value `p` is 6, so the two partitions are `[ -1, 0, 3, 8, 2, 5, 1 ]` and `[ 27, 10, 14, 9, 8, 26 ]`. The pivot is placed somewhere inside one of the two partitions, but the algorithm doesn't tell you which one or where. If the pivot value occurs more than once, then some instances may appear in the left partition and others may appear in the right partition. Because of these differences, the implementation of Hoare's quicksort is slightly different: ```swift func quicksortHoare(_ a: inout [T], low: Int, high: Int) { if low < high { let p = partitionHoare(&a, low: low, high: high) quicksortHoare(&a, low: low, high: p) quicksortHoare(&a, low: p + 1, high: high) } } ``` I'll leave it as an exercise for the reader to figure out exactly how Hoare's partitioning scheme works. :-) ## Picking a good pivot Lomuto's partitioning scheme always chooses the last array element for the pivot. Hoare's scheme uses the first element. But there is no guarantee that these pivots are any good. Here is what happens when you pick a bad value for the pivot. Let's say the array is, [ 7, 6, 5, 4, 3, 2, 1 ] and we're using Lomuto's scheme. The pivot is the last element, `1`. After pivoting, we have the following arrays: less than pivot: [ ] equal to pivot: [ 1 ] greater than pivot: [ 7, 6, 5, 4, 3, 2 ] Now recursively partition the "greater than" subarray and get: less than pivot: [ ] equal to pivot: [ 2 ] greater than pivot: [ 7, 6, 5, 4, 3 ] And again: less than pivot: [ ] equal to pivot: [ 3 ] greater than pivot: [ 7, 6, 5, 4 ] And so on... That's no good, because this pretty much reduces quicksort to the much slower insertion sort. For quicksort to be efficient, it needs to split the array into roughly two halves. The optimal pivot for this example would have been `4`, so we'd get: less than pivot: [ 3, 2, 1 ] equal to pivot: [ 4 ] greater than pivot: [ 7, 6, 5 ] You might think this means we should always choose the middle element rather than the first or the last, but imagine what happens in the following situation: [ 7, 6, 5, 1, 4, 3, 2 ] Now the middle element is `1` and that gives the same lousy results as in the previous example. Ideally, the pivot is the *median* element of the array that you're partitioning, i.e. the element that sits in the middle of the sorted array. Of course, you won't know what the median is until after you've sorted the array, so this is a bit of a chicken-and-egg problem. However, there are some tricks to choose good, if not ideal, pivots. One trick is "median-of-three", where you find the median of the first, middle, and last element in this subarray. In theory that often gives a good approximation of the true median. Another common solution is to choose the pivot randomly. Sometimes this may result in choosing a suboptimal pivot but on average this gives very good results. Here is how you can do quicksort with a randomly chosen pivot: ```swift func quicksortRandom(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) // 1 (a[pivotIndex], a[high]) = (a[high], a[pivotIndex]) // 2 let p = partitionLomuto(&a, low: low, high: high) quicksortRandom(&a, low: low, high: p - 1) quicksortRandom(&a, low: p + 1, high: high) } } ``` There are two important differences with before: 1. The `random(min:max:)` function returns an integer in the range `min...max`, inclusive. This is our pivot index. 2. Because the Lomuto scheme expects `a[high]` to be the pivot entry, we swap `a[pivotIndex]` with `a[high]` to put the pivot element at the end before calling `partitionLomuto()`. It may seem strange to use random numbers in something like a sorting function, but it is necessary to make quicksort behave efficiently under all circumstances. With bad pivots, the performance of quicksort can be quite horrible, **O(n^2)**. But if you choose good pivots on average, for example by using a random number generator, the expected running time becomes **O(n log n)**, which is as good as sorting algorithms get. ## Dutch national flag partitioning But there are more improvements to make! In the first example of quicksort I showed you, we ended up with an array that was partitioned like this: [ values < pivot | values equal to pivot | values > pivot ] But as you've seen with the Lomuto partitioning scheme, if the pivot occurs more than once the duplicates end up in the left half. And with Hoare's scheme the pivot can be all over the place. The solution to this is "Dutch national flag" partitioning, named after the fact that the [Dutch flag](https://en.wikipedia.org/wiki/Flag_of_the_Netherlands) has three bands just like we want to have three partitions. The code for this scheme is: ```swift func partitionDutchFlag(_ a: inout [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { let pivot = a[pivotIndex] var smaller = low var equal = low var larger = high while equal <= larger { if a[equal] < pivot { swap(&a, smaller, equal) smaller += 1 equal += 1 } else if a[equal] == pivot { equal += 1 } else { swap(&a, equal, larger) larger -= 1 } } return (smaller, larger) } ``` This works very similarly to the Lomuto scheme, except that the loop partitions the array into four (possibly empty) regions: - `[low ... smaller-1]` contains all values < pivot - `[smaller ... equal-1]` contains all values == pivot - `[equal ... larger]` contains all values > pivot - `[larger ... high]` are values we haven't looked at yet Note that this doesn't assume the pivot is in `a[high]`. Instead, you have to pass in the index of the element you wish to use as a pivot. An example of how to use it: ```swift var list = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ] partitionDutchFlag(&list, low: 0, high: list.count - 1, pivotIndex: 10) list // show the results ``` Just for fun, we're giving it the index of the other `8` this time. The result is: [ -1, 0, 3, 2, 5, 1, 8, 8, 27, 14, 9, 26, 10 ] Notice how the two `8`s are in the middle now. The return value from `partitionDutchFlag()` is a tuple, `(6, 7)`. This is the range that contains the pivot value(s). Here is how you would use it in quicksort: ```swift func quicksortDutchFlag(_ a: inout [T], low: Int, high: Int) { if low < high { let pivotIndex = random(min: low, max: high) let (p, q) = partitionDutchFlag(&a, low: low, high: high, pivotIndex: pivotIndex) quicksortDutchFlag(&a, low: low, high: p - 1) quicksortDutchFlag(&a, low: q + 1, high: high) } } ``` Using Dutch flag partitioning makes for a more efficient quicksort if the array contains many duplicate elements. (And I'm not just saying that because I'm Dutch!) > **Note:** The above implementation of `partitionDutchFlag()` uses a custom `swap()` routine for swapping the contents of two array elements. Unlike Swift's own `swap()`, this doesn't give an error when the two indices refer to the same array element. See [Quicksort.swift](Quicksort.swift) for the code. ## See also [Quicksort on Wikipedia](https://en.wikipedia.org/wiki/Quicksort) *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Quicksort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Quicksort/Tests/QuicksortTests.swift ================================================ import XCTest class QuicksortTests: XCTestCase { func testQuicksort() { checkSortAlgorithm(quicksort) } fileprivate typealias QuicksortFunction = (inout [Int], _ low: Int, _ high: Int) -> Void fileprivate func checkQuicksort(_ function: QuicksortFunction) { checkSortAlgorithm { (a: [Int]) -> [Int] in var b = a function(&b, 0, b.count - 1) return b } } func testQuicksortLomuto() { checkQuicksort(quicksortLomuto) } func testQuicksortHoare() { checkQuicksort(quicksortHoare) } func testQuicksortRandom() { checkQuicksort(quicksortRandom) } func testQuicksortDutchFlag() { checkQuicksort(quicksortDutchFlag) } } ================================================ FILE: Quicksort/Tests/SortingTestHelpers.swift ================================================ import XCTest func randomArray(_ size: Int) -> [Int] { var a = [Int]() for _ in 1...size { a.append(Int(arc4random_uniform(1000))) } return a } func arrayIsSortedLowToHigh(_ a: [Int]) -> Bool { for x in 1.. a[x] { return false } } return true } typealias SortFunction = ([Int]) -> [Int] func checkSortingRandomArray(_ sortFunction: SortFunction) { let numberOfIterations = 100 for _ in 1...numberOfIterations { let a = randomArray(Int(arc4random_uniform(100)) + 1) let s = sortFunction(a) XCTAssertEqual(a.count, s.count) XCTAssertTrue(arrayIsSortedLowToHigh(s)) } } func checkSortingEmptyArray(_ sortFunction: SortFunction) { let a = [Int]() let s = sortFunction(a) XCTAssertEqual(s.count, 0) } func checkSortingArrayOneElement(_ sortFunction: SortFunction) { let a = [123] let s = sortFunction(a) XCTAssertEqual(s, [123]) } func checkSortingArrayTwoElementsInOrder(_ sortFunction: SortFunction) { let a = [123, 456] let s = sortFunction(a) XCTAssertEqual(s, [123, 456]) } func checkSortingArrayTwoElementsOutOfOrder(_ sortFunction: SortFunction) { let a = [456, 123] let s = sortFunction(a) XCTAssertEqual(s, [123, 456]) } func checkSortingArrayTwoEqualElements(_ sortFunction: SortFunction) { let a = [123, 123] let s = sortFunction(a) XCTAssertEqual(s, [123, 123]) } func checkSortingArrayThreeElementsABC(_ sortFunction: SortFunction) { let a = [2, 4, 6] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } func checkSortingArrayThreeElementsACB(_ sortFunction: SortFunction) { let a = [2, 6, 4] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } func checkSortingArrayThreeElementsBAC(_ sortFunction: SortFunction) { let a = [4, 2, 6] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } func checkSortingArrayThreeElementsBCA(_ sortFunction: SortFunction) { let a = [4, 6, 2] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } func checkSortingArrayThreeElementsCAB(_ sortFunction: SortFunction) { let a = [6, 2, 4] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } func checkSortingArrayThreeElementsCBA(_ sortFunction: SortFunction) { let a = [6, 4, 2] let s = sortFunction(a) XCTAssertEqual(s, [2, 4, 6]) } func checkSortAlgorithm(_ sortFunction: SortFunction) { checkSortingEmptyArray(sortFunction) checkSortingArrayOneElement(sortFunction) checkSortingArrayTwoElementsInOrder(sortFunction) checkSortingArrayTwoElementsOutOfOrder(sortFunction) checkSortingArrayTwoEqualElements(sortFunction) checkSortingArrayThreeElementsABC(sortFunction) checkSortingArrayThreeElementsACB(sortFunction) checkSortingArrayThreeElementsBAC(sortFunction) checkSortingArrayThreeElementsBCA(sortFunction) checkSortingArrayThreeElementsCAB(sortFunction) checkSortingArrayThreeElementsCBA(sortFunction) checkSortingRandomArray(sortFunction) } func checkSortAlgorithm(_ sortFunction: @escaping ([Int], (Int, Int) -> Bool) -> [Int]) { checkSortAlgorithm { a in sortFunction(a, <) } } ================================================ FILE: Quicksort/Tests/Tests-Quicksort.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3E61C77A4CA003CECC7 /* Quicksort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E51C77A4CA003CECC7 /* Quicksort.swift */; }; 7B80C3E91C77A4D0003CECC7 /* QuicksortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E71C77A4D0003CECC7 /* QuicksortTests.swift */; }; 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests-Quicksort.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Tests-Quicksort.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3E51C77A4CA003CECC7 /* Quicksort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Quicksort.swift; path = ../Quicksort.swift; sourceTree = SOURCE_ROOT; }; 7B80C3E71C77A4D0003CECC7 /* QuicksortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuicksortTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortingTestHelpers.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests-Quicksort.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3E51C77A4CA003CECC7 /* Quicksort.swift */, 7B80C3E71C77A4D0003CECC7 /* QuicksortTests.swift */, 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests-Quicksort */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests-Quicksort" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Tests-Quicksort"; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests-Quicksort.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0900; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests-Quicksort" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests-Quicksort */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */, 7B80C3E61C77A4CA003CECC7 /* Quicksort.swift in Sources */, 7B80C3E91C77A4D0003CECC7 /* QuicksortTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.2; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.2; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests-Quicksort" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests-Quicksort" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Quicksort/Tests/Tests-Quicksort.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Quicksort/Tests/Tests-Quicksort.xcodeproj/xcshareddata/xcschemes/Tests-Quicksort.xcscheme ================================================ ================================================ FILE: README.markdown ================================================ ![Swift Algorithm Club](Images/SwiftAlgorithm-410-transp.png) # Welcome to the Swift Algorithm Club! Here you'll find implementations of popular algorithms and data structures in everyone's favorite new language Swift, with detailed explanations of how they work. If you're a computer science student who needs to learn this stuff for exams -- or if you're a self-taught programmer who wants to brush up on the theory behind your craft -- you've come to the right place! The goal of this project is to **explain how algorithms work**. The focus is on clarity and readability of the code, not on making a reusable library that you can drop into your own projects. That said, most of the code should be ready for production use but you may need to tweak it to fit into your own codebase. Code is compatible with **Xcode 10** and **Swift 4.2**. We'll keep this updated with the latest version of Swift. If you're interested in a GitHub pages version of the repo, check out [this](https://aquarchitect.github.io/swift-algorithm-club/). :heart_eyes: **Suggestions and contributions are welcome!** :heart_eyes: ## Important links [What are algorithms and data structures?](What%20are%20Algorithms.markdown) Pancakes! [Why learn algorithms?](Why%20Algorithms.markdown) Worried this isn't your cup of tea? Then read this. [Big-O notation](Big-O%20Notation.markdown). We often say things like, "This algorithm is **O(n)**." If you don't know what that means, read this first. [Algorithm design techniques](Algorithm%20Design.markdown). How do you create your own algorithms? [How to contribute](https://github.com/raywenderlich/swift-algorithm-club/blob/master/.github/CONTRIBUTING.md). Report an issue to leave feedback, or submit a pull request. ## Where to start? If you're new to algorithms and data structures, here are a few good ones to start out with: - [Stack](Stack/) - [Queue](Queue/) - [Insertion Sort](Insertion%20Sort/) - [Binary Search](Binary%20Search/) and [Binary Search Tree](Binary%20Search%20Tree/) - [Merge Sort](Merge%20Sort/) - [Boyer-Moore string search](Boyer-Moore-Horspool/) ## The algorithms ### Searching - [Linear Search](Linear%20Search/). Find an element in an array. - [Binary Search](Binary%20Search/). Quickly find elements in a sorted array. - [Count Occurrences](Count%20Occurrences/). Count how often a value appears in an array. - [Select Minimum / Maximum](Select%20Minimum%20Maximum). Find the minimum/maximum value in an array. - [k-th Largest Element](Kth%20Largest%20Element/). Find the *k*-th largest element in an array, such as the median. - [Selection Sampling](Selection%20Sampling/). Randomly choose a bunch of items from a collection. - [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. ### String Search - [Brute-Force String Search](Brute-Force%20String%20Search/). A naive method. - [Boyer-Moore](Boyer-Moore-Horspool/). A fast method to search for substrings. It skips ahead based on a look-up table, to avoid looking at every character in the text. - [Knuth-Morris-Pratt](Knuth-Morris-Pratt/). A linear-time string algorithm that returns indexes of all occurrencies of a given pattern. - [Rabin-Karp](Rabin-Karp/) Faster search by using hashing. - [Longest Common Subsequence](Longest%20Common%20Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. - [Z-Algorithm](Z-Algorithm/). Finds all instances of a pattern in a String, and returns the indexes of where the pattern starts within the String. ### Sorting It's fun to see how sorting algorithms work, but in practice you'll almost never have to provide your own sorting routines. Swift's own `sort()` is more than up to the job. But if you're curious, read on... Basic sorts: - [Insertion Sort](Insertion%20Sort/) - [Selection Sort](Selection%20Sort/) - [Shell Sort](Shell%20Sort/) Fast sorts: - [Quicksort](Quicksort/) - [Merge Sort](Merge%20Sort/) - [Heap Sort](Heap%20Sort/) Hybrid sorts: - [Introsort](Introsort/) Special-purpose sorts: - [Counting Sort](Counting%20Sort/) - [Radix Sort](Radix%20Sort/) - [Topological Sort](Topological%20Sort/) Bad sorting algorithms (don't use these!): - [Bubble Sort](Bubble%20Sort/) - [Slow Sort](Slow%20Sort/) ### Compression - [Run-Length Encoding (RLE)](Run-Length%20Encoding/). Store repeated values as a single byte and a count. - [Huffman Coding](Huffman%20Coding/). Store more common elements using a smaller number of bits. ### Miscellaneous - [Shuffle](Shuffle/). Randomly rearranges the contents of an array. - [Comb Sort](Comb%20Sort/). An improve upon the Bubble Sort algorithm. - [Convex Hull](Convex%20Hull/). - [Miller-Rabin Primality Test](Miller-Rabin%20Primality%20Test/). Is the number a prime number? - [MinimumCoinChange](MinimumCoinChange/). A showcase for dynamic programming. - [Genetic](Genetic/). A simple example on how to slowly mutate a value to its ideal form, in the context of biological evolution. - [Myers Difference Algorithm](Myers%20Difference%20Algorithm/). Finding the longest common subsequence of two sequences. ### Mathematics - [Greatest Common Divisor (GCD)](GCD/). Special bonus: the least common multiple. - [Permutations and Combinations](Combinatorics/). Get your combinatorics on! - [Shunting Yard Algorithm](Shunting%20Yard/). Convert infix expressions to postfix. - [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication. - [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. - [Strassen's Multiplication Matrix](Strassen%20Matrix%20Multiplication/). Efficient way to handle matrix multiplication. - [CounterClockWise](/CounterClockWise/). Determining the area of a simple polygon. ### Machine learning - [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. - k-Nearest Neighbors - [Linear Regression](Linear%20Regression/). A technique for creating a model of the relationship between two (or more) variable quantities. - Logistic Regression - Neural Networks - PageRank - [Naive Bayes Classifier](Naive%20Bayes%20Classifier/) - [Simulated annealing](Simulated%20annealing/). Probabilistic technique for approximating the global maxima in a (often discrete) large search space. ## Data structures The choice of data structure for a particular task depends on a few things. First, there is the shape of your data and the kinds of operations that you'll need to perform on it. If you want to look up objects by a key you need some kind of dictionary; if your data is hierarchical in nature you want a tree structure of some sort; if your data is sequential you want a stack or queue. Second, it matters what particular operations you'll be performing most, as certain data structures are optimized for certain actions. For example, if you often need to find the most important object in a collection, then a heap or priority queue is more optimal than a plain array. Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types is sufficient, but sometimes you may want something more fancy... ### Variations on arrays - [Array2D](Array2D/). A two-dimensional array with fixed dimensions. Useful for board games. - [Bit Set](Bit%20Set/). A fixed-size sequence of *n* bits. - [Fixed Size Array](Fixed%20Size%20Array/). When you know beforehand how large your data will be, it might be more efficient to use an old-fashioned array with a fixed size. - [Ordered Array](Ordered%20Array/). An array that is always sorted. - [Rootish Array Stack](Rootish%20Array%20Stack/). A space and time efficient variation on Swift arrays. ### Queues - [Stack](Stack/). Last-in, first-out! - [Queue](Queue/). First-in, first-out! - [Deque](Deque/). A double-ended queue. - [Priority Queue](Priority%20Queue). A queue where the most important element is always at the front. - [Ring Buffer](Ring%20Buffer/). Also known as a circular buffer. An array of a certain size that conceptually wraps around back to the beginning. ### Lists - [Linked List](Linked%20List/). A sequence of data items connected through links. Covers both singly and doubly linked lists. - [Skip-List](Skip-List/). Skip List is a probabilistic data-structure with same logarithmic time bound and efficiency as AVL/ or Red-Black tree and provides a clever compromise to efficiently support search and update operations. ### Trees - [Tree](Tree/). A general-purpose tree structure. - [Binary Tree](Binary%20Tree/). A tree where each node has at most two children. - [Binary Search Tree (BST)](Binary%20Search%20Tree/). A binary tree that orders its nodes in a way that allows for fast queries. - [Red-Black Tree](Red-Black%20Tree/). A self balancing binary search tree. - [Splay Tree](Splay%20Tree/). A self balancing binary search tree that enables fast retrieval of recently updated elements. - [Threaded Binary Tree](Threaded%20Binary%20Tree/). A binary tree that maintains a few extra variables for cheap and fast in-order traversals. - [Segment Tree](Segment%20Tree/). Can quickly compute a function over a portion of an array. - [Lazy Propagation](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Segment%20Tree/LazyPropagation) - kd-Tree - [Sparse Table](Sparse%20Table/). Another take on quickly computing a function over a portion of an array, but this time we'll make it even quicker!. - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap - [Trie](Trie/). A special type of tree used to store associative data structures. - [B-Tree](B-Tree/). A self-balancing search tree, in which nodes can have more than two children. - [QuadTree](QuadTree/). A tree with 4 children. - [Octree](Octree/). A tree with 8 children. ### Hashing - [Hash Table](Hash%20Table/). Allows you to store and retrieve objects by a key. This is how the dictionary type is usually implemented. - Hash Functions ### Sets - [Bloom Filter](Bloom%20Filter/). A constant-memory data structure that probabilistically tests whether an element is in a set. - [Hash Set](Hash%20Set/). A set implemented using a hash table. - [Multiset](Multiset/). A set where the number of times an element is added matters. (Also known as a bag.) - [Ordered Set](Ordered%20Set/). A set where the order of items matters. ### Graphs - [Graph](Graph/) - [Breadth-First Search (BFS)](Breadth-First%20Search/) - [Depth-First Search (DFS)](Depth-First%20Search/) - [Shortest Path](Shortest%20Path%20%28Unweighted%29/) on an unweighted tree - [Single-Source Shortest Paths](Single-Source%20Shortest%20Paths%20(Weighted)/) - [Minimum Spanning Tree](Minimum%20Spanning%20Tree%20%28Unweighted%29/) on an unweighted tree - [Minimum Spanning Tree](Minimum%20Spanning%20Tree/) - [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) - [Dijkstra's shortest path algorithm](Dijkstra%20Algorithm/) - [A-Star](A-Star/) ## Puzzles A lot of software developer interview questions consist of algorithmic puzzles. Here is a small selection of fun ones. For more puzzles (with answers), see [here](http://elementsofprogramminginterviews.com/) and [here](http://www.crackingthecodinginterview.com). - [Two-Sum Problem](Two-Sum%20Problem/) - [Three-Sum/Four-Sum Problem](3Sum%20and%204Sum/) - [Fizz Buzz](Fizz%20Buzz/) - [Monty Hall Problem](Monty%20Hall%20Problem/) - [Finding Palindromes](Palindromes/) - [Dining Philosophers](DiningPhilosophers/) - [Egg Drop Problem](Egg%20Drop%20Problem/) - [Encoding and Decoding Binary Tree](Encode%20and%20Decode%20Tree/) - [Closest Pair](Closest%20Pair/) ## Learn more! Like what you see? Check out [Data Structures & Algorithms in Swift](https://store.raywenderlich.com/products/data-structures-and-algorithms-in-swift), the official book by the Swift Algorithm Club team! ![Data Structures & Algorithms in Swift Book](Images/DataStructuresAndAlgorithmsInSwiftBook.png) You’ll start with the fundamental structures of linked lists, queues and stacks, and see how to implement them in a highly Swift-like way. Move on to working with various types of trees, including general purpose trees, binary trees, AVL trees, binary search trees, and tries. Go beyond bubble and insertion sort with better-performing algorithms, including mergesort, radix sort, heap sort, and quicksort. Learn how to construct directed, non-directed and weighted graphs to represent many real-world models, and traverse graphs and trees efficiently with breadth-first, depth-first, Dijkstra’s and Prim’s algorithms to solve problems such as finding the shortest path or lowest cost in a network. By the end of this book, you’ll have hands-on experience solving common issues with data structures and algorithms — and you’ll be well on your way to developing your own efficient and useful implementations! You can find the book on the [raywenderlich.com store](https://store.raywenderlich.com/products/data-structures-and-algorithms-in-swift). ## Credits The Swift Algorithm Club was originally created by [Matthijs Hollemans](https://github.com/hollance). It is now maintained by [Vincent Ngo](https://www.raywenderlich.com/u/jomoka), [Kelvin Lau](https://github.com/kelvinlauKL), and [Richard Ash](https://github.com/richard-ash). The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/raywenderlich/swift-algorithm-club/graphs/contributors) of the [raywenderlich.com](https://www.raywenderlich.com) community. We're always looking for help - why not [join the club](.github/CONTRIBUTING.md)? :] ## License All content is licensed under the terms of the MIT open source license. By posting here, or by submitting any pull request through this forum, you agree that all content you submit or create, both code and text, is subject to this license. Razeware, LLC, and others will have all the rights described in the license regarding this content. The precise terms of this license may be found [here](https://github.com/raywenderlich/swift-algorithm-club/blob/master/LICENSE.txt). [![Build Status](https://travis-ci.org/raywenderlich/swift-algorithm-club.svg?branch=master)](https://travis-ci.org/raywenderlich/swift-algorithm-club) ================================================ FILE: Rabin-Karp/README.markdown ================================================ # Rabin-Karp string search algorithm The Rabin-Karp string search algorithm is used to search text for a pattern. A practical application of the algorithm is detecting plagiarism. Given source material, the algorithm can rapidly search through a paper for instances of sentences from the source material, ignoring details such as case and punctuation. Because of the abundance of the sought strings, single-string searching algorithms are impractical. ## Example Given a text of "The big dog jumped over the fox" and a search pattern of "ump" this will return 13. It starts by hashing "ump" then hashing "The". If hashed don't match then it slides the window a character at a time (e.g. "he ") and subtracts out the previous hash from the "T". ## Algorithm The Rabin-Karp algorithm uses a sliding window the size of the search pattern. It starts by hashing the search pattern, then hashing the first x characters of the text string where x is the length of the search pattern. It then slides the window one character over and uses the previous hash value to calculate the new hash faster. Only when it finds a hash that matches the hash of the search pattern will it compare the two strings it see if they are the same (to prevent a hash collision from producing a false positive). ## The code The major search method is next. More implementation details are in rabin-karp.swift ```swift public func search(text: String , pattern: String) -> Int { // convert to array of ints let patternArray = pattern.flatMap { $0.asInt } let textArray = text.flatMap { $0.asInt } if textArray.count < patternArray.count { return -1 } let patternHash = hash(array: patternArray) var endIdx = patternArray.count - 1 let firstChars = Array(textArray[0...endIdx]) let firstHash = hash(array: firstChars) if (patternHash == firstHash) { // Verify this was not a hash collision if firstChars == patternArray { return 0 } } var prevHash = firstHash // Now slide the window across the text to be searched for idx in 1...(textArray.count - patternArray.count) { endIdx = idx + (patternArray.count - 1) let window = Array(textArray[idx...endIdx]) let windowHash = nextHash(prevHash: prevHash, dropped: textArray[idx - 1], added: textArray[endIdx], patternSize: patternArray.count - 1) if windowHash == patternHash { if patternArray == window { return idx } } prevHash = windowHash } return -1 } ``` This code can be tested in a playground using the following: ```swift search(text: "The big dog jumped"", "ump") ``` This will return 13 since ump is in the 13 position of the zero based string. ## Additional Resources [Rabin-Karp Wikipedia](https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm) *Written by [Bill Barbour](https://github.com/brbatwork)* ================================================ FILE: Rabin-Karp/Rabin-Karp.playground/Contents.swift ================================================ //: Taking our rabin-karp algorithm for a walk // last checked with Xcode 9.4 #if swift(>=4.0) print("Hello, Swift 4!") #endif import UIKit struct Constants { static let hashMultiplier = 69061 } precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence } infix operator ** : PowerPrecedence func ** (radix: Int, power: Int) -> Int { return Int(pow(Double(radix), Double(power))) } func ** (radix: Double, power: Int) -> Double { return pow(radix, Double(power)) } extension Character { var asInt: Int { let s = String(self).unicodeScalars return Int(s[s.startIndex].value) } } // Find first position of pattern in the text using Rabin Karp algorithm public func search(text: String, pattern: String) -> Int { // convert to array of ints let patternArray = pattern.compactMap { $0.asInt } let textArray = text.compactMap { $0.asInt } if textArray.count < patternArray.count { return -1 } let patternHash = hash(array: patternArray) var endIdx = patternArray.count - 1 let firstChars = Array(textArray[0...endIdx]) let firstHash = hash(array: firstChars) if patternHash == firstHash { // Verify this was not a hash collison if firstChars == patternArray { return 0 } } var prevHash = firstHash // Now slide the window across the text to be searched for idx in 1...(textArray.count - patternArray.count) { endIdx = idx + (patternArray.count - 1) let window = Array(textArray[idx...endIdx]) let windowHash = nextHash( prevHash: prevHash, dropped: textArray[idx - 1], added: textArray[endIdx], patternSize: patternArray.count - 1 ) if windowHash == patternHash { if patternArray == window { return idx } } prevHash = windowHash } return -1 } public func hash(array: Array) -> Double { var total: Double = 0 var exponent = array.count - 1 for i in array { total += Double(i) * (Double(Constants.hashMultiplier) ** exponent) exponent -= 1 } return Double(total) } public func nextHash(prevHash: Double, dropped: Int, added: Int, patternSize: Int) -> Double { let oldHash = prevHash - (Double(dropped) * (Double(Constants.hashMultiplier) ** patternSize)) return Double(Constants.hashMultiplier) * oldHash + Double(added) } // TESTS assert(search(text:"The big dog jumped over the fox", pattern:"ump") == 13, "Invalid index returned") assert(search(text:"The big dog jumped over the fox", pattern:"missed") == -1, "Invalid index returned") assert(search(text:"The big dog jumped over the fox", pattern:"T") == 0, "Invalid index returned") ================================================ FILE: Rabin-Karp/Rabin-Karp.playground/contents.xcplayground ================================================ ================================================ FILE: Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Rabin-Karp/rabin-karp.swift ================================================ // The MIT License (MIT) // Copyright (c) 2016 Bill Barbour (brbatwork[at]gmail.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. struct Constants { static let hashMultiplier = 69069 } precedencegroup PowerPrecedence { higherThan: MultiplicationPrecedence } infix operator ** : PowerPrecedence func ** (radix: Int, power: Int) -> Int { return Int(pow(Double(radix), Double(power))) } func ** (radix: Double, power: Int) -> Double { return pow(radix, Double(power)) } extension Character { var asInt: Int { let s = String(self).unicodeScalars return Int(s[s.startIndex].value) } } // Find first position of pattern in the text using Rabin Karp algorithm public func search(text: String, pattern: String) -> Int { // convert to array of ints let patternArray = pattern.characters.flatMap { $0.asInt } let textArray = text.characters.flatMap { $0.asInt } if textArray.count < patternArray.count { return -1 } let patternHash = hash(array: patternArray) var endIdx = patternArray.count - 1 let firstChars = Array(textArray[0...endIdx]) let firstHash = hash(array: firstChars) if patternHash == firstHash { // Verify this was not a hash collison if firstChars == patternArray { return 0 } } var prevHash = firstHash // Now slide the window across the text to be searched for idx in 1...(textArray.count - patternArray.count) { endIdx = idx + (patternArray.count - 1) let window = Array(textArray[idx...endIdx]) let windowHash = nextHash( prevHash: prevHash, dropped: textArray[idx - 1], added: textArray[endIdx], patternSize: patternArray.count - 1 ) if windowHash == patternHash { if patternArray == window { return idx } } prevHash = windowHash } return -1 } public func hash(array: Array) -> Double { var total: Double = 0 var exponent = array.count - 1 for i in array { total += Double(i) * (Double(Constants.hashMultiplier) ** exponent) exponent -= 1 } return Double(total) } public func nextHash(prevHash: Double, dropped: Int, added: Int, patternSize: Int) -> Double { let oldHash = prevHash - (Double(dropped) * (Double(Constants.hashMultiplier) ** patternSize)) return Double(Constants.hashMultiplier) * oldHash + Double(added) } // TESTS assert(search(text:"The big dog jumped over the fox", pattern:"ump") == 13, "Invalid index returned") assert(search(text:"The big dog jumped over the fox", pattern:"missed") == -1, "Invalid index returned") assert(search(text:"The big dog jumped over the fox", pattern:"T") == 0, "Invalid index returned") ================================================ FILE: Radix Sort/RadixSort.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // Test Radix Sort with small array of ten values var array: [Int] = [19, 4242, 2, 9, 912, 101, 55, 67, 89, 32] radixSort(&array) // Test Radix Sort with large array of 1000 random values var bigArray = (0..<1000).map { _ in Int.random(in: 1...1000) } bigArray radixSort(&bigArray) ================================================ FILE: Radix Sort/RadixSort.playground/Sources/radixSort.swift ================================================ /* Sorting Algorithm that sorts an input array of integers digit by digit. */ // NOTE: This implementation does not handle negative numbers public func radixSort(_ array: inout [Int] ) { let radix = 10 //Here we define our radix to be 10 var done = false var index: Int var digit = 1 //Which digit are we on? while !done { //While our sorting is not completed done = true //Assume it is done for now var buckets: [[Int]] = [] //Our sorting subroutine is bucket sort, so let us predefine our buckets for _ in 1...radix { buckets.append([]) } for number in array { index = number / digit //Which bucket will we access? buckets[index % radix].append(number) if done && index > 0 { //If we arent done, continue to finish, otherwise we are done done = false } } var i = 0 for j in 0.. ================================================ FILE: Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Radix Sort/RadixSortExample.swift ================================================ // // RadixSortExample.swift // // // Created by Cheer on 2017/3/2. // // import Foundation func radixSort1(_ arr: inout [Int]) { var temp = [[Int]](repeating: [], count: 10) for num in arr { temp[num % 10].append(num) } for i in 1...Int(arr.max()!.description.characters.count) { for index in 0.. CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Radix Sort/Tests/RadixSortTests.swift ================================================ // // RadixSortTests.swift // Tests // // Created by theng on 2017-01-10. // Copyright © 2017 Swift Algorithm Club. All rights reserved. // import XCTest class RadixSortTests: XCTestCase { func testCombSort() { let expectedSequence: [Int] = [2, 9, 19, 32, 55, 67, 89, 101, 912, 4242] var sequence = [19, 4242, 2, 9, 912, 101, 55, 67, 89, 32] radixSort(&sequence) XCTAssertEqual(sequence, expectedSequence) } } ================================================ FILE: Radix Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 056E92AB1E25D0C700B30F52 /* RadixSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056E92AA1E25D0C700B30F52 /* RadixSortTests.swift */; }; 056E92AF1E25D3D700B30F52 /* radixSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056E92AE1E25D3D700B30F52 /* radixSort.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 056E92A21E25D04D00B30F52 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 056E92A61E25D04D00B30F52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 056E92AA1E25D0C700B30F52 /* RadixSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadixSortTests.swift; sourceTree = ""; }; 056E92AE1E25D3D700B30F52 /* radixSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = radixSort.swift; path = ../radixSort.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 056E929F1E25D04D00B30F52 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 056E92851E25D03300B30F52 = { isa = PBXGroup; children = ( 056E92A31E25D04D00B30F52 /* Tests */, 056E928F1E25D03300B30F52 /* Products */, ); sourceTree = ""; }; 056E928F1E25D03300B30F52 /* Products */ = { isa = PBXGroup; children = ( 056E92A21E25D04D00B30F52 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 056E92A31E25D04D00B30F52 /* Tests */ = { isa = PBXGroup; children = ( 056E92AE1E25D3D700B30F52 /* radixSort.swift */, 056E92A61E25D04D00B30F52 /* Info.plist */, 056E92AA1E25D0C700B30F52 /* RadixSortTests.swift */, ); name = Tests; sourceTree = SOURCE_ROOT; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 056E92A11E25D04D00B30F52 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 056E929E1E25D04D00B30F52 /* Sources */, 056E929F1E25D04D00B30F52 /* Frameworks */, 056E92A01E25D04D00B30F52 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = 056E92A21E25D04D00B30F52 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 056E92861E25D03300B30F52 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0820; LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 056E92A11E25D04D00B30F52 = { CreatedOnToolsVersion = 8.2; LastSwiftMigration = 0820; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 056E92851E25D03300B30F52; productRefGroup = 056E928F1E25D03300B30F52 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 056E92A11E25D04D00B30F52 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 056E92A01E25D04D00B30F52 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 056E929E1E25D04D00B30F52 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 056E92AF1E25D3D700B30F52 /* radixSort.swift in Sources */, 056E92AB1E25D0C700B30F52 /* RadixSortTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 056E92991E25D03300B30F52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 056E929A1E25D03300B30F52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; }; name = Release; }; 056E92A81E25D04D00B30F52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 056E92A91E25D04D00B30F52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 056E92991E25D03300B30F52 /* Debug */, 056E929A1E25D03300B30F52 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 056E92A81E25D04D00B30F52 /* Debug */, 056E92A91E25D04D00B30F52 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 056E92861E25D03300B30F52 /* Project object */; } ================================================ FILE: Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Radix Sort/radixSort.swift ================================================ /* Sorting Algorithm that sorts an input array of integers digit by digit. */ // NOTE: This implementation does not handle negative numbers func radixSort(_ array: inout [Int] ) { let radix = 10 //Here we define our radix to be 10 var done = false var index: Int var digit = 1 //Which digit are we on? while !done { //While our sorting is not completed done = true //Assume it is done for now var buckets: [[Int]] = [] //Our sorting subroutine is bucket sort, so let us predefine our buckets for _ in 1...radix { buckets.append([]) } for number in array { index = number / digit //Which bucket will we access? buckets[index % radix].append(number) if done && index > 0 { //If we arent done, continue to finish, otherwise we are done done = false } } var i = 0 for j in 0.. "om" -> "an"`. On the other hand, `find("romans")` will return false. ### Insertion The `insert()` function lets you add new strings to the radix tree. This function returns true if the string you are trying to insert was successfully inserted into the `RadixTree` and false if the string is already in the tree. ### Deletion The `remove()` removes a string from the tree. When a string is removed, any other strings that have a prefix of the removed string are removed as well. For example, `remove("rom")` will also remove `"roman"`, `"rome"`, and `"romulus"` if those strings are in the tree as well. Calling `remove("")` will remove all strings in the tree. ### printTree() You can use the `printTree()` function to visualize the tree. This function is a little buggy and not perfect yet but gets the job done thus far. ### Helper functions The `sharedPrefix()` function is a non-member function in the **RadixTree.swift** file. It takes in two `String` objects and returns the shared prefix between them. For example, `sharedPrefix("apples", "oranges")` will return `""`, and `sharedPrefix("court", "coral")` will return `"co"`. This function is used in the implementation of the `find()`, `insert()`, and `remove()` functions. ## See also [Radix Tree - Wikipedia](https://en.wikipedia.org/wiki/Radix_tree) *Written for Swift Algorithm Club by Steven Scally* ================================================ FILE: Radix Tree/RadixTree.playground/Contents.swift ================================================ // Radix Tree // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif var radix = RadixTree() var radixWiki = RadixTree() radixWiki.insert("romanus") radixWiki.insert("rubicundus") radixWiki.insert("rubicon") radixWiki.insert("romane") radixWiki.insert("ruber") radixWiki.insert("rubens") radixWiki.insert("romulus") radixWiki.insert("start") radixWiki.insert("shoot") radixWiki.insert("shit") radixWiki.insert("starch") radixWiki.insert("steven") radixWiki.insert("shart") radixWiki.insert("shard") radixWiki.insert("compute") radixWiki.insert("compatible") radixWiki.insert("construction") radixWiki.insert("coral") radixWiki.insert("crude") radixWiki.insert("chalk") radixWiki.insert("chime") radixWiki.insert("courting") radixWiki.insert("courted") radixWiki.insert("rubicunduses") radixWiki.printTree() print("\n\nFIND TESTS") print(radixWiki.find("courts")) // false print(radixWiki.find("r")) // true print(radixWiki.find("ro")) // true print(radixWiki.find("rom")) // true print(radixWiki.find("roma")) // true print(radixWiki.find("roman")) // true print(radixWiki.find("romane")) // true print(radixWiki.find("romans")) // false print(radixWiki.find("steve")) // true print("\n\nREMOVE TESTS") print(radixWiki.remove("c")) radixWiki.printTree() print(radixWiki.remove("rub")) radixWiki.printTree() print(radixWiki.remove("stevenson")) print(radixWiki.remove("")) radixWiki.printTree() ================================================ FILE: Radix Tree/RadixTree.playground/Sources/RadixTree.swift ================================================ import Foundation // The root is the top of the Radix Tree public class Root { var children: [Edge] public init() { children = [Edge]() } // Returns the length (in number of edges) of the longest traversal down the tree. public func height() -> Int { // Base case: no children: the tree has a height of 1 if children.count == 0 { return 1 } // Recursion: find the max height of a root's child and return 1 + that max else { var max = 1 for c in children { if c.height() > max { max = c.height() } } return 1 + max } } // Returns how far down in the tree a Root/Edge is. // A root's level is always 0. public func level() -> Int { return 0 } // Prints the tree for debugging/visualization purposes. public func printRoot() { // Print the first half of the children if children.count > 1 { for c in 0...children.count/2-1 { children[c].printEdge() print("|") } } else if children.count > 0 { children[0].printEdge() } // Then print the root print("ROOT") // Print the second half of the children if children.count > 1 { for c in children.count/2...children.count-1 { children[c].printEdge() print("|") } } print() } } // Edges are what actually store the Strings in the tree public class Edge: Root { var parent: Root? var label: String public init(_ label: String) { self.label = label super.init() } public override func level() -> Int { // Recurse up the tree incrementing level by one until the root is reached if parent != nil { return 1 + parent!.level() } // If an edge has no parent, it's level is one // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE else { return 1 } } // Erases a specific edge (and all edges below it in the tree). public func erase() { self.parent = nil if children.count > 0 { // For each child, erase it, then remove it from the children array. for _ in 0...children.count-1 { children[0].erase() children.remove(at: 0) } } } // Prints the tree for debugging/visualization purposes. public func printEdge() { // Print the first half of the edge's children if children.count > 1 { for c in 0...children.count/2-1 { children[c].printEdge() } } else if children.count > 0 { children[0].printEdge() } // Tab over once up to the edge's level for x in 1...level() { if x == level() { print("|------>", terminator: "") } else { print("| ", terminator: "") } } print(label) // Print the second half of the edge's children if children.count == 0 { for _ in 1...level() { print("| ", terminator: "") } print() } if children.count > 1 { for c in children.count/2...children.count-1 { children[c].printEdge() } } } } public class RadixTree { var root: Root public init() { root = Root() } // Returns the height of the tree by calling the root's height function. public func height() -> Int { return root.height() - 1 } // Inserts a string into the tree. public func insert(_ str: String) -> Bool { //Account for a blank input. The empty string is already in the tree. if str == "" { return false } // searchStr is the parameter of the function // it will be substringed as the function traverses down the tree var searchStr = str // currEdge is the current Edge (or Root) in question var currEdge = root while true { var found = false // If the current Edge has no children then the remaining searchStr is // created as a child if currEdge.children.count == 0 { let newEdge = Edge(searchStr) currEdge.children.append(newEdge) newEdge.parent = currEdge return true } // Loop through all of the children for e in currEdge.children { // Get the shared prefix between the child in question and the // search string let shared = sharedPrefix(searchStr, e.label) var index = shared.startIndex // If the search string is equal to the shared string, // the string already exists in the tree if searchStr == shared { return false } // If the child's label is equal to the shared string, you have to // traverse another level down the tree, so substring the search // string, break the loop, and run it back else if shared == e.label { currEdge = e var tempIndex = searchStr.startIndex for _ in 1...shared.count { tempIndex = searchStr.index(after: tempIndex) } searchStr = String(searchStr[tempIndex...]) found = true break } // If the child's label and the search string share a partial prefix, // then both the label and the search string need to be substringed // and a new branch needs to be created else if shared.count > 0 { var labelIndex = e.label.startIndex // Create index objects and move them to after the shared prefix for _ in 1...shared.count { index = searchStr.index(after: index) labelIndex = e.label.index(after: labelIndex) } // Substring both the search string and the label from the shared prefix searchStr = String(searchStr[index...]) e.label = String(e.label[labelIndex...]) // Create 2 new edges and update parent/children values let newEdge = Edge(e.label) e.label = shared for ec in e.children { newEdge.children.append(ec) } newEdge.parent = e e.children.removeAll() for nec in newEdge.children { nec.parent = newEdge } e.children.append(newEdge) let newEdge2 = Edge(searchStr) newEdge2.parent = e e.children.append(newEdge2) return true } // If they don't share a prefix, go to next child } // If none of the children share a prefix, you have to create a new child if !found { let newEdge = Edge(searchStr) currEdge.children.append(newEdge) newEdge.parent = currEdge return true } } } // Tells you if a string is in the tree public func find(_ str: String) -> Bool { // A radix tree always contains the empty string if str == "" { return true } // If there are no children then the string cannot be in the tree else if root.children.count == 0 { return false } var searchStr = str var currEdge = root while true { var found = false // Loop through currEdge's children for c in currEdge.children { // First check if the search string and the child's label are equal // if so the string is in the tree, return true if searchStr == c.label { return true } // If that is not true, find the shared string b/t the search string // and the label let shared = sharedPrefix(searchStr, c.label) // If the shared string is equal to the label, update the curent node, // break the loop, and run it back if shared == c.label { currEdge = c var tempIndex = searchStr.startIndex for _ in 1...shared.count { tempIndex = searchStr.index(after: tempIndex) } searchStr = String(searchStr[tempIndex...]) found = true break } // If the shared string is empty, go to the next child else if shared.count == 0 { continue } // If the shared string matches the search string, return true else if shared == searchStr { return true } // If the search string and the child's label only share some characters, // the string is not in the tree, return false else if shared[shared.startIndex] == c.label[c.label.startIndex] && shared.count < c.label.count { return false } } // If nothing was found, return false if !found { return false } } } // Removes a string from the tree public func remove(_ str: String) -> Bool { // Removing the empty string removes everything in the tree if str == "" { for c in root.children { c.erase() root.children.remove(at: 0) } return true } // If the tree is empty, you cannot remove anything else if root.children.count == 0 { return false } var searchStr = str var currEdge = root while true { var found = false // If currEdge has no children, then the searchStr is not in the tree if currEdge.children.count == 0 { return false } // Loop through the children for c in 0...currEdge.children.count-1 { // If the child's label matches the search string, remove that child // and everything below it in the tree if currEdge.children[c].label == searchStr { currEdge.children[c].erase() currEdge.children.remove(at: c) return true } // Find the shared string let shared = sharedPrefix(searchStr, currEdge.children[c].label) // If the shared string is equal to the child's string, go down a level if shared == currEdge.children[c].label { currEdge = currEdge.children[c] var tempIndex = searchStr.startIndex for _ in 1...shared.count { tempIndex = searchStr.index(after: tempIndex) } searchStr = String(searchStr[tempIndex...]) found = true break } } // If there is no match, then the searchStr is not in the tree if !found { return false } } } // Prints the tree by calling the root's print function public func printTree() { root.printRoot() } } // Returns the prefix that is shared between the two input strings // i.e. sharedPrefix("court", "coral") -> "co" public func sharedPrefix(_ str1: String, _ str2: String) -> String { var temp = "" var c1 = str1.startIndex var c2 = str2.startIndex for _ in 0...min(str1.count-1, str2.count-1) { if str1[c1] == str2[c2] { temp.append( str1[c1] ) c1 = str1.index(after:c1) c2 = str2.index(after:c2) } else { return temp } } return temp } ================================================ FILE: Radix Tree/RadixTree.playground/contents.xcplayground ================================================ ================================================ FILE: Radix Tree/RadixTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Radix Tree/RadixTree.swift ================================================ import Foundation // The root is the top of the Radix Tree public class Root { var children: [Edge] public init() { children = [Edge]() } // Returns the length (in number of edges) of the longest traversal down the tree. public func height() -> Int { // Base case: no children: the tree has a height of 1 if children.count == 0 { return 1 } // Recursion: find the max height of a root's child and return 1 + that max else { var max = 1 for c in children { if c.height() > max { max = c.height() } } return 1 + max } } // Returns how far down in the tree a Root/Edge is. // A root's level is always 0. public func level() -> Int { return 0 } // Prints the tree for debugging/visualization purposes. public func printRoot() { // Print the first half of the children if children.count > 1 { for c in 0...children.count/2-1 { children[c].printEdge() print("|") } } else if children.count > 0 { children[0].printEdge() } // Then print the root print("ROOT") // Print the second half of the children if children.count > 1 { for c in children.count/2...children.count-1 { children[c].printEdge() print("|") } } print() } } // Edges are what actually store the Strings in the tree public class Edge: Root { var parent: Root? var label: String public init(_ label: String) { self.label = label super.init() } public override func level() -> Int { // Recurse up the tree incrementing level by one until the root is reached if parent != nil { return 1 + parent!.level() } // If an edge has no parent, it's level is one // NOTE: THIS SHOULD NEVER HAPPEN AS THE ROOT IS ALWAYS THE TOP OF THE TREE else { return 1 } } // Erases a specific edge (and all edges below it in the tree). public func erase() { self.parent = nil if children.count > 0 { // For each child, erase it, then remove it from the children array. for _ in 0...children.count-1 { children[0].erase() children.remove(at: 0) } } } // Prints the tree for debugging/visualization purposes. public func printEdge() { // Print the first half of the edge's children if children.count > 1 { for c in 0...children.count/2-1 { children[c].printEdge() } } else if children.count > 0 { children[0].printEdge() } // Tab over once up to the edge's level for x in 1...level() { if x == level() { print("|------>", terminator: "") } else { print("| ", terminator: "") } } print(label) // Print the second half of the edge's children if children.count == 0 { for _ in 1...level() { print("| ", terminator: "") } print() } if children.count > 1 { for c in children.count/2...children.count-1 { children[c].printEdge() } } } } public class RadixTree { var root: Root public init() { root = Root() } // Returns the height of the tree by calling the root's height function. public func height() -> Int { return root.height() - 1 } // Inserts a string into the tree. public func insert(_ str: String) -> Bool { //Account for a blank input. The empty string is already in the tree. if str == "" { return false } // searchStr is the parameter of the function // it will be substringed as the function traverses down the tree var searchStr = str // currEdge is the current Edge (or Root) in question var currEdge = root while true { var found = false // If the current Edge has no children then the remaining searchStr is // created as a child if currEdge.children.count == 0 { let newEdge = Edge(searchStr) currEdge.children.append(newEdge) newEdge.parent = currEdge return true } // Loop through all of the children for e in currEdge.children { // Get the shared prefix between the child in question and the // search string let shared = sharedPrefix(searchStr, e.label) var index = shared.startIndex // If the search string is equal to the shared string, // the string already exists in the tree if searchStr == shared { return false } // If the child's label is equal to the shared string, you have to // traverse another level down the tree, so substring the search // string, break the loop, and run it back else if shared == e.label { currEdge = e var tempIndex = searchStr.startIndex for _ in 1...shared.count { tempIndex = searchStr.index(after: tempIndex) } searchStr = String(searchStr[tempIndex...]) found = true break } // If the child's label and the search string share a partial prefix, // then both the label and the search string need to be substringed // and a new branch needs to be created else if shared.count > 0 { var labelIndex = e.label.startIndex // Create index objects and move them to after the shared prefix for _ in 1...shared.count { index = searchStr.index(after: index) labelIndex = e.label.index(after: labelIndex) } // Substring both the search string and the label from the shared prefix searchStr = String(searchStr[index...]) e.label = String(e.label[labelIndex...]) // Create 2 new edges and update parent/children values let newEdge = Edge(e.label) e.label = shared for ec in e.children { newEdge.children.append(ec) } newEdge.parent = e e.children.removeAll() for nec in newEdge.children { nec.parent = newEdge } e.children.append(newEdge) let newEdge2 = Edge(searchStr) newEdge2.parent = e e.children.append(newEdge2) return true } // If they don't share a prefix, go to next child } // If none of the children share a prefix, you have to create a new child if !found { let newEdge = Edge(searchStr) currEdge.children.append(newEdge) newEdge.parent = currEdge return true } } } // Tells you if a string is in the tree public func find(_ str: String) -> Bool { // A radix tree always contains the empty string if str == "" { return true } // If there are no children then the string cannot be in the tree else if root.children.count == 0 { return false } var searchStr = str var currEdge = root while true { var found = false // Loop through currEdge's children for c in currEdge.children { // First check if the search string and the child's label are equal // if so the string is in the tree, return true if searchStr == c.label { return true } // If that is not true, find the shared string b/t the search string // and the label let shared = sharedPrefix(searchStr, c.label) // If the shared string is equal to the label, update the curent node, // break the loop, and run it back if shared == c.label { currEdge = c var tempIndex = searchStr.startIndex for _ in 1...shared.count { tempIndex = searchStr.index(after: tempIndex) } searchStr = String(searchStr[tempIndex...]) found = true break } // If the shared string is empty, go to the next child else if shared.count == 0 { continue } // If the shared string matches the search string, return true else if shared == searchStr { return true } // If the search string and the child's label only share some characters, // the string is not in the tree, return false else if shared[shared.startIndex] == c.label[c.label.startIndex] && shared.count < c.label.count { return false } } // If nothing was found, return false if !found { return false } } } // Removes a string from the tree public func remove(_ str: String) -> Bool { // Removing the empty string removes everything in the tree if str == "" { for c in root.children { c.erase() root.children.remove(at: 0) } return true } // If the tree is empty, you cannot remove anything else if root.children.count == 0 { return false } var searchStr = str var currEdge = root while true { var found = false // If currEdge has no children, then the searchStr is not in the tree if currEdge.children.count == 0 { return false } // Loop through the children for c in 0...currEdge.children.count-1 { // If the child's label matches the search string, remove that child // and everything below it in the tree if currEdge.children[c].label == searchStr { currEdge.children[c].erase() currEdge.children.remove(at: c) return true } // Find the shared string let shared = sharedPrefix(searchStr, currEdge.children[c].label) // If the shared string is equal to the child's string, go down a level if shared == currEdge.children[c].label { currEdge = currEdge.children[c] var tempIndex = searchStr.startIndex for _ in 1...shared.count { tempIndex = searchStr.index(after: tempIndex) } searchStr = String(searchStr[tempIndex...]) found = true break } } // If there is no match, then the searchStr is not in the tree if !found { return false } } } // Prints the tree by calling the root's print function public func printTree() { root.printRoot() } } // Returns the prefix that is shared between the two input strings // i.e. sharedPrefix("court", "coral") -> "co" public func sharedPrefix(_ str1: String, _ str2: String) -> String { var temp = "" var c1 = str1.startIndex var c2 = str2.startIndex for _ in 0...min(str1.count-1, str2.count-1) { if str1[c1] == str2[c2] { temp.append( str1[c1] ) c1 = str1.index(after:c1) c2 = str2.index(after:c2) } else { return temp } } return temp } ================================================ FILE: Red-Black Tree/README.markdown ================================================ # Red-Black Tree A red-black tree (RBT) is a balanced version of a [Binary Search Tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Binary%20Search%20Tree) guaranteeing that the basic operations (search, predecessor, successor, minimum, maximum, insert and delete) have a logarithmic worst case performance. Binary search trees (BSTs) have the disadvantage that they can become unbalanced after some insert or delete operations. In the worst case, this could lead to a tree where the nodes build a linked list as shown in the following example: ``` a \ b \ c \ d ``` To prevent this issue, RBTs perform rebalancing operations after an insert or delete and store an additional color property at each node which can either be red or black. After each operation a RBT satisfies the following properties: ## Properties 1. Every node is either red or black 2. The root is black 3. Every leaf (nullLeaf) is black 4. If a node is red, then both its children are black 5. For each node, all paths from the node to descendant leaves contain the same number of black nodes Property 5 includes the definition of the black-height of a node x, bh(x), which is the number of black nodes on a path from this node down to a leaf not counting the node itself. From [CLRS] ## Methods Nodes: * `nodeX.getPredecessor()` Returns the inorder predecessor of nodeX * `nodeX.getSuccessor()` Returns the inorder successor of nodeX * `nodeX.minimum()` Returns the node with the minimum key of the subtree of nodeX * `nodeX.maximum()` Returns the node with the maximum key of the subtree of nodeX Tree: * `search(input:)` Returns the node with the given key value * `minValue()` Returns the minimum key value of the whole tree * `maxValue()` Returns the maximum key value of the whole tree * `insert(key:)` Inserts the key value into the tree * `delete(key:)` Delete the node with the respective key value from the tree * `verify()` Verifies that the given tree fulfills the red-black tree properties * `count()` Returns how many nodes in the tree * `isEmpty()` Returns if the tree has no nodes * `allElements()` Returns an array containing all nodes (in-order traversal) in the tree. The rotation, insertion and deletion algorithms are implemented based on the pseudo-code provided in [CLRS] ## Implementation Details For convenience, all nil-pointers to children or the parent (except the parent of the root) of a node are exchanged with a nullLeaf. This is an ordinary node object, like all other nodes in the tree, but with a black color, and in this case a nil value for its children, parent and key. Therefore, an empty tree consists of exactly one nullLeaf at the root. ## Rotation Left rotation (around x): Assumes that x.rightChild y is not a nullLeaf, rotates around the link from x to y, makes y the new root of the subtree with x as y's left child and y's left child as x's right child, where n = a node, [n] = a subtree ``` | | x y / \ ~> / \ [A] y x [C] / \ / \ [B] [C] [A] [B] ``` Right rotation (around y): Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, makes x the new root of the subtree with y as x's right child and x's right child as y's left child, where n = a node, [n] = a subtree ``` | | x y / \ <~ / \ [A] y x [C] / \ / \ [B] [C] [A] [B] ``` As rotation is a local operation only exchanging pointers it's runtime is O(1). ## Insertion We create a node with the given key and set its color to red. Then we insert it into the the tree by performing a standard insert into a BST. After this, the tree might not be a valid RBT anymore, so we fix the red-black properties by calling the insertFixup algorithm. The only violation of the red-black properties occurs at the inserted node z and its parent. Either both are red, or the parent does not exist (so there is a violation since the root must be black). We have three distinct cases: **Case 1:** The uncle of z is red. If z.parent is left child, z's uncle is z.grandparent's right child. If this is the case, we recolor and move z to z.grandparent, then we check again for this new z. In the following cases, we denote a red node with (x) and a black node with {x}, p = parent, gp = grandparent and u = uncle ``` | | {gp} (newZ) / \ ~> / \ (p) (u) {p} {u} / \ / \ / \ / \ (z) [C] [D] [E] (z) [C] [D] [E] / \ / \ [A] [B] [A] [B] ``` **Case 2a:** The uncle of z is black and z is right child. Here, we move z upwards, so z's parent is the newZ and then we rotate around this newZ. After this, we have Case 2b. ``` | | {gp} {gp} / \ ~> / \ (p) {u} (z) {u} / \ / \ / \ / \ [A] (z) [D] [E] (newZ) [C] [D] [E] / \ / \ [B] [C] [A] [B] ``` **Case 2b:** The uncle of z is black and z is left child. In this case, we recolor z.parent to black and z.grandparent to red. Then we rotate around z's grandparent. Afterwards we have valid red-black tree. ``` | | {gp} {p} / \ ~> / \ (p) {u} (z) (gp) / \ / \ / \ / \ (z) [C] [D] [E] [A] [B] [C] {u} / \ / \ [A] [B] [D] [E] ``` Running time of this algorithm: * Only case 1 may repeat, but this only h/2 steps, where h is the height of the tree * Case 2a -> Case 2b -> red-black tree * Case 2b -> red-black tree As we perform case 1 at most O(log n) times and all other cases at most once, we have O(log n) recolorings and at most 2 rotations. The overall runtime of insert is O(log n). ## Deletion We search for the node with the given key, and if it exists we delete it by performing a standard delete from a BST. If the deleted nodes' color was red everything is fine, otherwise red-black properties may be violated so we call the fixup procedure deleteFixup. Violations can be that the parent and child of the deleted node x where red, so we now have two adjacent red nodes, or if we deleted the root, the root could now be red, or the black height property is violated. We have 4 cases: We call deleteFixup on node x **Case 1:** The sibling of x is red. The sibling is the other child of x's parent, which is not x itself. In this case, we recolor the parent of x and x.sibling then we left rotate around x's parent. In the following cases s = sibling of x, (x) = red, {x} = black, |x| = red/black. ``` | | {p} {s} / \ ~> / \ {x} (s) (p) [D] / \ / \ / \ [A] [B] [C] [D] {x} [C] / \ [A] [B] ``` **Case 2:** The sibling of x is black and has two black children. Here, we recolor x.sibling to red, move x upwards to x.parent and check again for this newX. ``` | | |p| |newX| / \ ~> / \ {x} {s} {x} (s) / \ / \ / \ / \ [A] [B] {l} {r} [A] [B] {l} {r} / \ / \ / \ / \ [C][D][E][F] [C][D][E][F] ``` **Case 3:** The sibling of x is black with one black child to the right. In this case, we recolor the sibling to red and sibling.leftChild to black, then we right rotate around the sibling. After this we have case 4. ``` | | |p| |p| / \ ~> / \ {x} {s} {x} {l} / \ / \ / \ / \ [A] [B] (l) {r} [A] [B] [C] (s) / \ / \ / \ [C][D][E][F] [D]{e} / \ [E] [F] ``` **Case 4:** The sibling of x is black with one red child to the right. Here, we recolor the sibling to the color of x.parent and x.parent and sibling.rightChild to black. Then we left rotate around x.parent. After this operation we have a valid red-black tree. Here, ||x|| denotes that x can have either color red or black, but that this can be different to |x| color. This is important, as s gets the same color as p. ``` | | ||p|| ||s|| / \ ~> / \ {x} {s} {p} {r} / \ / \ / \ / \ [A] [B] |l| (r) {x} |l| [E] [F] / \ / \ / \ / \ [C][D][E][F] [A][B][C][D] ``` Running time of this algorithm: * Only case 2 can repeat, but this only h many times, where h is the height of the tree * Case 1 -> case 2 -> red-black tree Case 1 -> case 3 -> case 4 -> red-black tree Case 1 -> case 4 -> red-black tree * Case 3 -> case 4 -> red-black tree * Case 4 -> red-black tree As we perform case 2 at most O(log n) times and all other steps at most once, we have O(log n) recolorings and at most 3 rotations. The overall runtime of delete is O(log n). ## Resources: [CLRS] T. Cormen, C. Leiserson, R. Rivest, and C. Stein. "Introduction to Algorithms", Third Edition. 2009 *Written for Swift Algorithm Club by Ute Schiehlen. Updated from Jaap Wijnen and Ashwin Raghuraman's contributions. Swift 4.2 check by Bruno Scheele.* ================================================ FILE: Red-Black Tree/RedBlackTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // Test for the RedBlackTree implementation provided in the Source folder of this Playground import Foundation let redBlackTree = RedBlackTree() let randomMax = Double(0x10000000) var values = [Double]() for i in 0..<1000 { let value = Double(arc4random()) / randomMax values.append(value) redBlackTree.insert(key: value) if i % 100 == 0 { redBlackTree.verify() } } redBlackTree.verify() for i in 0..<1000 { let rand = arc4random_uniform(UInt32(values.count)) let index = Int(rand) let value = values.remove(at: index) redBlackTree.delete(key: value) if i % 100 == 0 { redBlackTree.verify() } } redBlackTree.verify() ================================================ FILE: Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift ================================================ //Copyright (c) 2016 Matthijs Hollemans and contributors // //Permission is hereby granted, free of charge, to any person obtaining a copy //of this software and associated documentation files (the "Software"), to deal //in the Software without restriction, including without limitation the rights //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell //copies of the Software, and to permit persons to whom the Software is //furnished to do so, subject to the following conditions: // //The above copyright notice and this permission notice shall be included in //all copies or substantial portions of the Software. // //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN //THE SOFTWARE. import Foundation private enum RBTreeColor { case red case black } private enum RotationDirection { case left case right } // MARK: - RBNode public class RBTreeNode: Equatable { public typealias RBNode = RBTreeNode fileprivate var color: RBTreeColor = .black fileprivate var key: T? var leftChild: RBNode? var rightChild: RBNode? fileprivate weak var parent: RBNode? public init(key: T?, leftChild: RBNode?, rightChild: RBNode?, parent: RBNode?) { self.key = key self.leftChild = leftChild self.rightChild = rightChild self.parent = parent self.leftChild?.parent = self self.rightChild?.parent = self } public convenience init(key: T?) { self.init(key: key, leftChild: RBNode(), rightChild: RBNode(), parent: RBNode()) } // For initialising the nullLeaf public convenience init() { self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil) self.color = .black } var isRoot: Bool { return parent == nil } var isLeaf: Bool { return rightChild == nil && leftChild == nil } var isNullLeaf: Bool { return key == nil && isLeaf && color == .black } var isLeftChild: Bool { return parent?.leftChild === self } var isRightChild: Bool { return parent?.rightChild === self } var grandparent: RBNode? { return parent?.parent } var sibling: RBNode? { if isLeftChild { return parent?.rightChild } else { return parent?.leftChild } } var uncle: RBNode? { return parent?.sibling } public func getKey() -> T? { return key } } // MARK: - RedBlackTree public class RedBlackTree { public typealias RBNode = RBTreeNode fileprivate(set) var root: RBNode fileprivate(set) var size = 0 fileprivate let nullLeaf = RBNode() fileprivate let allowDuplicateNode: Bool public init(_ allowDuplicateNode: Bool = false) { root = nullLeaf self.allowDuplicateNode = allowDuplicateNode } } // MARK: - Size extension RedBlackTree { public func count() -> Int { return size } public func isEmpty() -> Bool { return size == 0 } public func allElements() -> [T] { var nodes: [T] = [] getAllElements(node: root, nodes: &nodes) return nodes } private func getAllElements(node: RBTreeNode, nodes: inout [T]) { guard !node.isNullLeaf else { return } if let left = node.leftChild { getAllElements(node: left, nodes: &nodes) } if let key = node.key { nodes.append(key) } if let right = node.rightChild { getAllElements(node: right, nodes: &nodes) } } } // MARK: - Equatable protocol extension RBTreeNode { static public func == (lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { return lhs.key == rhs.key } } // MARK: - Finding a nodes successor and predecessor extension RBTreeNode { /* * Returns the inorder successor node of a node * The successor is a node with the next larger key value of the current node */ public func getSuccessor() -> RBNode? { // If node has right child: successor min of this right tree if let rightChild = self.rightChild { if !rightChild.isNullLeaf { return rightChild.minimum() } } // Else go upward until node left child var currentNode = self var parent = currentNode.parent while currentNode.isRightChild { if let parent = parent { currentNode = parent } parent = currentNode.parent } return parent } /* * Returns the inorder predecessor node of a node * The predecessor is a node with the next smaller key value of the current node */ public func getPredecessor() -> RBNode? { // if node has left child: predecessor is min of this left tree if let leftChild = leftChild, !leftChild.isNullLeaf { return leftChild.maximum() } // else go upward while node is left child var currentNode = self var parent = currentNode.parent while currentNode.isLeftChild { if let parent = parent { currentNode = parent } parent = currentNode.parent } return parent } } // MARK: - Searching extension RBTreeNode { /* * Returns the node with the minimum key of the current subtree */ public func minimum() -> RBNode? { if let leftChild = leftChild { if !leftChild.isNullLeaf { return leftChild.minimum() } return self } return self } /* * Returns the node with the maximum key of the current subtree */ public func maximum() -> RBNode? { if let rightChild = rightChild { if !rightChild.isNullLeaf { return rightChild.maximum() } return self } return self } } extension RedBlackTree { /* * Returns the node with the given key |input| if existing */ public func search(input: T) -> RBNode? { return search(key: input, node: root) } /* * Returns the node with given |key| in subtree of |node| */ fileprivate func search(key: T, node: RBNode?) -> RBNode? { // If node nil -> key not found guard let node = node else { return nil } // If node is nullLeaf == semantically same as if nil if !node.isNullLeaf { if let nodeKey = node.key { // Node found if key == nodeKey { return node } else if key < nodeKey { return search(key: key, node: node.leftChild) } else { return search(key: key, node: node.rightChild) } } } return nil } } // MARK: - Finding maximum and minimum value extension RedBlackTree { /* * Returns the minimum key value of the whole tree */ public func minValue() -> T? { guard let minNode = root.minimum() else { return nil } return minNode.key } /* * Returns the maximum key value of the whole tree */ public func maxValue() -> T? { guard let maxNode = root.maximum() else { return nil } return maxNode.key } } // MARK: - Inserting new nodes extension RedBlackTree { /* * Insert a node with key |key| into the tree * 1. Perform normal insert operation as in a binary search tree * 2. Fix red-black properties * Runntime: O(log n) */ public func insert(key: T) { // If key must be unique and find the key already existed, quit if search(input: key) != nil && !allowDuplicateNode { return } if root.isNullLeaf { root = RBNode(key: key) } else { insert(input: RBNode(key: key), node: root) } size += 1 } /* * Nearly identical insert operation as in a binary search tree * Differences: All nil pointers are replaced by the nullLeaf, we color the inserted node red, * after inserting we call insertFixup to maintain the red-black properties */ private func insert(input: RBNode, node: RBNode) { guard let inputKey = input.key, let nodeKey = node.key else { return } if inputKey < nodeKey { guard let child = node.leftChild else { addAsLeftChild(child: input, parent: node) return } if child.isNullLeaf { addAsLeftChild(child: input, parent: node) } else { insert(input: input, node: child) } } else { guard let child = node.rightChild else { addAsRightChild(child: input, parent: node) return } if child.isNullLeaf { addAsRightChild(child: input, parent: node) } else { insert(input: input, node: child) } } } private func addAsLeftChild(child: RBNode, parent: RBNode) { parent.leftChild = child child.parent = parent child.color = .red insertFixup(node: child) } private func addAsRightChild(child: RBNode, parent: RBNode) { parent.rightChild = child child.parent = parent child.color = .red insertFixup(node: child) } /* * Fixes possible violations of the red-black property after insertion * Only violation of red-black properties occurs at inserted node |z| and z.parent * We have 3 distinct cases: case 1, 2a and 2b * - case 1: may repeat, but only h/2 steps, where h is the height of the tree * - case 2a -> case 2b -> red-black tree * - case 2b -> red-black tree */ private func insertFixup(node z: RBNode) { if !z.isNullLeaf { guard let parentZ = z.parent else { return } // If both |z| and his parent are red -> violation of red-black property -> need to fix it if parentZ.color == .red { guard let uncle = z.uncle else { return } // Case 1: Uncle red -> recolor + move z if uncle.color == .red { parentZ.color = .black uncle.color = .black if let grandparentZ = parentZ.parent { grandparentZ.color = .red // Move z to grandparent and check again insertFixup(node: grandparentZ) } } // Case 2: Uncle black else { var zNew = z // Case 2.a: z right child -> rotate if parentZ.isLeftChild && z.isRightChild { zNew = parentZ leftRotate(node: zNew) } else if parentZ.isRightChild && z.isLeftChild { zNew = parentZ rightRotate(node: zNew) } // Case 2.b: z left child -> recolor + rotate zNew.parent?.color = .black if let grandparentZnew = zNew.grandparent { grandparentZnew.color = .red if z.isLeftChild { rightRotate(node: grandparentZnew) } else { leftRotate(node: grandparentZnew) } // We have a valid red-black-tree } } } } root.color = .black } } // MARK: - Deleting a node extension RedBlackTree { /* * Delete a node with key |key| from the tree * 1. Perform standard delete operation as in a binary search tree * 2. Fix red-black properties * Runntime: O(log n) */ public func delete(key: T) { if size == 1 { root = nullLeaf size -= 1 } else if let node = search(key: key, node: root) { if !node.isNullLeaf { delete(node: node) size -= 1 } } } /* * Nearly identical delete operation as in a binary search tree * Differences: All nil pointers are replaced by the nullLeaf, * after deleting we call insertFixup to maintain the red-black properties if the delted node was * black (as if it was red -> no violation of red-black properties) */ private func delete(node z: RBNode) { var nodeY = RBNode() var nodeX = RBNode() if let leftChild = z.leftChild, let rightChild = z.rightChild { if leftChild.isNullLeaf || rightChild.isNullLeaf { nodeY = z } else { if let successor = z.getSuccessor() { nodeY = successor } } } if let leftChild = nodeY.leftChild { if !leftChild.isNullLeaf { nodeX = leftChild } else if let rightChild = nodeY.rightChild { nodeX = rightChild } } nodeX.parent = nodeY.parent if let parentY = nodeY.parent { // Should never be the case, as parent of root = nil if parentY.isNullLeaf { root = nodeX } else { if nodeY.isLeftChild { parentY.leftChild = nodeX } else { parentY.rightChild = nodeX } } } else { root = nodeX } if nodeY != z { z.key = nodeY.key } // If sliced out node was red -> nothing to do as red-black-property holds // If it was black -> fix red-black-property if nodeY.color == .black { deleteFixup(node: nodeX) } } /* * Fixes possible violations of the red-black property after deletion * We have w distinct cases: only case 2 may repeat, but only h many steps, where h is the height * of the tree * - case 1 -> case 2 -> red-black tree * case 1 -> case 3 -> case 4 -> red-black tree * case 1 -> case 4 -> red-black tree * - case 3 -> case 4 -> red-black tree * - case 4 -> red-black tree */ private func deleteFixup(node x: RBNode) { var xTmp = x if !x.isRoot && x.color == .black { guard var sibling = x.sibling else { return } // Case 1: Sibling of x is red if sibling.color == .red { // Recolor sibling.color = .black if let parentX = x.parent { parentX.color = .red // Rotation if x.isLeftChild { leftRotate(node: parentX) } else { rightRotate(node: parentX) } // Update sibling if let sibl = x.sibling { sibling = sibl } } } // Case 2: Sibling is black with two black children if sibling.leftChild?.color == .black && sibling.rightChild?.color == .black { // Recolor sibling.color = .red // Move fake black unit upwards if let parentX = x.parent { deleteFixup(node: parentX) } // We have a valid red-black-tree } else { // Case 3: a. Sibling black with one black child to the right if x.isLeftChild && sibling.rightChild?.color == .black { // Recolor sibling.leftChild?.color = .black sibling.color = .red // Rotate rightRotate(node: sibling) // Update sibling of x if let sibl = x.sibling { sibling = sibl } } // Still case 3: b. One black child to the left else if x.isRightChild && sibling.leftChild?.color == .black { // Recolor sibling.rightChild?.color = .black sibling.color = .red // Rotate leftRotate(node: sibling) // Update sibling of x if let sibl = x.sibling { sibling = sibl } } // Case 4: Sibling is black with red right child // Recolor if let parentX = x.parent { sibling.color = parentX.color parentX.color = .black // a. x left and sibling with red right child if x.isLeftChild { sibling.rightChild?.color = .black // Rotate leftRotate(node: parentX) } // b. x right and sibling with red left child else { sibling.leftChild?.color = .black //Rotate rightRotate(node: parentX) } // We have a valid red-black-tree xTmp = root } } } xTmp.color = .black } } // MARK: - Rotation extension RedBlackTree { /* * Left rotation around node x * Assumes that x.rightChild y is not a nullLeaf, rotates around the link from x to y, * makes y the new root of the subtree with x as y's left child and y's left child as x's right * child, where n = a node, [n] = a subtree * | | * x y * / \ ~> / \ * [A] y x [C] * / \ / \ * [B] [C] [A] [B] */ fileprivate func leftRotate(node x: RBNode) { rotate(node: x, direction: .left) } /* * Right rotation around node y * Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, * makes x the new root of the subtree with y as x's right child and x's right child as y's left * child, where n = a node, [n] = a subtree * | | * x y * / \ <~ / \ * [A] y x [C] * / \ / \ * [B] [C] [A] [B] */ fileprivate func rightRotate(node x: RBNode) { rotate(node: x, direction: .right) } /* * Rotation around a node x * Is a local operation preserving the binary-search-tree property that only exchanges pointers. * Runntime: O(1) */ private func rotate(node x: RBNode, direction: RotationDirection) { var nodeY: RBNode? = RBNode() // Set |nodeY| and turn |nodeY|'s left/right subtree into |x|'s right/left subtree switch direction { case .left: nodeY = x.rightChild x.rightChild = nodeY?.leftChild x.rightChild?.parent = x case .right: nodeY = x.leftChild x.leftChild = nodeY?.rightChild x.leftChild?.parent = x } // Link |x|'s parent to nodeY nodeY?.parent = x.parent if x.isRoot { if let node = nodeY { root = node } } else if x.isLeftChild { x.parent?.leftChild = nodeY } else if x.isRightChild { x.parent?.rightChild = nodeY } // Put |x| on |nodeY|'s left switch direction { case .left: nodeY?.leftChild = x case .right: nodeY?.rightChild = x } x.parent = nodeY } } // MARK: - Verify extension RedBlackTree { /* * Verifies that the existing tree fulfills all red-black properties * Returns true if the tree is a valid red-black tree, false otherwise */ public func verify() -> Bool { if root.isNullLeaf { print("The tree is empty") return true } return property2() && property4() && property5() } // Property 1: Every node is either red or black -> fullfilled through setting node.color of type // RBTreeColor // Property 2: The root is black private func property2() -> Bool { if root.color == .red { print("Property-Error: Root is red") return false } return true } // Property 3: Every nullLeaf is black -> fullfilled through initialising nullLeafs with color = black // Property 4: If a node is red, then both its children are black private func property4() -> Bool { return property4(node: root) } private func property4(node: RBNode) -> Bool { if node.isNullLeaf { return true } if let leftChild = node.leftChild, let rightChild = node.rightChild { if node.color == .red { if !leftChild.isNullLeaf && leftChild.color == .red { print("Property-Error: Red node with key \(String(describing: node.key)) has red left child") return false } if !rightChild.isNullLeaf && rightChild.color == .red { print("Property-Error: Red node with key \(String(describing: node.key)) has red right child") return false } } return property4(node: leftChild) && property4(node: rightChild) } return false } // Property 5: For each node, all paths from the node to descendant leaves contain the same number // of black nodes (same blackheight) private func property5() -> Bool { if property5(node: root) == -1 { return false } else { return true } } private func property5(node: RBNode) -> Int { if node.isNullLeaf { return 0 } guard let leftChild = node.leftChild, let rightChild = node.rightChild else { return -1 } let left = property5(node: leftChild) let right = property5(node: rightChild) if left == -1 || right == -1 { return -1 } else if left == right { let addedHeight = node.color == .black ? 1 : 0 return left + addedHeight } else { print("Property-Error: Black height violated at node with key \(String(describing: node.key))") return -1 } } } // MARK: - Debugging extension RBTreeNode: CustomDebugStringConvertible { public var debugDescription: String { var s = "" if isNullLeaf { s = "nullLeaf" } else { if let key = key { s = "key: \(key)" } else { s = "key: nil" } if let parent = parent { s += ", parent: \(String(describing: parent.key))" } if let left = leftChild { s += ", left = [" + left.debugDescription + "]" } if let right = rightChild { s += ", right = [" + right.debugDescription + "]" } s += ", color = \(color)" } return s } } extension RedBlackTree: CustomDebugStringConvertible { public var debugDescription: String { return root.debugDescription } } extension RBTreeNode: CustomStringConvertible { public var description: String { var s = "" if isNullLeaf { s += "nullLeaf" } else { if let left = leftChild { s += "(\(left.description)) <- " } if let key = key { s += "\(key)" } else { s += "nil" } s += ", \(color)" if let right = rightChild { s += " -> (\(right.description))" } } return s } } extension RedBlackTree: CustomStringConvertible { public var description: String { if root.isNullLeaf { return "[]" } else { return root.description } } } ================================================ FILE: Red-Black Tree/RedBlackTree.playground/contents.xcplayground ================================================ ================================================ FILE: Red-Black Tree/RedBlackTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Red-Black Tree/RedBlackTree.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Red-Black Tree/RedBlackTree.swift ================================================ //Copyright (c) 2016 Matthijs Hollemans and contributors // //Permission is hereby granted, free of charge, to any person obtaining a copy //of this software and associated documentation files (the "Software"), to deal //in the Software without restriction, including without limitation the rights //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell //copies of the Software, and to permit persons to whom the Software is //furnished to do so, subject to the following conditions: // //The above copyright notice and this permission notice shall be included in //all copies or substantial portions of the Software. // //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN //THE SOFTWARE. import Foundation private enum RBTreeColor { case red case black } private enum RotationDirection { case left case right } // MARK: - RBNode public class RBTreeNode: Equatable { public typealias RBNode = RBTreeNode fileprivate var color: RBTreeColor = .black fileprivate var key: T? var leftChild: RBNode? var rightChild: RBNode? fileprivate weak var parent: RBNode? public init(key: T?, leftChild: RBNode?, rightChild: RBNode?, parent: RBNode?) { self.key = key self.leftChild = leftChild self.rightChild = rightChild self.parent = parent self.leftChild?.parent = self self.rightChild?.parent = self } public convenience init(key: T?) { self.init(key: key, leftChild: RBNode(), rightChild: RBNode(), parent: RBNode()) } // For initialising the nullLeaf public convenience init() { self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil) self.color = .black } var isRoot: Bool { return parent == nil } var isLeaf: Bool { return rightChild == nil && leftChild == nil } var isNullLeaf: Bool { return key == nil && isLeaf && color == .black } var isLeftChild: Bool { return parent?.leftChild === self } var isRightChild: Bool { return parent?.rightChild === self } var grandparent: RBNode? { return parent?.parent } var sibling: RBNode? { if isLeftChild { return parent?.rightChild } else { return parent?.leftChild } } var uncle: RBNode? { return parent?.sibling } } // MARK: - RedBlackTree public class RedBlackTree { public typealias RBNode = RBTreeNode fileprivate(set) var root: RBNode fileprivate(set) var size = 0 fileprivate let nullLeaf = RBNode() fileprivate let allowDuplicateNode: Bool public init(_ allowDuplicateNode: Bool = false) { root = nullLeaf self.allowDuplicateNode = allowDuplicateNode } } // MARK: - Size extension RedBlackTree { public func count() -> Int { return size } public func isEmpty() -> Bool { return size == 0 } public func allElements() -> [T] { var nodes: [T] = [] getAllElements(node: root, nodes: &nodes) return nodes } private func getAllElements(node: RBTreeNode, nodes: inout [T]) { guard !node.isNullLeaf else { return } if let left = node.leftChild { getAllElements(node: left, nodes: &nodes) } if let key = node.key { nodes.append(key) } if let right = node.rightChild { getAllElements(node: right, nodes: &nodes) } } } // MARK: - Equatable protocol extension RBTreeNode { static public func == (lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { return lhs.key == rhs.key } } // MARK: - Finding a nodes successor extension RBTreeNode { /* * Returns the inorder successor node of a node * The successor is a node with the next larger key value of the current node */ public func getSuccessor() -> RBNode? { // If node has right child: successor min of this right tree if let rightChild = self.rightChild { if !rightChild.isNullLeaf { return rightChild.minimum() } } // Else go upward until node left child var currentNode = self var parent = currentNode.parent while currentNode.isRightChild { if let parent = parent { currentNode = parent } parent = currentNode.parent } return parent } } // MARK: - Searching extension RBTreeNode { /* * Returns the node with the minimum key of the current subtree */ public func minimum() -> RBNode? { if let leftChild = leftChild { if !leftChild.isNullLeaf { return leftChild.minimum() } return self } return self } /* * Returns the node with the maximum key of the current subtree */ public func maximum() -> RBNode? { if let rightChild = rightChild { if !rightChild.isNullLeaf { return rightChild.maximum() } return self } return self } } extension RedBlackTree { /* * Returns the node with the given key |input| if existing */ public func search(input: T) -> RBNode? { return search(key: input, node: root) } /* * Returns the node with given |key| in subtree of |node| */ fileprivate func search(key: T, node: RBNode?) -> RBNode? { // If node nil -> key not found guard let node = node else { return nil } // If node is nullLeaf == semantically same as if nil if !node.isNullLeaf { if let nodeKey = node.key { // Node found if key == nodeKey { return node } else if key < nodeKey { return search(key: key, node: node.leftChild) } else { return search(key: key, node: node.rightChild) } } } return nil } } // MARK: - Finding maximum and minimum value extension RedBlackTree { /* * Returns the minimum key value of the whole tree */ public func minValue() -> T? { guard let minNode = root.minimum() else { return nil } return minNode.key } /* * Returns the maximum key value of the whole tree */ public func maxValue() -> T? { guard let maxNode = root.maximum() else { return nil } return maxNode.key } } // MARK: - Inserting new nodes extension RedBlackTree { /* * Insert a node with key |key| into the tree * 1. Perform normal insert operation as in a binary search tree * 2. Fix red-black properties * Runntime: O(log n) */ public func insert(key: T) { // If key must be unique and find the key already existed, quit if search(input: key) != nil && !allowDuplicateNode { return } if root.isNullLeaf { root = RBNode(key: key) } else { insert(input: RBNode(key: key), node: root) } size += 1 } /* * Nearly identical insert operation as in a binary search tree * Differences: All nil pointers are replaced by the nullLeaf, we color the inserted node red, * after inserting we call insertFixup to maintain the red-black properties */ private func insert(input: RBNode, node: RBNode) { guard let inputKey = input.key, let nodeKey = node.key else { return } if inputKey < nodeKey { guard let child = node.leftChild else { addAsLeftChild(child: input, parent: node) return } if child.isNullLeaf { addAsLeftChild(child: input, parent: node) } else { insert(input: input, node: child) } } else { guard let child = node.rightChild else { addAsRightChild(child: input, parent: node) return } if child.isNullLeaf { addAsRightChild(child: input, parent: node) } else { insert(input: input, node: child) } } } private func addAsLeftChild(child: RBNode, parent: RBNode) { parent.leftChild = child child.parent = parent child.color = .red insertFixup(node: child) } private func addAsRightChild(child: RBNode, parent: RBNode) { parent.rightChild = child child.parent = parent child.color = .red insertFixup(node: child) } /* * Fixes possible violations of the red-black property after insertion * Only violation of red-black properties occurs at inserted node |z| and z.parent * We have 3 distinct cases: case 1, 2a and 2b * - case 1: may repeat, but only h/2 steps, where h is the height of the tree * - case 2a -> case 2b -> red-black tree * - case 2b -> red-black tree */ private func insertFixup(node z: RBNode) { if !z.isNullLeaf { guard let parentZ = z.parent else { return } // If both |z| and his parent are red -> violation of red-black property -> need to fix it if parentZ.color == .red { guard let uncle = z.uncle else { return } // Case 1: Uncle red -> recolor + move z if uncle.color == .red { parentZ.color = .black uncle.color = .black if let grandparentZ = parentZ.parent { grandparentZ.color = .red // Move z to grandparent and check again insertFixup(node: grandparentZ) } } // Case 2: Uncle black else { var zNew = z // Case 2.a: z right child -> rotate if parentZ.isLeftChild && z.isRightChild { zNew = parentZ leftRotate(node: zNew) } else if parentZ.isRightChild && z.isLeftChild { zNew = parentZ rightRotate(node: zNew) } // Case 2.b: z left child -> recolor + rotate zNew.parent?.color = .black if let grandparentZnew = zNew.grandparent { grandparentZnew.color = .red if z.isLeftChild { rightRotate(node: grandparentZnew) } else { leftRotate(node: grandparentZnew) } // We have a valid red-black-tree } } } } root.color = .black } } // MARK: - Deleting a node extension RedBlackTree { /* * Delete a node with key |key| from the tree * 1. Perform standard delete operation as in a binary search tree * 2. Fix red-black properties * Runntime: O(log n) */ public func delete(key: T) { if size == 1 { root = nullLeaf size -= 1 } else if let node = search(key: key, node: root) { if !node.isNullLeaf { delete(node: node) size -= 1 } } } /* * Nearly identical delete operation as in a binary search tree * Differences: All nil pointers are replaced by the nullLeaf, * after deleting we call insertFixup to maintain the red-black properties if the delted node was * black (as if it was red -> no violation of red-black properties) */ private func delete(node z: RBNode) { var nodeY = RBNode() var nodeX = RBNode() if let leftChild = z.leftChild, let rightChild = z.rightChild { if leftChild.isNullLeaf || rightChild.isNullLeaf { nodeY = z } else { if let successor = z.getSuccessor() { nodeY = successor } } } if let leftChild = nodeY.leftChild { if !leftChild.isNullLeaf { nodeX = leftChild } else if let rightChild = nodeY.rightChild { nodeX = rightChild } } nodeX.parent = nodeY.parent if let parentY = nodeY.parent { // Should never be the case, as parent of root = nil if parentY.isNullLeaf { root = nodeX } else { if nodeY.isLeftChild { parentY.leftChild = nodeX } else { parentY.rightChild = nodeX } } } else { root = nodeX } if nodeY != z { z.key = nodeY.key } // If sliced out node was red -> nothing to do as red-black-property holds // If it was black -> fix red-black-property if nodeY.color == .black { deleteFixup(node: nodeX) } } /* * Fixes possible violations of the red-black property after deletion * We have w distinct cases: only case 2 may repeat, but only h many steps, where h is the height * of the tree * - case 1 -> case 2 -> red-black tree * case 1 -> case 3 -> case 4 -> red-black tree * case 1 -> case 4 -> red-black tree * - case 3 -> case 4 -> red-black tree * - case 4 -> red-black tree */ private func deleteFixup(node x: RBNode) { var xTmp = x if !x.isRoot && x.color == .black { guard var sibling = x.sibling else { return } // Case 1: Sibling of x is red if sibling.color == .red { // Recolor sibling.color = .black if let parentX = x.parent { parentX.color = .red // Rotation if x.isLeftChild { leftRotate(node: parentX) } else { rightRotate(node: parentX) } // Update sibling if let sibl = x.sibling { sibling = sibl } } } // Case 2: Sibling is black with two black children if sibling.leftChild?.color == .black && sibling.rightChild?.color == .black { // Recolor sibling.color = .red // Move fake black unit upwards if let parentX = x.parent { deleteFixup(node: parentX) } // We have a valid red-black-tree } else { // Case 3: a. Sibling black with one black child to the right if x.isLeftChild && sibling.rightChild?.color == .black { // Recolor sibling.leftChild?.color = .black sibling.color = .red // Rotate rightRotate(node: sibling) // Update sibling of x if let sibl = x.sibling { sibling = sibl } } // Still case 3: b. One black child to the left else if x.isRightChild && sibling.leftChild?.color == .black { // Recolor sibling.rightChild?.color = .black sibling.color = .red // Rotate leftRotate(node: sibling) // Update sibling of x if let sibl = x.sibling { sibling = sibl } } // Case 4: Sibling is black with red right child // Recolor if let parentX = x.parent { sibling.color = parentX.color parentX.color = .black // a. x left and sibling with red right child if x.isLeftChild { sibling.rightChild?.color = .black // Rotate leftRotate(node: parentX) } // b. x right and sibling with red left child else { sibling.leftChild?.color = .black //Rotate rightRotate(node: parentX) } // We have a valid red-black-tree xTmp = root } } } xTmp.color = .black } } // MARK: - Rotation extension RedBlackTree { /* * Left rotation around node x * Assumes that x.rightChild y is not a nullLeaf, rotates around the link from x to y, * makes y the new root of the subtree with x as y's left child and y's left child as x's right * child, where n = a node, [n] = a subtree * | | * x y * / \ ~> / \ * [A] y x [C] * / \ / \ * [B] [C] [A] [B] */ fileprivate func leftRotate(node x: RBNode) { rotate(node: x, direction: .left) } /* * Right rotation around node y * Assumes that y.leftChild x is not a nullLeaf, rotates around the link from y to x, * makes x the new root of the subtree with y as x's right child and x's right child as y's left * child, where n = a node, [n] = a subtree * | | * x y * / \ <~ / \ * [A] y x [C] * / \ / \ * [B] [C] [A] [B] */ fileprivate func rightRotate(node x: RBNode) { rotate(node: x, direction: .right) } /* * Rotation around a node x * Is a local operation preserving the binary-search-tree property that only exchanges pointers. * Runntime: O(1) */ private func rotate(node x: RBNode, direction: RotationDirection) { var nodeY: RBNode? = RBNode() // Set |nodeY| and turn |nodeY|'s left/right subtree into |x|'s right/left subtree switch direction { case .left: nodeY = x.rightChild x.rightChild = nodeY?.leftChild x.rightChild?.parent = x case .right: nodeY = x.leftChild x.leftChild = nodeY?.rightChild x.leftChild?.parent = x } // Link |x|'s parent to nodeY nodeY?.parent = x.parent if x.isRoot { if let node = nodeY { root = node } } else if x.isLeftChild { x.parent?.leftChild = nodeY } else if x.isRightChild { x.parent?.rightChild = nodeY } // Put |x| on |nodeY|'s left switch direction { case .left: nodeY?.leftChild = x case .right: nodeY?.rightChild = x } x.parent = nodeY } } // MARK: - Verify extension RedBlackTree { /* * Verifies that the existing tree fulfills all red-black properties * Returns true if the tree is a valid red-black tree, false otherwise */ public func verify() -> Bool { if root.isNullLeaf { print("The tree is empty") return true } return property2() && property4() && property5() } // Property 1: Every node is either red or black -> fullfilled through setting node.color of type // RBTreeColor // Property 2: The root is black private func property2() -> Bool { if root.color == .red { print("Property-Error: Root is red") return false } return true } // Property 3: Every nullLeaf is black -> fullfilled through initialising nullLeafs with color = black // Property 4: If a node is red, then both its children are black private func property4() -> Bool { return property4(node: root) } private func property4(node: RBNode) -> Bool { if node.isNullLeaf { return true } if let leftChild = node.leftChild, let rightChild = node.rightChild { if node.color == .red { if !leftChild.isNullLeaf && leftChild.color == .red { print("Property-Error: Red node with key \(String(describing: node.key)) has red left child") return false } if !rightChild.isNullLeaf && rightChild.color == .red { print("Property-Error: Red node with key \(String(describing: node.key)) has red right child") return false } } return property4(node: leftChild) && property4(node: rightChild) } return false } // Property 5: For each node, all paths from the node to descendant leaves contain the same number // of black nodes (same blackheight) private func property5() -> Bool { if property5(node: root) == -1 { return false } else { return true } } private func property5(node: RBNode) -> Int { if node.isNullLeaf { return 0 } guard let leftChild = node.leftChild, let rightChild = node.rightChild else { return -1 } let left = property5(node: leftChild) let right = property5(node: rightChild) if left == -1 || right == -1 { return -1 } else if left == right { let addedHeight = node.color == .black ? 1 : 0 return left + addedHeight } else { print("Property-Error: Black height violated at node with key \(String(describing: node.key))") return -1 } } } // MARK: - Debugging extension RBTreeNode: CustomDebugStringConvertible { public var debugDescription: String { var s = "" if isNullLeaf { s = "nullLeaf" } else { if let key = key { s = "key: \(key)" } else { s = "key: nil" } if let parent = parent { s += ", parent: \(String(describing: parent.key))" } if let left = leftChild { s += ", left = [" + left.debugDescription + "]" } if let right = rightChild { s += ", right = [" + right.debugDescription + "]" } s += ", color = \(color)" } return s } } extension RedBlackTree: CustomDebugStringConvertible { public var debugDescription: String { return root.debugDescription } } extension RBTreeNode: CustomStringConvertible { public var description: String { var s = "" if isNullLeaf { s += "nullLeaf" } else { if let left = leftChild { s += "(\(left.description)) <- " } if let key = key { s += "\(key)" } else { s += "nil" } s += ", \(color)" if let right = rightChild { s += " -> (\(right.description))" } } return s } } extension RedBlackTree: CustomStringConvertible { public var description: String { if root.isNullLeaf { return "[]" } else { return root.description } } } ================================================ FILE: Ring Buffer/README.markdown ================================================ # Ring Buffer Also known as a circular buffer. The problem with a [queue based on an array](../Queue/) is that adding new items to the back of the queue is fast, **O(1)**, but removing items from the front of the queue is slow, **O(n)**. Removing is slow because it requires the remaining array elements to be shifted in memory. A more efficient way to implement a queue is to use a ring buffer or circular buffer. This is an array that conceptually wraps around back to the beginning, so you never have to remove any items. All operations are **O(1)**. Here is how it works in principle. We have an array of a fixed size, say 5 items: [ , , , , ] r w Initially, the array is empty and the read (`r`) and write (`w`) pointers are at the beginning. Let's add some data to this array. We'll write, or "enqueue", the number `123`: [ 123, , , , ] r ---> w Each time we add data, the write pointer moves one step forward. Let's add a few more elements: [ 123, 456, 789, 666, ] r -------------> w There is now one open spot left in the array, but rather than enqueuing another item the app decides to read some data. That's possible because the write pointer is ahead of the read pointer, meaning data is available for reading. The read pointer advances as we read the available data: [ 123, 456, 789, 666, ] ---> r w Let's read two more items: [ 123, 456, 789, 666, ] --------> r w Now the app decides it's time to write again and enqueues two more data items, `333` and `555`: [ 123, 456, 789, 666, 333 ] r ---> w Whoops, the write pointer has reached the end of the array, so there is no more room for object `555`. What now? Well, this is why it's a circular buffer: we wrap the write pointer back to the beginning and write the remaining data: [ 555, 456, 789, 666, 333 ] ---> w r We can now read the remaining three items, `666`, `333`, and `555`. [ 555, 456, 789, 666, 333 ] w --------> r Of course, as the read pointer reaches the end of the buffer it also wraps around: [ 555, 456, 789, 666, 333 ] w ---> r And now the buffer is empty again because the read pointer has caught up with the write pointer. Here is a very basic implementation in Swift: ```swift public struct RingBuffer { fileprivate var array: [T?] fileprivate var readIndex = 0 fileprivate var writeIndex = 0 public init(count: Int) { array = [T?](repeating: nil, count: count) } public mutating func write(_ element: T) -> Bool { if !isFull { array[writeIndex % array.count] = element writeIndex += 1 return true } else { return false } } public mutating func read() -> T? { if !isEmpty { let element = array[readIndex % array.count] readIndex += 1 return element } else { return nil } } fileprivate var availableSpaceForReading: Int { return writeIndex - readIndex } public var isEmpty: Bool { return availableSpaceForReading == 0 } fileprivate var availableSpaceForWriting: Int { return array.count - availableSpaceForReading } public var isFull: Bool { return availableSpaceForWriting == 0 } } ``` The `RingBuffer` object has an array for the actual storage of the data, and `readIndex` and `writeIndex` variables for the "pointers" into the array. The `write()` function puts the new element into the array at the `writeIndex`, and the `read()` function returns the element at the `readIndex`. But hold up, you say, how does this wrapping around work? There are several ways to accomplish this and I chose a slightly controversial one. In this implementation, the `writeIndex` and `readIndex` always increment and never actually wrap around. Instead, we do the following to find the actual index into the array: ```swift array[writeIndex % array.count] ``` and: ```swift array[readIndex % array.count] ``` In other words, we take the modulo (or the remainder) of the read index and write index divided by the size of the underlying array. The reason this is a bit controversial is that `writeIndex` and `readIndex` always increment, so in theory these values could become too large to fit into an integer and the app will crash. However, a quick back-of-the-napkin calculation should take away those fears. Both `writeIndex` and `readIndex` are 64-bit integers. If we assume that they are incremented 1000 times per second, which is a lot, then doing this continuously for one year requires `ceil(log_2(365 * 24 * 60 * 60 * 1000)) = 35` bits. That leaves 28 bits to spare, so that should give you about 2^28 years before running into problems. That's a long time. :-) To play with this ring buffer, copy the code to a playground and do the following to mimic the example above: ```swift var buffer = RingBuffer(count: 5) buffer.write(123) buffer.write(456) buffer.write(789) buffer.write(666) buffer.read() // 123 buffer.read() // 456 buffer.read() // 789 buffer.write(333) buffer.write(555) buffer.read() // 666 buffer.read() // 333 buffer.read() // 555 buffer.read() // nil ``` You've seen that a ring buffer can make a more optimal queue but it also has a disadvantage: the wrapping makes it tricky to resize the queue. But if a fixed-size queue is suitable for your purposes, then you're golden. A ring buffer is also very useful for when a producer of data writes into the array at a different rate than the consumer of the data reads it. This happens often with file or network I/O. Ring buffers are also the preferred way of communicating between high priority threads (such as an audio rendering callback) and other, slower, parts of the system. The implementation given here is not thread-safe. It only serves as an example of how a ring buffer works. That said, it should be fairly straightforward to make it thread-safe for a single reader and single writer by using `OSAtomicIncrement64()` to change the read and write pointers. A cool trick to make a really fast ring buffer is to use the operating system's virtual memory system to map the same buffer onto different memory pages. Crazy stuff but worth looking into if you need to use a ring buffer in a high performance environment. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Ring Buffer/RingBuffer.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play public struct RingBuffer { fileprivate var array: [T?] fileprivate var readIndex = 0 fileprivate var writeIndex = 0 public init(count: Int) { array = [T?](repeating: nil, count: count) } /* Returns false if out of space. */ @discardableResult public mutating func write(_ element: T) -> Bool { guard !isFull else { return false } defer { writeIndex += 1 } array[wrapped: writeIndex] = element return true } /* Returns nil if the buffer is empty. */ public mutating func read() -> T? { guard !isEmpty else { return nil } defer { array[wrapped: readIndex] = nil readIndex += 1 } return array[wrapped: readIndex] } fileprivate var availableSpaceForReading: Int { return writeIndex - readIndex } public var isEmpty: Bool { return availableSpaceForReading == 0 } fileprivate var availableSpaceForWriting: Int { return array.count - availableSpaceForReading } public var isFull: Bool { return availableSpaceForWriting == 0 } } extension RingBuffer: Sequence { public func makeIterator() -> AnyIterator { var index = readIndex return AnyIterator { guard index < self.writeIndex else { return nil } defer { index += 1 } return self.array[wrapped: index] } } } private extension Array { subscript (wrapped index: Int) -> Element { get { return self[index % count] } set { self[index % count] = newValue } } } var buffer = RingBuffer(count: 5) buffer.array // [nil, nil, nil, nil, nil] buffer.readIndex // 0 buffer.writeIndex // 0 buffer.availableSpaceForReading // 0 buffer.availableSpaceForWriting // 5 buffer.write(123) buffer.write(456) buffer.write(789) buffer.write(666) buffer.array // [{Some 123}, {Some 456}, {Some 789}, {Some 666}, nil] buffer.readIndex // 0 buffer.writeIndex // 4 buffer.availableSpaceForReading // 4 buffer.availableSpaceForWriting // 1 buffer.read() // 123 buffer.readIndex // 1 buffer.availableSpaceForReading // 3 buffer.availableSpaceForWriting // 2 buffer.read() // 456 buffer.read() // 789 buffer.readIndex // 3 buffer.availableSpaceForReading // 1 buffer.availableSpaceForWriting // 4 buffer.write(333) buffer.write(555) buffer.array // [{Some 555}, {Some 456}, {Some 789}, {Some 666}, {Some 333}] buffer.availableSpaceForReading // 3 buffer.availableSpaceForWriting // 2 buffer.writeIndex // 6 buffer.read() // 666 buffer.read() // 333 buffer.read() // 555 buffer.read() // nil buffer.availableSpaceForReading // 0 buffer.availableSpaceForWriting // 5 buffer.readIndex // 6 ================================================ FILE: Ring Buffer/RingBuffer.playground/contents.xcplayground ================================================ ================================================ FILE: Ring Buffer/RingBuffer.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Ring Buffer/RingBuffer.swift ================================================ /* Fixed-length ring buffer In this implementation, the read and write pointers always increment and never wrap around. On a 64-bit platform that should not get you into trouble any time soon. Not thread-safe, so don't read and write from different threads at the same time! To make this thread-safe for one reader and one writer, it should be enough to change read/writeIndex += 1 to OSAtomicIncrement64(), but I haven't tested this... */ public struct RingBuffer { private var array: [T?] private var readIndex = 0 private var writeIndex = 0 public init(count: Int) { array = [T?](repeating: nil, count: count) } /* Returns false if out of space. */ @discardableResult public mutating func write(_ element: T) -> Bool { guard !isFull else { return false } defer { writeIndex += 1 } array[wrapped: writeIndex] = element return true } /* Returns nil if the buffer is empty. */ public mutating func read() -> T? { guard !isEmpty else { return nil } defer { array[wrapped: readIndex] = nil readIndex += 1 } return array[wrapped: readIndex] } private var availableSpaceForReading: Int { return writeIndex - readIndex } public var isEmpty: Bool { return availableSpaceForReading == 0 } private var availableSpaceForWriting: Int { return array.count - availableSpaceForReading } public var isFull: Bool { return availableSpaceForWriting == 0 } } public extension RingBuffer: Sequence { public func makeIterator() -> AnyIterator { var index = readIndex return AnyIterator { guard index < self.writeIndex else { return nil } defer { index += 1 } return self.array[wrapped: index] } } } private extension Array { subscript (wrapped index: Int) -> Element { get { return self[index % count] } set { self[index % count] = newValue } } } ================================================ FILE: Rootish Array Stack/README.md ================================================ # Rootish Array Stack A *Rootish Array Stack* is an ordered array based structure that minimizes wasted space (based on [Gauss's summation technique](https://betterexplained.com/articles/techniques-for-adding-the-numbers-1-to-100/)). A *Rootish Array Stack* consists of an array holding many fixed size arrays in ascending size. ![Rootish Array Stack Intro](images/RootishArrayStackIntro.png) A resizable array holds references to blocks (arrays of fixed size). A block's capacity is the same as it's index in the resizable array. Blocks don't grow/shrink like regular Swift arrays. Instead, when their capacity is reached, a new slightly larger block is created. When a block is emptied the last block is freed. This is a great improvement on what Swift arrays do in terms of wasted space. ![Rootish Array Stack Intro](images/RootishArrayStackExample.png) Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). ## Gauss' Summation Trick One of the most well known legends about famous mathematician [Carl Friedrich Gauss](https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss) goes back to when he was in primary school. One day, Gauss' teacher asked his class to add up all the numbers from 1 to 100, hoping that the task would take long enough for him to step out for a smoke break. The teacher was shocked when young Gauss had his hand up with the answer `5050`. So soon? The teacher suspected a cheat, but no. Gauss had found a formula to sidestep the problem of manually adding up all the numbers 1 by 1. His formula: ``` sum from 1...n = n * (n + 1) / 2 ``` To understand this imagine `n` blocks where `x` represents `1` unit. In this example let `n` be `5`: ``` blocks: [x] [x x] [x x x] [x x x x] [x x x x x] # of x's: 1 2 3 4 5 ``` _Block `1` has 1 `x`, block `2` as 2 `x`s, block `3` has 3 `x`s, etc..._ If you wanted to take the sum of all the blocks from `1` to `n`, you could go through and count them _one by one_. This is okay, but for a large sequence of blocks that could take a long time! Instead, you could arrange the blocks to look like a _half pyramid_: ``` # | blocks --|------------- 1 | x 2 | x x 3 | x x x 4 | x x x x 5 | x x x x x ``` Then we mirror the _half pyramid_ and rearrange the image so that it fits with the original _half pyramid_ in a rectangular shape: ``` x o x o o o o o x x o o x x o o o o x x x o o o => x x x o o o x x x x o o o o x x x x o o x x x x x o o o o o x x x x x o ``` Here we have `n` rows and `n + 1` columns. _5 rows and 6 columns_. We can calculate the sum just as we would an area! Let's also express the width and height in terms of `n`: ``` area of a rectangle = height * width = n * (n + 1) ``` We only want to calculate the amount of `x`s, not the amount of `o`s. Since there's a 1:1 ratio between `x`s and `o`s we can just divide our area by 2! ``` area of only x = n * (n + 1) / 2 ``` Voila! A super fast way to take a sum of all the blocks! This equation is useful for deriving fast `block` and `inner block index` equations. ## Get/Set with Speed Next, we want to find an efficient and accurate way to access an element at a random index. For example, which block does `rootishArrayStack[12]` point to? To answer this we will need more math! Determining the inner block `index` turns out to be easy. If `index` is in some `block` then: ``` inner block index = index - block * (block + 1) / 2 ``` Determining which `block` an index points to is more difficult. The number of elements up to and including the element requested is: `index + 1` elements. The number of elements in blocks `0...block` is `(block + 1) * (block + 2) / 2` (equation derived above). The relationship between the `block` and the `index` is as follows: ``` (block + 1) * (block + 2) / 2 >= index + 1 ``` This can be rewritten as: ``` (block)^2 + (3 * block) - (2 * index) >= 0 ``` Using the quadratic formula we get: ``` block = (-3 ± √(9 + 8 * index)) / 2 ``` A negative block doesn't make sense, so we take the positive root instead. In general, this solution is not an integer. However, going back to our inequality, we want the smallest block such that `block => (-3 + √(9 + 8 * index)) / 2`. Next, we take the ceiling of the result: ``` block = ⌈(-3 + √(9 + 8 * index)) / 2⌉ ``` Now we can figure out what `rootishArrayStack[12]` points to! First, let's see which block the `12` points to: ``` block = ⌈(-3 + √(9 + 8 * (12))) / 2⌉ block = ⌈(-3 + √105) / 2⌉ block = ⌈(-3 + (10.246950766)) / 2⌉ block = ⌈(7.246950766) / 2⌉ block = ⌈3.623475383⌉ block = 4 ``` Next lets see which `innerBlockIndex` `12` points to: ``` inner block index = (12) - (4) * ((4) + 1) / 2 inner block index = (12) - (4) * (5) / 2 inner block index = (12) - 10 inner block index = 2 ``` Therefore, `rootishArrayStack[12]` points to the block at index `4` and at inner block index `2`. ![Rootish Array Stack Intro](images/RootishArrayStackExample2.png) ### Interesting Discovery Using the `block` equation, we can see that the number of `blocks` is proportional to the square root of the number of elements: **O(blocks) = O(√n)**. # Implementation Details Let's start with instance variables and struct declaration: ```swift import Darwin public struct RootishArrayStack { fileprivate var blocks = [Array]() fileprivate var internalCount = 0 public init() { } var count: Int { return internalCount } ... } ``` The elements are of generic type `T`, so data of any kind can be stored in the list. `blocks` will be a resizable array to hold fixed sized arrays that take type `T?`. > The reason for the fixed size arrays taking type `T?` is so that references to elements aren't retained after they've been removed. Eg: if you remove the last element, the last index must be set to `nil` to prevent the last element being held in memory at an inaccessible index. `internalCount` is an internal mutable counter that keeps track of the number of elements. `count` is a read only variable that returns the `internalCount` value. `Darwin` is imported here to provide simple math functions such as `ceil()` and `sqrt()`. The `capacity` of the structure is simply the Gaussian summation trick: ```swift var capacity: Int { return blocks.count * (blocks.count + 1) / 2 } ``` Next, let's look at how we would `get` and `set` elements: ```swift fileprivate func block(fromIndex: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } fileprivate func innerBlockIndex(fromIndex index: Int, fromBlock block: Int) -> Int { return index - block * (block + 1) / 2 } public subscript(index: Int) -> T { get { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) return blocks[block][innerBlockIndex]! } set(newValue) { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) blocks[block][innerBlockIndex] = newValue } } ``` `block(fromIndex:)` and `innerBlockIndex(fromIndex:, fromBlock:)` are wrapping the `block` and `inner block index` equations we derived earlier. `superscript` lets us have `get` and `set` access to the structure with the familiar `[index:]` syntax. For both `get` and `set` in `superscript` we use the same logic: 1. determine the block that the index points to 2. determine the inner block index 3. `get`/`set` the value Next, let's look at how we would `growIfNeeded()` and `shrinkIfNeeded()`. ```swift fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { let newArray = [T?](repeating: nil, count: blocks.count + 1) blocks.append(newArray) } } fileprivate mutating func shrinkIfNeeded() { if capacity + blocks.count >= count { while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 > count { blocks.remove(at: blocks.count - 1) } } } ``` If our data set grows or shrinks in size, we want our data structure to accommodate the change. Just like a Swift array, when a capacity threshold is met we will `grow` or `shrink` the size of our structure. For the Rootish Array Stack we want to `grow` if the second last block is full on an `insert` operation, and `shrink` if the two last blocks are empty. Now to the more familiar Swift array behaviour. ```swift public mutating func insert(element: T, atIndex index: Int) { growIfNeeded() internalCount += 1 var i = count - 1 while i > index { self[i] = self[i - 1] i -= 1 } self[index] = element } public mutating func append(element: T) { insert(element: element, atIndex: count) } public mutating func remove(atIndex index: Int) -> T { let element = self[index] for i in index.. Setting a optionals value to `nil` is different than setting it's wrapped value to `nil`. An optionals wrapped value is an embedded type within the optional reference. This means that a `nil` wrapped value is actually `.some(.none)` whereas setting the root reference to `nil` is `.none`. To better understand Swift optionals I recommend checking out @SebastianBoldt's article [Swift! Optionals?](https://medium.com/ios-os-x-development/swift-optionals-78dafaa53f3#.rvjobhuzs). # Performance * An internal counter keeps track of the number of elements in the structure. `count` is executed in **O(1)** time. * `capacity` can be calculated using Gauss' summation trick in an equation which takes **O(1)** time to execute. * Since `subcript[index:]` uses the `block` and `inner block index` equations, which can be executed in **O(1)** time, all get and set operations take **O(1)**. * Ignoring the time cost to `grow` and `shrink`, `insert(atIndex:)` and `remove(atIndex:)` operations shift all elements right of the specified index resulting in **O(n)** time. # Analysis of Growing and Shrinking The performance analysis doesn't account for the cost to `grow` and `shrink`. Unlike a regular Swift array, `grow` and `shrink` operations don't copy all the elements into a backing array. They only allocate or free an array proportional to the number of `blocks`. The number of `blocks` is proportional to the square root of the number of elements. Growing and shrinking only costs **O(√n)**. # Wasted Space Wasted space is how much memory with respect to the number of elements `n` is unused. The Rootish Array Stack never has more than 2 empty blocks and it never has less than 1 empty block. The last two blocks are proportional to the number of blocks, which is proportional to the square root of the number of elements. The number of references needed to point to each block is the same as the number of blocks. Therefore, the amount of wasted space with respect to the number of elements is **O(√n)**. _Written for Swift Algorithm Club by @BenEmdon_ _With help from [OpenDataStructures.org](http://opendatastructures.org)_ ================================================ FILE: Rootish Array Stack/RootishArrayStack.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif import Darwin public struct RootishArrayStack { // MARK: - Instance variables fileprivate var blocks = [Array]() fileprivate var internalCount = 0 // MARK: - Init public init() { } // MARK: - Calculated variables var count: Int { return internalCount } var capacity: Int { return blocks.count * (blocks.count + 1) / 2 } var isEmpty: Bool { return blocks.count == 0 } var first: T? { guard capacity > 0 else { return nil } return blocks[0][0] } var last: T? { guard capacity > 0 else { return nil } let block = self.block(fromIndex: count - 1) let innerBlockIndex = self.innerBlockIndex(fromIndex: count - 1, fromBlock: block) return blocks[block][innerBlockIndex] } // MARK: - Equations fileprivate func block(fromIndex index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } fileprivate func innerBlockIndex(fromIndex index: Int, fromBlock block: Int) -> Int { return index - block * (block + 1) / 2 } // MARK: - Behavior fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { let newArray = [T?](repeating: nil, count: blocks.count + 1) blocks.append(newArray) } } fileprivate mutating func shrinkIfNeeded() { if capacity + blocks.count >= count { while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { blocks.remove(at: blocks.count - 1) } } } public subscript(index: Int) -> T { get { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) return blocks[block][innerBlockIndex]! } set(newValue) { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) blocks[block][innerBlockIndex] = newValue } } public mutating func insert(element: T, atIndex index: Int) { growIfNeeded() internalCount += 1 var i = count - 1 while i > index { self[i] = self[i - 1] i -= 1 } self[index] = element } public mutating func append(element: T) { insert(element: element, atIndex: count) } fileprivate mutating func makeNil(atIndex index: Int) { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) blocks[block][innerBlockIndex] = nil } public mutating func remove(atIndex index: Int) -> T { let element = self[index] for i in index..() list.isEmpty // true list.first // nil list.last // nil list.count // 0 list.capacity // 0 list.memoryDescription // { // } list.append(element: "Hello") list.isEmpty // false list.first // "Hello" list.last // "hello" list.count // 1 list.capacity // 1 list.memoryDescription // { // [Optional("Hello")] // } list.append(element: "World") list.isEmpty // false list.first // "Hello" list.last // "World" list.count // 2 list.capacity // 3 list[0] // "Hello" list[1] // "World" //list[2] // crash! list.memoryDescription // { // [Optional("Hello")] // [Optional("World"), nil] // } list.insert(element: "Swift", atIndex: 1) list.isEmpty // false list.first // "Hello" list.last // "World" list.count // 3 list.capacity // 6 list[0] // "Hello" list[1] // "Swift" list[2] // "World" list.memoryDescription // { // [Optional("Hello")] // [Optional("Swift"), Optional("World")] // [nil, nil, nil] // } list.remove(atIndex: 2) // "World" list.isEmpty // false list.first // "Hello" list.last // "Swift" list.count // 2 list.capacity // 3 list[0] // "Hello" list[1] // "Swift" //list[2] // crash! list[0] = list[1] list[1] = "is awesome" list // ["Swift", "is awesome"] ================================================ FILE: Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground ================================================ ================================================ FILE: Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Rootish Array Stack/RootishArrayStack.swift ================================================ // // RootishArrayStack // // Created by @BenEmdon on 2016-11-07. // import Darwin public struct RootishArrayStack { // MARK: - Instance variables fileprivate var blocks = [Array]() fileprivate var internalCount = 0 // MARK: - Init public init() { } // MARK: - Calculated variables var count: Int { return internalCount } var capacity: Int { return blocks.count * (blocks.count + 1) / 2 } var isEmpty: Bool { return blocks.count == 0 } var first: T? { guard capacity > 0 else { return nil } return blocks[0][0] } var last: T? { guard capacity > 0 else { return nil } let block = self.block(fromIndex: count - 1) let innerBlockIndex = self.innerBlockIndex(fromIndex: count - 1, fromBlock: block) return blocks[block][innerBlockIndex] } // MARK: - Equations fileprivate func block(fromIndex index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } fileprivate func innerBlockIndex(fromIndex index: Int, fromBlock block: Int) -> Int { return index - block * (block + 1) / 2 } // MARK: - Behavior fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { let newArray = [T?](repeating: nil, count: blocks.count + 1) blocks.append(newArray) } } fileprivate mutating func shrinkIfNeeded() { if capacity + blocks.count >= count { while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { blocks.remove(at: blocks.count - 1) } } } public subscript(index: Int) -> T { get { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) return blocks[block][innerBlockIndex]! } set(newValue) { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) blocks[block][innerBlockIndex] = newValue } } public mutating func insert(element: T, atIndex index: Int) { growIfNeeded() internalCount += 1 var i = count - 1 while i > index { self[i] = self[i - 1] i -= 1 } self[index] = element } public mutating func append(element: T) { insert(element: element, atIndex: count) } fileprivate mutating func makeNil(atIndex index: Int) { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) blocks[block][innerBlockIndex] = nil } public mutating func remove(atIndex index: Int) -> T { let element = self[index] for i in index.. CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Rootish Array Stack/Tests/RootishArrayStack.swift ================================================ // // RootishArrayStack // // Created by @BenEmdon on 2016-11-07. // import Darwin public struct RootishArrayStack { // MARK: - Instance variables fileprivate var blocks = [Array]() fileprivate var internalCount = 0 // MARK: - Init public init() { } // MARK: - Calculated variables var count: Int { return internalCount } var capacity: Int { return blocks.count * (blocks.count + 1) / 2 } var isEmpty: Bool { return blocks.count == 0 } var first: T? { guard capacity > 0 else { return nil } return blocks[0][0] } var last: T? { guard capacity > 0 else { return nil } let block = self.block(fromIndex: count - 1) let innerBlockIndex = self.innerBlockIndex(fromIndex: count - 1, fromBlock: block) return blocks[block][innerBlockIndex] } // MARK: - Equations fileprivate func block(fromIndex index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } fileprivate func innerBlockIndex(fromIndex index: Int, fromBlock block: Int) -> Int { return index - block * (block + 1) / 2 } // MARK: - Behavior fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { let newArray = [T?](repeating: nil, count: blocks.count + 1) blocks.append(newArray) } } fileprivate mutating func shrinkIfNeeded() { if capacity + blocks.count >= count { while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { blocks.remove(at: blocks.count - 1) } } } public subscript(index: Int) -> T { get { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) return blocks[block][innerBlockIndex]! } set(newValue) { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) blocks[block][innerBlockIndex] = newValue } } public mutating func insert(element: T, atIndex index: Int) { growIfNeeded() internalCount += 1 var i = count - 1 while i > index { self[i] = self[i - 1] i -= 1 } self[index] = element } public mutating func append(element: T) { insert(element: element, atIndex: count) } fileprivate mutating func makeNil(atIndex index: Int) { let block = self.block(fromIndex: index) let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) blocks[block][innerBlockIndex] = nil } public mutating func remove(atIndex index: Int) -> T { let element = self[index] for i in index..) -> Bool { for index in 0.. RootishArrayStack { var list = RootishArrayStack() if let numbers = numbers { for number in numbers { list.append(element: number) } } return list } func testEmptyList() { let emptyArray = [Int]() let list = buildList() XCTAssertTrue(list.isEmpty) XCTAssertEqual(list.count, 0) XCTAssertEqual(list.capacity, 0) XCTAssertNil(list.first) XCTAssertNil(list.last) XCTAssertTrue(list.equal(toArray: emptyArray)) } func testListWithOneElement() { let array = [1] let list = buildList(withNumbers: array) XCTAssertFalse(list.isEmpty) XCTAssertEqual(list.count, 1) XCTAssertEqual(list.capacity, 1) XCTAssertEqual(list.first, 1) XCTAssertEqual(list.last, 1) XCTAssertEqual(list.first, list.last) XCTAssertTrue(list.equal(toArray: array)) } func testListWithTwoElements() { let array = [1, 2] let list = buildList(withNumbers: array) XCTAssertFalse(list.isEmpty) XCTAssertEqual(list.count, 2) XCTAssertEqual(list.capacity, 3) XCTAssertEqual(list.first, 1) XCTAssertEqual(list.last, 2) XCTAssertNotEqual(list.first, list.last) XCTAssertTrue(list.equal(toArray: array)) } func testListWithThreeElements() { let array = [1, 2, 3] let list = buildList(withNumbers: array) XCTAssertFalse(list.isEmpty) XCTAssertEqual(list.count, 3) XCTAssertEqual(list.capacity, 6) XCTAssertEqual(list.first, 1) XCTAssertEqual(list.last, 3) XCTAssertNotEqual(list.first, list.last) XCTAssertTrue(list.equal(toArray: array)) } func testFillThenEmpty() { let array = [Int](0..<100) let emptyArray = [Int]() var list = buildList(withNumbers: array) XCTAssertTrue(list.equal(toArray: array)) for _ in 0..<100 { list.remove(atIndex: list.count - 1) } XCTAssertEqual(list.count, 0) XCTAssertEqual(list.capacity, 0) XCTAssertTrue(list.equal(toArray: emptyArray)) } func testInsertFront() { var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] var list = buildList(withNumbers: array) XCTAssertEqual(list.count, 10) XCTAssertEqual(list.capacity, 15) XCTAssertEqual(list.first, 1) XCTAssertTrue(list.equal(toArray: array)) let newElement = 0 list.insert(element: newElement, atIndex: 0) array.insert(newElement, at: 0) XCTAssertEqual(list.count, 11) XCTAssertEqual(list.capacity, 21) XCTAssertEqual(list.first, newElement) XCTAssertTrue(list.equal(toArray: array)) } func testInsertMiddle() { var array = [0, 2, 3] var list = buildList(withNumbers: array) XCTAssertEqual(list.count, 3) XCTAssertEqual(list.capacity, 6) XCTAssertTrue(list.equal(toArray: array)) let newElement = 1 list.insert(element: newElement, atIndex: 1) array.insert(newElement, at: 1) XCTAssertEqual(list.count, 4) XCTAssertEqual(list.capacity, 10) XCTAssertEqual(list[1], newElement) XCTAssertTrue(list.equal(toArray: array)) } func testSubscriptGet() { let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] let list = buildList(withNumbers: array) for index in 0...9 { XCTAssertEqual(list[index], index) } XCTAssertTrue(list.equal(toArray: array)) } func testSubscriptSet() { var array = [Int](0..<10) var list = buildList(withNumbers: array) list[1] = 100 list[5] = 500 list[8] = 800 array[1] = 100 array[5] = 500 array[8] = 800 XCTAssertTrue(list.equal(toArray: array)) } func testRemoveFirst() { var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] var list = buildList(withNumbers: array) XCTAssertEqual(list.count, 10) XCTAssertEqual(list.capacity, 15) XCTAssertEqual(list.first, 1) XCTAssertTrue(list.equal(toArray: array)) list.remove(atIndex: 0) array.remove(at: 0) XCTAssertEqual(list.count, 9) XCTAssertEqual(list.capacity, 15) XCTAssertEqual(list.first, 2) XCTAssertTrue(list.equal(toArray: array)) } func testRemoveMiddle() { var array = [0, 1, 2, 3] var list = buildList(withNumbers: array) XCTAssertEqual(list.count, 4) XCTAssertEqual(list.capacity, 10) XCTAssertEqual(list.first, 0) XCTAssertTrue(list.equal(toArray: array)) list.remove(atIndex: 2) array.remove(at: 2) XCTAssertEqual(list.count, 3) XCTAssertEqual(list.capacity, 6) XCTAssertEqual(list.first, 0) XCTAssertTrue(list.equal(toArray: array)) } func testRemoveLast() { var array = [0, 1, 2, 3] var list = buildList(withNumbers: array) XCTAssertEqual(list.count, 4) XCTAssertEqual(list.capacity, 10) XCTAssertEqual(list.first, 0) XCTAssertTrue(list.equal(toArray: array)) list.remove(atIndex: 3) array.remove(at: 3) XCTAssertEqual(list.count, 3) XCTAssertEqual(list.capacity, 6) XCTAssertEqual(list.first, 0) XCTAssertTrue(list.equal(toArray: array)) } func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } } ================================================ FILE: Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 1D059BB21E073CED00391DD1 /* RootishArrayStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D059BB11E073CED00391DD1 /* RootishArrayStack.swift */; }; 7B80C3FA1C77A61E003CECC7 /* RootishArrayStackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F91C77A61E003CECC7 /* RootishArrayStackTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 1D059BB11E073CED00391DD1 /* RootishArrayStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RootishArrayStack.swift; path = ../RootishArrayStack.swift; sourceTree = ""; }; 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3F91C77A61E003CECC7 /* RootishArrayStackTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootishArrayStackTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 1D059BB11E073CED00391DD1 /* RootishArrayStack.swift */, 7B80C3F91C77A61E003CECC7 /* RootishArrayStackTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0820; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3FA1C77A61E003CECC7 /* RootishArrayStackTests.swift in Sources */, 1D059BB21E073CED00391DD1 /* RootishArrayStack.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Run-Length Encoding/README.markdown ================================================ # Run-Length Encoding (RLE) RLE is probably the simplest way to do compression. Let's say you have data that looks like this: aaaaabbbcdeeeeeeef... then RLE encodes it as follows: 5a3b1c1d7e1f... Instead of repeating bytes, you first write how often that byte occurs and then the byte's actual value. So `5a` means `aaaaa`. If the data has a lot of "byte runs", that is lots of repeating bytes, then RLE can save quite a bit of space. It works quite well on images. There are many different ways you can implement RLE. Here's an extension of `Data` that does a version of RLE inspired by the old [PCX image file format](https://en.wikipedia.org/wiki/PCX). The rules are these: - Each byte run, i.e. when a certain byte value occurs more than once in a row, is compressed using two bytes: the first byte records the number of repetitions, the second records the actual value. The first byte is stored as: `191 + count`. This means encoded byte runs can never be more than 64 bytes long. - A single byte in the range 0 - 191 is not compressed and is copied without change. - A single byte in the range 192 - 255 is represented by two bytes: first the byte 192 (meaning a run of 1 byte), followed by the actual value. Here is the compression code. It returns a new `Data` object containing the run-length encoded bytes: ```swift extension Data { public func compressRLE() -> Data { var data = Data() self.withUnsafeBytes { (uPtr: UnsafePointer) in var ptr = uPtr let end = ptr + count while ptr < end { //1 var count = 0 var byte = ptr.pointee var next = byte while next == byte && ptr < end && count < 64 { //2 ptr = ptr.advanced(by: 1) next = ptr.pointee count += 1 } if count > 1 || byte >= 192 { // 3 var size = 191 + UInt8(count) data.append(&size, count: 1) data.append(&byte, count: 1) } else { // 4 data.append(&byte, count: 1) } } } return data } } ``` How it works: 1. We use an `UnsafePointer` to step through the bytes of the original `Data` object. 2. At this point we've read the current byte value into the `byte` variable. If the next byte is the same, then we keep reading until we find a byte value that is different, or we reach the end of the data. We also stop if the run is 64 bytes because that's the maximum we can encode. 3. Here, we have to decide how to encode the bytes we just read. The first possibility is that we've read a run of 2 or more bytes (up to 64). In that case we write out two bytes: the length of the run followed by the byte value. But it's also possible we've read a single byte with a value >= 192. That will also be encoded with two bytes. 4. The third possibility is that we've read a single byte < 192. That simply gets copied to the output verbatim. You can test it like this in a playground: ```swift let originalString = "aaaaabbbcdeeeeeeef" let utf8 = originalString.data(using: String.Encoding.utf8)! let compressed = utf8.compressRLE() ``` The compressed `Data` object should be ``. Let's decode that by hand to see what has happened: c4 This is 196 in decimal. It means the next byte appears 5 times. 61 The data byte "a". c2 The next byte appears 3 times. 62 The data byte "b". 63 The data byte "c". Because this is < 192, it's a single data byte. 64 The data byte "d". Also appears just once. c6 The next byte will appear 7 times. 65 The data byte "e". 66 The data byte "f". Appears just once. So that's 9 bytes encoded versus 18 original. That's a savings of 50%. Of course, this was only a simple test case... If you get unlucky and there are no byte runs at all in your original data, then this method will actually make the encoded data twice as large! So it really depends on the input data. Here is the decompression code: ```swift public func decompressRLE() -> Data { var data = Data() self.withUnsafeBytes { (uPtr: UnsafePointer) in var ptr = uPtr let end = ptr + count while ptr < end { // Read the next byte. This is either a single value less than 192, // or the start of a byte run. var byte = ptr.pointee // 1 ptr = ptr.advanced(by: 1) if byte < 192 { // 2 data.append(&byte, count: 1) } else if ptr < end { // 3 // Read the actual data value. var value = ptr.pointee ptr = ptr.advanced(by: 1) // And write it out repeatedly. for _ in 0 ..< byte - 191 { data.append(&value, count: 1) } } } } return data } ``` 1. Again this uses an `UnsafePointer` to read the `Data`. Here we read the next byte; this is either a single value less than 192, or the start of a byte run. 2. If it's a single value, then it's just a matter of copying it to the output. 3. But if the byte is the start of a run, we have to first read the actual data value and then write it out repeatedly. To turn the compressed data back into the original, you'd do: ```swift let decompressed = compressed.decompressRLE() let restoredString = String(data: decompressed, encoding: NSUTF8StringEncoding) ``` And now `originalString == restoredString` must be true! Footnote: The original PCX implementation is slightly different. There, a byte value of 192 (0xC0) means that the following byte will be repeated 0 times. This also limits the maximum run size to 63 bytes. Because it makes no sense to store bytes that don't occur, in my implementation 192 means the next byte appears once, and the maximum run length is 64 bytes. This was probably a trade-off when they designed the PCX format way back when. If you look at it in binary, the upper two bits indicate whether a byte is compressed. (If both bits are set then the byte value is 192 or more.) To get the run length you can simply do `byte & 0x3F`, giving you a value in the range 0 to 63. *Written for Swift Algorithm Club by Matthijs Hollemans* *Migrated to Swift3 by Jaap Wijnen* ================================================ FILE: Run-Length Encoding/RLE.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation let originalString = "aaaaabbbcdeeeeeeef" let utf8 = originalString.data(using: String.Encoding.utf8)! let compressed = utf8.compressRLE() let decompressed = compressed.decompressRLE() let restoredString = String(data: decompressed, encoding: String.Encoding.utf8) originalString == restoredString func encodeAndDecode(_ bytes: [UInt8]) -> Bool { var bytes = bytes var data1 = Data(bytes: &bytes, count: bytes.count) print("data1 is \(data1.count) bytes") var rleData = data1.compressRLE() print("encoded data is \(rleData.count) bytes") var data2 = rleData.decompressRLE() print("data2 is \(data2.count) bytes") return data1 == data2 } func testEmpty() -> Bool { let bytes: [UInt8] = [] return encodeAndDecode(bytes) } func testOneByteWithLowValue() -> Bool { let bytes: [UInt8] = [0x80] return encodeAndDecode(bytes) } func testOneByteWithHighValue() -> Bool { let bytes: [UInt8] = [0xD0] return encodeAndDecode(bytes) } func testSimpleCases() -> Bool { let bytes: [UInt8] = [ 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, 0x00, 0xC0, 0xC1, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF ] return encodeAndDecode(bytes) } func testBufferWithoutSpans() -> Bool { // There is nothing that can be encoded in this buffer, so the encoded // data ends up being longer. var bytes: [UInt8] = [] for i in 0..<1024 { bytes.append(UInt8(i % 256)) } return encodeAndDecode(bytes) } func testBufferWithSpans(_ spanSize: Int) -> Bool { print("span size \(spanSize)") let length = spanSize * 32 var bytes: [UInt8] = Array(repeating: 0, count: length) for t in stride(from: 0, to: length, by: spanSize) { for i in 0.. Bool { let length = 1 + Int(arc4random_uniform(2048)) var bytes: [UInt8] = [] for _ in 0.. Bool { var tests: [Bool] = [ testEmpty(), testOneByteWithLowValue(), testOneByteWithHighValue(), testSimpleCases(), testBufferWithoutSpans(), testBufferWithSpans(4), testBufferWithSpans(63), testBufferWithSpans(64), testBufferWithSpans(65), testBufferWithSpans(66), testBufferWithSpans(80) ] for _ in 0..<10 { let result = testRandomByte() tests.append(result) } var result = true for bool in tests { result = result && bool } return result } runTests() ================================================ FILE: Run-Length Encoding/RLE.playground/Sources/RLE.swift ================================================ import Foundation extension Data { /* Compresses the NSData using run-length encoding. */ public func compressRLE() -> Data { var data = Data() self.withUnsafeBytes { (uPtr: UnsafePointer) in var ptr = uPtr let end = ptr + count while ptr < end { var count = 0 var byte = ptr.pointee var next = byte // Is the next byte the same? Keep reading until we find a different // value, or we reach the end of the data, or the run is 64 bytes. while next == byte && ptr < end && count < 64 { ptr = ptr.advanced(by: 1) next = ptr.pointee count += 1 } if count > 1 || byte >= 192 { // byte run of up to 64 repeats var size = 191 + UInt8(count) data.append(&size, count: 1) data.append(&byte, count: 1) } else { // single byte between 0 and 192 data.append(&byte, count: 1) } } } return data } /* Converts a run-length encoded NSData back to the original. */ public func decompressRLE() -> Data { var data = Data() self.withUnsafeBytes { (uPtr: UnsafePointer) in var ptr = uPtr let end = ptr + count while ptr < end { // Read the next byte. This is either a single value less than 192, // or the start of a byte run. var byte = ptr.pointee ptr = ptr.advanced(by: 1) if byte < 192 { // single value data.append(&byte, count: 1) } else if ptr < end { // byte run // Read the actual data value. var value = ptr.pointee ptr = ptr.advanced(by: 1) // And write it out repeatedly. for _ in 0 ..< byte - 191 { data.append(&value, count: 1) } } } } return data } } ================================================ FILE: Run-Length Encoding/RLE.playground/contents.xcplayground ================================================ ================================================ FILE: Run-Length Encoding/RLE.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Segment Tree/LazyPropagation/LazyPropagation.playground/Contents.swift ================================================ public class LazySegmentTree { private var value: Int private var leftBound: Int private var rightBound: Int private var leftChild: LazySegmentTree? private var rightChild: LazySegmentTree? // Interval Update Lazy Element private var lazyValue: Int // MARK: - Push Up Operation // Description: pushUp() - update items to the top private func pushUp(lson: LazySegmentTree, rson: LazySegmentTree) { self.value = lson.value + rson.value } // MARK: - Push Down Operation // Description: pushDown() - update items to the bottom private func pushDown(round: Int, lson: LazySegmentTree, rson: LazySegmentTree) { guard lazyValue != 0 else { return } lson.lazyValue += lazyValue rson.lazyValue += lazyValue lson.value += lazyValue * (round - (round >> 1)) rson.value += lazyValue * (round >> 1) lazyValue = 0 } public init(array: [Int], leftBound: Int, rightBound: Int) { self.leftBound = leftBound self.rightBound = rightBound self.value = 0 self.lazyValue = 0 guard leftBound != rightBound else { value = array[leftBound] return } let middle = leftBound + (rightBound - leftBound) / 2 leftChild = LazySegmentTree(array: array, leftBound: leftBound, rightBound: middle) rightChild = LazySegmentTree(array: array, leftBound: middle + 1, rightBound: rightBound) if let leftChild = leftChild, let rightChild = rightChild { pushUp(lson: leftChild, rson: rightChild) } } public convenience init(array: [Int]) { self.init(array: array, leftBound: 0, rightBound: array.count - 1) } public func query(leftBound: Int, rightBound: Int) -> Int { if leftBound <= self.leftBound && self.rightBound <= rightBound { return value } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } pushDown(round: self.rightBound - self.leftBound + 1, lson: leftChild, rson: rightChild) let middle = self.leftBound + (self.rightBound - self.leftBound) / 2 var result = 0 if leftBound <= middle { result += leftChild.query(leftBound: leftBound, rightBound: rightBound) } if rightBound > middle { result += rightChild.query(leftBound: leftBound, rightBound: rightBound) } return result } // MARK: - One Item Update public func update(index: Int, incremental: Int) { guard self.leftBound != self.rightBound else { self.value += incremental return } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } let middle = self.leftBound + (self.rightBound - self.leftBound) / 2 if index <= middle { leftChild.update(index: index, incremental: incremental) } else { rightChild.update(index: index, incremental: incremental) } pushUp(lson: leftChild, rson: rightChild) } // MARK: - Interval Item Update public func update(leftBound: Int, rightBound: Int, incremental: Int) { if leftBound <= self.leftBound && self.rightBound <= rightBound { self.lazyValue += incremental self.value += incremental * (self.rightBound - self.leftBound + 1) return } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } pushDown(round: self.rightBound - self.leftBound + 1, lson: leftChild, rson: rightChild) let middle = self.leftBound + (self.rightBound - self.leftBound) / 2 if leftBound <= middle { leftChild.update(leftBound: leftBound, rightBound: rightBound, incremental: incremental) } if middle < rightBound { rightChild.update(leftBound: leftBound, rightBound: rightBound, incremental: incremental) } pushUp(lson: leftChild, rson: rightChild) } } let array = [1, 2, 3, 4, 1, 3, 2] let sumSegmentTree = LazySegmentTree(array: array) print(sumSegmentTree.query(leftBound: 0, rightBound: 3)) // 10 = 1 + 2 + 3 + 4 sumSegmentTree.update(index: 1, incremental: 2) print(sumSegmentTree.query(leftBound: 0, rightBound: 3)) // 12 = 1 + 4 + 3 + 4 sumSegmentTree.update(leftBound: 0, rightBound: 2, incremental: 2) print(sumSegmentTree.query(leftBound: 0, rightBound: 3)) // 18 = 3 + 6 + 5 + 4 for index in 2 ... 5 { sumSegmentTree.update(index: index, incremental: 3) } sumSegmentTree.update(leftBound: 0, rightBound: 5, incremental: 2) print(sumSegmentTree.query(leftBound: 0, rightBound: 2)) ================================================ FILE: Segment Tree/LazyPropagation/LazyPropagation.playground/contents.xcplayground ================================================ ================================================ FILE: Segment Tree/LazyPropagation/LazyPropagation.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Segment Tree/LazyPropagation/README.markdown ================================================ # Lazy Propagation in Segment Tree In previous implement about the Segment Tree by **Artur Antonov**, it's a strong data structure with *Generic* ``. And we can pass a closure parameter `function: (T, T) -> T` to reflect the relationship between parent and child node. And in particular, Generic can solve multiple strings stitching problem. It's just like the sample in Playground: ```swift stringSegmentTree.replaceItem(at: 0, withItem: "I") stringSegmentTree.replaceItem(at: 1, withItem: " like") stringSegmentTree.replaceItem(at: 2, withItem: " algorithms") stringSegmentTree.replaceItem(at: 3, withItem: " and") stringSegmentTree.replaceItem(at: 4, withItem: " swift") stringSegmentTree.replaceItem(at: 5, withItem: "!") print(stringSegmentTree.query(leftBound: 0, rightBound: 5)) // "I like algorithms and swift!" ``` The use of `` is so exciting. But we seldom use the Segment Tree to solve string problem instead of *Suffix Array*. And the Segment Tree is a kind of *Interval Tree* to solve the Interval Problem in mathemtics and statistics, which is a structure for storing intervals, or segments, and allows querying which of the stored segments contain a given point. A segment tree for a set *I* of n intervals uses `O(nlogn)` storage and can be built in `O(nlogn)` time. Segment trees support searching for all the intervals that contain a query point in O(log n+k), k being the number of retrieved intervals or segments. But that is common Segment Tree. By **Lazy Propagation**, we can implement to modify an interval in `O(logn)` time. Let's explore together in following: ## `PushUp` - update to the top At first, we reference the implement of **Artur Antonov** about Segment Tree. This code contained *build*, *single update* and *interval query* three operation. The implement of *build* and *single update* operation is following: ```swift // Author: Artur Antonov public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound self.function = function // ① if leftBound == rightBound { value = array[leftBound] } // ② else { let middle = (leftBound + rightBound) / 2 leftChild = SegmentTree(array: array, leftBound: leftBound, rightBound: middle, function: function) rightChild = SegmentTree(array: array, leftBound: middle+1, rightBound: rightBound, function: function) value = function(leftChild!.value, rightChild!.value) } } ``` In position ①, it means the current node is *leaf* because its left bound data is equal to the right. So we assign a value to it directly. In position ②, it means the current node is *parent* (which has one or more children), and we need to recursion down and update current node's data in the follow-up process. And then, we have a look for *interval query* operation: ```swift // Author: Artur Antonov public func query(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } // ① if leftChild.rightBound < leftBound { return rightChild.query(leftBound: leftBound, rightBound: rightBound) } // ② else if rightChild.leftBound > rightBound { return leftChild.query(leftBound: leftBound, rightBound: rightBound) } // ③ else { let leftResult = leftChild.query(leftBound: leftBound, rightBound: leftChild.rightBound) let rightResult = rightChild.query(leftBound:rightChild.leftBound, rightBound: rightBound) return function(leftResult, rightResult) } } ``` Position ① means that the left bound of current query interval is on the right of this right bound, so recurs to right direction. Position ② is opposite of position ①, recurs to left direction. Position ③ means our check interval is included the interval we need, so recurs deeply. ![pushUp](Images/pushUp.png) There are common part from the two parts of code above - **recurs deeply below, and update data up**. So we can decouple this operation named `func pushUp(lson: LazySegmentTree, rson: LazySegmentTree)`: ```swift // MARK: - Push Up Operation private func pushUp(lson: LazySegmentTree, rson: LazySegmentTree) { self.value = lson.value + rson.value } ``` (This code only describe the *Sum Segment Tree*) And then, we can update the implement before: ```swift public init(array: [Int], leftBound: Int, rightBound: Int) { self.leftBound = leftBound self.rightBound = rightBound self.value = 0 self.lazyValue = 0 guard leftBound != rightBound else { value = array[leftBound] return } let middle = leftBound + (rightBound - leftBound) / 2 leftChild = LazySegmentTree(array: array, leftBound: leftBound, rightBound: middle) rightChild = LazySegmentTree(array: array, leftBound: middle + 1, rightBound: rightBound) if let leftChild = leftChild, let rightChild = rightChild { pushUp(lson: leftChild, rson: rightChild) } } // MARK: - One Item Update public func update(index: Int, incremental: Int) { guard self.leftBound != self.rightBound else { self.value += incremental return } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } let middle = self.leftBound + (self.rightBound - self.leftBound) / 2 if index <= middle { leftChild.update(index: index, incremental: incremental) } else { rightChild.update(index: index, incremental: incremental) } pushUp(lson: leftChild, rson: rightChild) } ``` ## `PushDown` - Lazy Propagation You may feel that the `pushUp` is so simple. In fact, this's just to lead `pushDown` this function. Before this, I want to talk about the topic about **interval operation**. The interval operation is a way to update all elements of a continuous subset. But these isn't in the version of **Artur Antonov**. You might disdain with this, because it's solved with a `for` loop: ```swift // Sample: update the elements with subscript [2, 5] for index in 2 ... 5 { sumSegmentTree.update(index: index, incremental: 3) } ``` It is a `O(n)` time operation, which make the interval operation uses `O(nlogn)` time to update these elements. We need a `O(logn)` way to maintain the elegance of Segment Tree. Check the data structure of Segment Tree again: ![Segment-tree](Images/Segment-tree.png) We only catch the root node in programming. If we want to explore the bottom of the tree, and use `pushUp` to update every node, the task will be reached. So it asked us to traverse the tree, that spent `O(n)` time to do this with any way. This can't conform our expectations. Then we started to think about `pushDown` to update down from the root. **After we update the parent, the data continued to distributed to its children according to law.** But it still need `O(n)` time to do this. Keep thinking, we **only update the parent, and to update the children when `query` time**. Yeah, that's the key of **lazy propagation**. Because the recursing direct of the `query` and `update interval` is same. So we got it! 😁 Let's check this sample: ![lazy-sample-2](Images/lazy-sample-2.png) `update` make the subscript 1...3 elements plus 2, so we make the 1st node in 2 depth and 3rd in 3 depth get a *lazy mark*, which means these node need to be updated. And we shouldn't add a *lazy mark* for root node, because it was updated before the `pushDown` in the first recursing. In `query` operation, we accord to the original method to recurs the tree, and find the 1st node held *lazy mark* in 2 depth, so to update it. It's the same situation about the 1st node in 3 depth. Do you understand the **lazy propagation**? **In short, we only update the wide range node data and add it a lazy mark. Then they will be update when we need to query them.** And the *Update Down* operation is the function of `pushDown`. This is the complete implementation about the Sum Segment Tree with interval update operation: ```swift public class LazySegmentTree { private var value: Int private var leftBound: Int private var rightBound: Int private var leftChild: LazySegmentTree? private var rightChild: LazySegmentTree? // Interval Update Lazy Element private var lazyValue: Int // MARK: - Push Up Operation // Description: pushUp() - update items to the top private func pushUp(lson: LazySegmentTree, rson: LazySegmentTree) { self.value = lson.value + rson.value } // MARK: - Push Down Operation // Description: pushDown() - update items to the bottom private func pushDown(round: Int, lson: LazySegmentTree, rson: LazySegmentTree) { guard lazyValue != 0 else { return } lson.lazyValue += lazyValue rson.lazyValue += lazyValue lson.value += lazyValue * (round - (round >> 1)) rson.value += lazyValue * (round >> 1) lazyValue = 0 } public init(array: [Int], leftBound: Int, rightBound: Int) { self.leftBound = leftBound self.rightBound = rightBound self.value = 0 self.lazyValue = 0 guard leftBound != rightBound else { value = array[leftBound] return } let middle = leftBound + (rightBound - leftBound) / 2 leftChild = LazySegmentTree(array: array, leftBound: leftBound, rightBound: middle) rightChild = LazySegmentTree(array: array, leftBound: middle + 1, rightBound: rightBound) if let leftChild = leftChild, let rightChild = rightChild { pushUp(lson: leftChild, rson: rightChild) } } public convenience init(array: [Int]) { self.init(array: array, leftBound: 0, rightBound: array.count - 1) } public func query(leftBound: Int, rightBound: Int) -> Int { if leftBound <= self.leftBound && self.rightBound <= rightBound { return value } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } pushDown(round: self.rightBound - self.leftBound + 1, lson: leftChild, rson: rightChild) let middle = self.leftBound + (self.rightBound - self.leftBound) / 2 var result = 0 if leftBound <= middle { result += leftChild.query(leftBound: leftBound, rightBound: rightBound) } if rightBound > middle { result += rightChild.query(leftBound: leftBound, rightBound: rightBound) } return result } // MARK: - One Item Update public func update(index: Int, incremental: Int) { guard self.leftBound != self.rightBound else { self.value += incremental return } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } let middle = self.leftBound + (self.rightBound - self.leftBound) / 2 if index <= middle { leftChild.update(index: index, incremental: incremental) } else { rightChild.update(index: index, incremental: incremental) } pushUp(lson: leftChild, rson: rightChild) } // MARK: - Interval Item Update public func update(leftBound: Int, rightBound: Int, incremental: Int) { if leftBound <= self.leftBound && self.rightBound <= rightBound { self.lazyValue += incremental self.value += incremental * (self.rightBound - self.leftBound + 1) return } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } pushDown(round: self.rightBound - self.leftBound + 1, lson: leftChild, rson: rightChild) let middle = self.leftBound + (self.rightBound - self.leftBound) / 2 if leftBound <= middle { leftChild.update(leftBound: leftBound, rightBound: rightBound, incremental: incremental) } if middle < rightBound { rightChild.update(leftBound: leftBound, rightBound: rightBound, incremental: incremental) } pushUp(lson: leftChild, rson: rightChild) } } ``` Explain some sample snippets: ```swift private var lazyValue: Int ``` Here we add a new property for Segment Tree to represent *lazy mark*. And it is a incremental value for Sum Segment Tree. If the `lazyValue` isn't equal to zero, the current node need to be updated. And its real value is equal to `value + lazyValue * (rightBound - leftBound + 1)`. ```swift // MARK: - Push Down Operation // Description: pushDown() - update items to the bottom private func pushDown(round: Int, lson: LazySegmentTree, rson: LazySegmentTree) { guard lazyValue != 0 else { return } lson.lazyValue += lazyValue rson.lazyValue += lazyValue lson.value += lazyValue * (round - (round >> 1)) rson.value += lazyValue * (round >> 1) lazyValue = 0 } ``` ![pushdown](Images/pushdown.png) At first we check whether the node needs to be updated. If the `lazyValue` isn't equal to zero, we need to `pushDown`. And the update rules are the `lazyValue * (rightBound - leftBound + 1)`. At last, reset the `lazyValue` to zero. ## Conclusion This is the introduce of the Lazy Propagation in Segment Tree. You can also learn **Functional Segment Tree** to understand the Lazy Propagation deeply. In addition, I learn from the *notonlysuccess*'s code about Segment Tree described by C, this is the [link](http://www.cnblogs.com/Destiny-Gem/articles/3875243.html). In fact, the operation of Segment Tree is far more than that. It can also be used to handle problems between collections. I want to implement it with Swift in the future and make the Swift Segment Tree stronger and stronger. 😁 --- *Written for Swift Algorithm Club by [Desgard_Duan](https://github.com/desgard)* ================================================ FILE: Segment Tree/README.markdown ================================================ # Segment Tree > For an example on lazy propagation, see this [article](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Segment%20Tree/LazyPropagation). I'm pleased to present to you Segment Tree. It's actually one of my favorite data structures because it's very flexible and simple in realization. Let's suppose that you have an array **a** of some type and some associative function **f**. For example, the function can be sum, multiplication, min, max, [gcd](../GCD/), and so on. Your task is to: - answer a query for an interval given by **l** and **r**, i.e. perform `f(a[l], a[l+1], ..., a[r-1], a[r])` - support replacing an item at some index `a[index] = newItem` For example, if we have an array of numbers: ```swift var a = [ 20, 3, -1, 101, 14, 29, 5, 61, 99 ] ``` We want to query this array on the interval from 3 to 7 for the function "sum". That means we do the following: 101 + 14 + 29 + 5 + 61 = 210 because `101` is at index 3 in the array and `61` is at index 7. So we pass all the numbers between `101` and `61` to the sum function, which adds them all up. If we had used the "min" function, the result would have been `5` because that's the smallest number in the interval from 3 to 7. Here's naive approach if our array's type is `Int` and **f** is just the sum of two integers: ```swift func query(array: [Int], l: Int, r: Int) -> Int { var sum = 0 for i in l...r { sum += array[i] } return sum } ``` The running time of this algorithm is **O(n)** in the worst case, that is when **l = 0, r = n-1** (where **n** is the number of elements in the array). And if we have **m** queries to answer we get **O(m*n)** complexity. If we have an array with 100,000 items (**n = 10^5**) and we have to do 100 queries (**m = 100**), then our algorithm will do **10^7** units of work. Ouch, that doesn't sound very good. Let's look at how we can improve it. Segment trees allow us to answer queries and replace items with **O(log n)** time. Isn't it magic? :sparkles: The main idea of segment trees is simple: we precalculate some segments in our array and then we can use those without repeating calculations. ## Structure of segment tree A segment tree is just a [binary tree](../Binary%20Tree/) where each node is an instance of the `SegmentTree` class: ```swift public class SegmentTree { private var value: T private var function: (T, T) -> T private var leftBound: Int private var rightBound: Int private var leftChild: SegmentTree? private var rightChild: SegmentTree? } ``` Each node has the following data: - `leftBound` and `rightBound` describe an interval - `leftChild` and `rightChild` are pointers to child nodes - `value` is the result of applying the function `f(a[leftBound], a[leftBound+1], ..., a[rightBound-1], a[rightBound])` If our array is `[1, 2, 3, 4]` and the function `f = a + b`, the segment tree looks like this: ![structure](Images/Structure.png) The `leftBound` and `rightBound` of each node are marked in red. ## Building a segment tree Here's how we create a node of the segment tree: ```swift public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound self.function = function if leftBound == rightBound { // 1 value = array[leftBound] } else { let middle = (leftBound + rightBound) / 2 // 2 // 3 leftChild = SegmentTree(array: array, leftBound: leftBound, rightBound: middle, function: function) rightChild = SegmentTree(array: array, leftBound: middle+1, rightBound: rightBound, function: function) value = function(leftChild!.value, rightChild!.value) // 4 } } ``` Notice that this is a recursive method. You give it an array such as `[1, 2, 3, 4]` and it builds up the entire tree, from the root node to all the child nodes. 1. The recursion terminates if `leftBound` and `rightBound` are equal. Such a `SegmentTree` instance represents a leaf node. For the input array `[1, 2, 3, 4]`, this process will create four such leaf nodes: `1`, `2`, `3`, and `4`. We just fill in the `value` property with the number from the array. 2. However, if `rightBound` is still greater than `leftBound`, we create two child nodes. We divide the current segment into two equal segments (at least, if the length is even; if it's odd, one segment will be slightly larger). 3. Recursively build child nodes for those two segments. The left child node covers the interval **[leftBound, middle]** and the right child node covers **[middle+1, rightBound]**. 4. After having constructed our child nodes, we can calculate our own value because **f(leftBound, rightBound) = f(f(leftBound, middle), f(middle+1, rightBound))**. It's math! Building the tree is an **O(n)** operation. ## Getting answer to query We go through all this trouble so we can efficiently query the tree. Here's the code: ```swift public func query(withLeftBound: leftBound: Int, rightBound: Int) -> T { // 1 if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } // 2 if leftChild.rightBound < leftBound { return rightChild.query(withLeftBound: leftBound, rightBound: rightBound) // 3 } else if rightChild.leftBound > rightBound { return leftChild.query(withLeftBound: leftBound, rightBound: rightBound) // 4 } else { let leftResult = leftChild.query(withLeftBound: leftBound, rightBound: leftChild.rightBound) let rightResult = rightChild.query(withLeftBound: rightChild.leftBound, rightBound: rightBound) return function(leftResult, rightResult) } } ``` Again, this is a recursive method. It checks four different possibilities. 1) First, we check if the query segment is equal to the segment for which our current node is responsible. If it is we just return this node's value. ![equalSegments](Images/EqualSegments.png) 2) Does the query segment fully lie within the right child? If so, recursively perform the query on the right child. ![rightSegment](Images/RightSegment.png) 3) Does the query segment fully lie within the left child? If so, recursively perform the query on the left child. ![leftSegment](Images/LeftSegment.png) 4) If none of the above, it means our query partially lies in both children so we combine the results of queries on both children. ![mixedSegment](Images/MixedSegment.png) This is how you can test it out in a playground: ```swift let array = [1, 2, 3, 4] let sumSegmentTree = SegmentTree(array: array, function: +) sumSegmentTree.query(withLeftBound: 0, rightBound: 3) // 1 + 2 + 3 + 4 = 10 sumSegmentTree.query(withLeftBound: 1, rightBound: 2) // 2 + 3 = 5 sumSegmentTree.query(withLeftBound: 0, rightBound: 0) // just 1 sumSegmentTree.query(withLeftBound: 3, rightBound: 3) // just 4 ``` Querying the tree takes **O(log n)** time. ## Replacing items The value of a node in the segment tree depends on the nodes below it. So if we want to change a value of a leaf node, we need to update all its parent nodes too. Here is the code: ```swift public func replaceItem(at index: Int, withItem item: T) { if leftBound == rightBound { value = item } else if let leftChild = leftChild, rightChild = rightChild { if leftChild.rightBound >= index { leftChild.replaceItem(at: index, withItem: item) } else { rightChild.replaceItem(at: index, withItem: item) } value = function(leftChild.value, rightChild.value) } } ``` As usual, this works with recursion. If the node is a leaf, we just change its value. If the node is not a leaf, then we recursively call `replaceItem(at: )` to update its children. After that, we recalculate the node's own value so that it is up-to-date again. Replacing an item takes **O(log n)** time. See the playground for more examples of how to use the segment tree. ## See also [Lazy Propagation](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Segment%20Tree/LazyPropagation) implementation and explanation. [Segment tree at PEGWiki](http://wcipeg.com/wiki/Segment_tree) *Written for Swift Algorithm Club by [Artur Antonov](https://github.com/goingreen)* ================================================ FILE: Segment Tree/SegmentTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif public class SegmentTree { private var value: T private var function: (T, T) -> T private var leftBound: Int private var rightBound: Int private var leftChild: SegmentTree? private var rightChild: SegmentTree? public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound self.function = function if leftBound == rightBound { value = array[leftBound] } else { let middle = (leftBound + rightBound) / 2 leftChild = SegmentTree(array: array, leftBound: leftBound, rightBound: middle, function: function) rightChild = SegmentTree(array: array, leftBound: middle+1, rightBound: rightBound, function: function) value = function(leftChild!.value, rightChild!.value) } } public convenience init(array: [T], function: @escaping (T, T) -> T) { self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) } public func query(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } if leftChild.rightBound < leftBound { return rightChild.query(leftBound: leftBound, rightBound: rightBound) } else if rightChild.leftBound > rightBound { return leftChild.query(leftBound: leftBound, rightBound: rightBound) } else { let leftResult = leftChild.query(leftBound: leftBound, rightBound: leftChild.rightBound) let rightResult = rightChild.query(leftBound:rightChild.leftBound, rightBound: rightBound) return function(leftResult, rightResult) } } public func replaceItem(at index: Int, withItem item: T) { if leftBound == rightBound { value = item } else if let leftChild = leftChild, let rightChild = rightChild { if leftChild.rightBound >= index { leftChild.replaceItem(at: index, withItem: item) } else { rightChild.replaceItem(at: index, withItem: item) } value = function(leftChild.value, rightChild.value) } } } let array = [1, 2, 3, 4] let sumSegmentTree = SegmentTree(array: array, function: +) print(sumSegmentTree.query(leftBound: 0, rightBound: 3)) // 1 + 2 + 3 + 4 = 10 print(sumSegmentTree.query(leftBound: 1, rightBound: 2)) // 2 + 3 = 5 print(sumSegmentTree.query(leftBound: 0, rightBound: 0)) // 1 = 1 sumSegmentTree.replaceItem(at: 0, withItem: 2) //our array now is [2, 2, 3, 4] print(sumSegmentTree.query(leftBound: 0, rightBound: 0)) // 2 = 2 print(sumSegmentTree.query(leftBound: 0, rightBound: 1)) // 2 + 2 = 4 //you can use any associative function (i.e (a+b)+c == a+(b+c)) as function for segment tree func gcd(_ m: Int, _ n: Int) -> Int { var a = 0 var b = max(m, n) var r = min(m, n) while r != 0 { a = b b = r r = a % b } return b } let gcdArray = [2, 4, 6, 3, 5] let gcdSegmentTree = SegmentTree(array: gcdArray, function: gcd) print(gcdSegmentTree.query(leftBound: 0, rightBound: 1)) // gcd(2, 4) = 2 print(gcdSegmentTree.query(leftBound: 2, rightBound: 3)) // gcd(6, 3) = 3 print(gcdSegmentTree.query(leftBound: 1, rightBound: 3)) // gcd(4, 6, 3) = 1 print(gcdSegmentTree.query(leftBound: 0, rightBound: 4)) // gcd(2, 4, 6, 3, 5) = 1 gcdSegmentTree.replaceItem(at: 3, withItem: 10) //gcdArray now is [2, 4, 6, 10, 5] print(gcdSegmentTree.query(leftBound: 3, rightBound: 4)) // gcd(10, 5) = 5 //example of segment tree which finds minimum on given range let minArray = [2, 4, 1, 5, 3] let minSegmentTree = SegmentTree(array: minArray, function: min) print(minSegmentTree.query(leftBound: 0, rightBound: 4)) // min(2, 4, 1, 5, 3) = 1 print(minSegmentTree.query(leftBound: 0, rightBound: 1)) // min(2, 4) = 2 minSegmentTree.replaceItem(at: 2, withItem: 10) // minArray now is [2, 4, 10, 5, 3] print(minSegmentTree.query(leftBound: 0, rightBound: 4)) // min(2, 4, 10, 5, 3) = 2 //type of elements in array can be any type which has some associative function let stringArray = ["a", "b", "c", "A", "B", "C"] let stringSegmentTree = SegmentTree(array: stringArray, function: +) print(stringSegmentTree.query(leftBound: 0, rightBound: 1)) // "a"+"b" = "ab" print(stringSegmentTree.query(leftBound: 2, rightBound: 3)) // "c"+"A" = "cA" print(stringSegmentTree.query(leftBound: 1, rightBound: 3)) // "b"+"c"+"A" = "bcA" print(stringSegmentTree.query(leftBound: 0, rightBound: 5)) // "a"+"b"+"c"+"A"+"B"+"C" = "abcABC" stringSegmentTree.replaceItem(at: 0, withItem: "I") stringSegmentTree.replaceItem(at: 1, withItem: " like") stringSegmentTree.replaceItem(at: 2, withItem: " algorithms") stringSegmentTree.replaceItem(at: 3, withItem: " and") stringSegmentTree.replaceItem(at: 4, withItem: " swift") stringSegmentTree.replaceItem(at: 5, withItem: "!") print(stringSegmentTree.query(leftBound: 0, rightBound: 5)) ================================================ FILE: Segment Tree/SegmentTree.playground/contents.xcplayground ================================================ ================================================ FILE: Segment Tree/SegmentTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Segment Tree/SegmentTree.swift ================================================ /* Segment tree Performance: building the tree is O(n) query is O(log n) replace item is O(log n) */ public class SegmentTree { private var value: T private var function: (T, T) -> T private var leftBound: Int private var rightBound: Int private var leftChild: SegmentTree? private var rightChild: SegmentTree? public init(array: [T], leftBound: Int, rightBound: Int, function: @escaping (T, T) -> T) { self.leftBound = leftBound self.rightBound = rightBound self.function = function if leftBound == rightBound { value = array[leftBound] } else { let middle = (leftBound + rightBound) / 2 leftChild = SegmentTree(array: array, leftBound: leftBound, rightBound: middle, function: function) rightChild = SegmentTree(array: array, leftBound: middle+1, rightBound: rightBound, function: function) value = function(leftChild!.value, rightChild!.value) } } public convenience init(array: [T], function: @escaping (T, T) -> T) { self.init(array: array, leftBound: 0, rightBound: array.count-1, function: function) } public func query(leftBound: Int, rightBound: Int) -> T { if self.leftBound == leftBound && self.rightBound == rightBound { return self.value } guard let leftChild = leftChild else { fatalError("leftChild should not be nil") } guard let rightChild = rightChild else { fatalError("rightChild should not be nil") } if leftChild.rightBound < leftBound { return rightChild.query(leftBound: leftBound, rightBound: rightBound) } else if rightChild.leftBound > rightBound { return leftChild.query(leftBound: leftBound, rightBound: rightBound) } else { let leftResult = leftChild.query(leftBound: leftBound, rightBound: leftChild.rightBound) let rightResult = rightChild.query(leftBound:rightChild.leftBound, rightBound: rightBound) return function(leftResult, rightResult) } } public func replaceItem(at index: Int, withItem item: T) { if leftBound == rightBound { value = item } else if let leftChild = leftChild, let rightChild = rightChild { if leftChild.rightBound >= index { leftChild.replaceItem(at: index, withItem: item) } else { rightChild.replaceItem(at: index, withItem: item) } value = function(leftChild.value, rightChild.value) } } } ================================================ FILE: Select Minimum Maximum/Maximum.swift ================================================ /* Finds the maximum value in an array in O(n) time. */ func maximum(_ array: [T]) -> T? { guard var maximum = array.first else { return nil } for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum } ================================================ FILE: Select Minimum Maximum/Minimum.swift ================================================ /* Finds the minimum value in an array in O(n) time. */ func minimum(_ array: [T]) -> T? { guard var minimum = array.first else { return nil } for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum } ================================================ FILE: Select Minimum Maximum/MinimumMaximumPairs.swift ================================================ /* Finds the maximum and minimum value in an array in O(n) time. */ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { guard var minimum = array.first else { return nil } var maximum = minimum // if 'array' has an odd number of items, let 'minimum' or 'maximum' deal with the leftover let start = array.count % 2 // 1 if odd, skipping the first element for i in stride(from: start, to: array.count, by: 2) { let pair = (array[i], array[i+1]) if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 } if pair.1 < minimum { minimum = pair.1 } } else { if pair.1 > maximum { maximum = pair.1 } if pair.0 < minimum { minimum = pair.0 } } } return (minimum, maximum) } ================================================ FILE: Select Minimum Maximum/README.markdown ================================================ # Select Minimum / Maximum Goal: Find the minimum/maximum object in an unsorted array. ## Maximum or minimum We have an array of generic objects and we iterate over all the objects keeping track of the minimum/maximum element so far. ### An example Let's say the we want to find the maximum value in the unsorted list `[ 8, 3, 9, 4, 6 ]`. Pick the first number, `8`, and store it as the maximum element so far. Pick the next number from the list, `3`, and compare it to the current maximum. `3` is less than `8` so the maximum `8` does not change. Pick the next number from the list, `9`, and compare it to the current maximum. `9` is greater than `8` so we store `9` as the maximum. Repeat this process until the all elements in the list have been processed. ### The code Here is a simple implementation in Swift: ```swift func minimum(_ array: [T]) -> T? { guard var minimum = array.first else { return nil } for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum } func maximum(_ array: [T]) -> T? { guard var maximum = array.first else { return nil } for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum } ``` Put this code in a playground and test it like so: ```swift let array = [ 8, 3, 9, 4, 6 ] minimum(array) // This will return 3 maximum(array) // This will return 9 ``` ### In the Swift standard library The Swift library already contains an extension to `SequenceType` that returns the minimum/maximum element in a sequence. ```swift let array = [ 8, 3, 9, 4, 6 ] array.minElement() // This will return 3 array.maxElement() // This will return 9 ``` ```swift let array = [ 8, 3, 9, 4, 6 ] //swift3 array.min() // This will return 3 array.max() // This will return 9 ``` ## Maximum and minimum To find both the maximum and minimum values contained in array while minimizing the number of comparisons we can compare the items in pairs. ### An example Let's say the we want to find the minimum and maximum value in the unsorted list `[ 8, 3, 9, 6, 4 ]`. Pick the first number, `8`, and store it as the minimum and maximum element so far. Because we have an odd number of items we remove `8` from the list which leaves the pairs `[ 3, 9 ]` and `[ 6, 4 ]`. Pick the next pair of numbers from the list, `[ 3, 9 ]`. Of these two numbers, `3` is the smaller one, so we compare `3` to the current minimum `8`, and we compare `9` to the current maximum `8`. `3` is less than `8` so the new minimum is `3`. `9` is greater than `8` so the new maximum is `9`. Pick the next pair of numbers from the list, `[ 6, 4 ]`. Here, `4` is the smaller one, so we compare `4` to the current minimum `3`, and we compare `6` to the current maximum `9`. `4` is greater than `3` so the minimum does not change. `6` is less than `9` so the maximum does not change. The result is a minimum of `3` and a maximum of `9`. ### The code Here is a simple implementation in Swift: ```swift func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { guard var minimum = array.first else { return nil } var maximum = minimum // if 'array' has an odd number of items, let 'minimum' or 'maximum' deal with the leftover let start = array.count % 2 // 1 if odd, skipping the first element for i in stride(from: start, to: array.count, by: 2) { let pair = (array[i], array[i+1]) if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 } if pair.1 < minimum { minimum = pair.1 } } else { if pair.1 > maximum { maximum = pair.1 } if pair.0 < minimum { minimum = pair.0 } } } return (minimum, maximum) } ``` Put this code in a playground and test it like so: ```swift let result = minimumMaximum(array)! result.minimum // This will return 3 result.maximum // This will return 9 ``` By picking elements in pairs and comparing their maximum and minimum with the running minimum and maximum we reduce the number of comparisons to 3 for every 2 elements. ## Performance These algorithms run at **O(n)**. Each object in the array is compared with the running minimum/maximum so the time it takes is proportional to the array length. *Written by [Chris Pilcher](https://github.com/chris-pilcher)* ================================================ FILE: Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift ================================================ // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif // Compare each item to find minimum func minimum(_ array: [T]) -> T? { guard var minimum = array.first else { return nil } for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum } // Compare each item to find maximum func maximum(_ array: [T]) -> T? { guard var maximum = array.first else { return nil } for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum } // Compare in pairs to find minimum and maximum func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { guard !array.isEmpty else { return nil } var minimum = array.first! var maximum = array.first! // if 'array' has an odd number of items, let 'minimum' or 'maximum' deal with the leftover let start = array.count % 2 // 1 if odd, skipping the first element for i in stride(from: start, to: array.count, by: 2) { let pair = (array[i], array[i+1]) if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 } if pair.1 < minimum { minimum = pair.1 } } else { if pair.1 > maximum { maximum = pair.1 } if pair.0 < minimum { minimum = pair.0 } } } return (minimum, maximum) } // Test of minimum and maximum functions let array = [ 8, 3, 9, 4, 6 ] minimum(array) maximum(array) // Test of minimumMaximum function let result = minimumMaximum(array)! result.minimum result.maximum // Built-in Swift functions array.min() array.max() ================================================ FILE: Select Minimum Maximum/SelectMinimumMaximum.playground/contents.xcplayground ================================================ ================================================ FILE: Select Minimum Maximum/SelectMinimumMaximum.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Select Minimum Maximum/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Select Minimum Maximum/Tests/MaximumTests.swift ================================================ import XCTest class MaximumTests: XCTestCase { func testMaximumGivenAListContainingOneElement() { let array = [ 99 ] let result = maximum(array) XCTAssertEqual(result, 99) } func testMaximumGivenAListContainingMultipleElementsWithTheSameValue() { let array = [ 3, 16, 3, 16 ] let result = maximum(array) XCTAssertEqual(result, 16) } func testMaximumGivenAListOfOrderedElements() { let array = [ 3, 4, 6, 8, 9 ] let result = maximum(array) XCTAssertEqual(result, 9) } func testMaximumGivenAListOfReverseOrderedElements() { let array = [ 9, 8, 6, 4, 3 ] let result = maximum(array) XCTAssertEqual(result, 9) } func testMaximumGivenAnEmptyList() { let array = [Int]() let result = maximum(array) XCTAssertNil(result) } func testMaximumMatchesSwiftLibraryGivenARandomList() { for _ in 0...10 { for n in 1...100 { let array = createRandomList(n) let result = maximum(array) XCTAssertEqual(result, array.max()) } } } } ================================================ FILE: Select Minimum Maximum/Tests/MinimumMaximumPairsTests.swift ================================================ import XCTest class MinimumMaximumPairsTests: XCTestCase { func testMinimumAndMaximumGivenAListContainingOneElement() { let array = [ 8 ] let result = minimumMaximum(array)! XCTAssertEqual(result.minimum, 8) XCTAssertEqual(result.maximum, 8) } func testMinimumAndMaximumGivenAListContainingMultipleElementsWithTheSameValue() { let array = [ 8, 16, 8, 8 ] let result = minimumMaximum(array)! XCTAssertEqual(result.minimum, 8) XCTAssertEqual(result.maximum, 16) } func testMimimumAndMaximumGivenAListContainingAnEvenNumberOfElements() { let array = [ 3, 4, 6, 8 ] let result = minimumMaximum(array)! XCTAssertEqual(result.minimum, 3) XCTAssertEqual(result.maximum, 8) } func testMimimumAndMaximumGivenAListContainingAnOddNumberOfElements() { let array = [ 8, 3, 9, 4, 6 ] let result = minimumMaximum(array)! XCTAssertEqual(result.minimum, 3) XCTAssertEqual(result.maximum, 9) } func testMimimumAndMaximumGivenAListOfOrderedElements() { let array = [ 3, 4, 6, 8, 9 ] let result = minimumMaximum(array)! XCTAssertEqual(result.minimum, 3) XCTAssertEqual(result.maximum, 9) } func testMimimumAndMaximumGivenAListOfReverseOrderedElements() { let array = [ 9, 8, 6, 4, 3 ] let result = minimumMaximum(array)! XCTAssertEqual(result.minimum, 3) XCTAssertEqual(result.maximum, 9) } func testMinimumAndMaximumGivenAnEmptyList() { let array = [Int]() let result = minimumMaximum(array) XCTAssertNil(result) } func testMinimumAndMaximumMatchSwiftLibraryGivenARandomList() { for _ in 0...10 { for n in 1...100 { let array = createRandomList(n) let result = minimumMaximum(array)! XCTAssertEqual(result.minimum, array.min()) XCTAssertEqual(result.maximum, array.max()) } } } } ================================================ FILE: Select Minimum Maximum/Tests/MinimumTests.swift ================================================ import XCTest class MinimumTests: XCTestCase { func testMinimumGivenAListContainingOneElement() { let array = [ 54 ] let result = minimum(array) XCTAssertEqual(result, 54) } func testMinimumGivenAListContainingMultipleElementsWithTheSameValue() { let array = [ 2, 16, 2, 16 ] let result = minimum(array) XCTAssertEqual(result, 2) } func testMinimumGivenAListOfOrderedElements() { let array = [ 3, 4, 6, 8, 9 ] let result = minimum(array) XCTAssertEqual(result, 3) } func testMinimumGivenAListOfReverseOrderedElements() { let array = [ 9, 8, 6, 4, 3 ] let result = minimum(array) XCTAssertEqual(result, 3) } func testMinimumGivenAnEmptyList() { let array = [Int]() let result = minimum(array) XCTAssertNil(result) } func testMinimumMatchesSwiftLibraryGivenARandomList() { for _ in 0...10 { for n in 1...100 { let array = createRandomList(n) let result = minimum(array) XCTAssertEqual(result, array.min()) } } } } ================================================ FILE: Select Minimum Maximum/Tests/TestHelper.swift ================================================ import Foundation func createRandomList(_ numberOfElements: Int) -> [UInt32] { return (1...numberOfElements).map {_ in arc4random()} } ================================================ FILE: Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C40C1C77A768003CECC7 /* Maximum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4091C77A768003CECC7 /* Maximum.swift */; }; 7B80C40D1C77A768003CECC7 /* Minimum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C40A1C77A768003CECC7 /* Minimum.swift */; }; 7B80C40E1C77A768003CECC7 /* MinimumMaximumPairs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C40B1C77A768003CECC7 /* MinimumMaximumPairs.swift */; }; 7B80C4131C77A770003CECC7 /* MaximumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C40F1C77A770003CECC7 /* MaximumTests.swift */; }; 7B80C4141C77A770003CECC7 /* MinimumTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4101C77A770003CECC7 /* MinimumTests.swift */; }; 7B80C4151C77A770003CECC7 /* MinimumMaximumPairsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4111C77A770003CECC7 /* MinimumMaximumPairsTests.swift */; }; 7B80C4161C77A770003CECC7 /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4121C77A770003CECC7 /* TestHelper.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C4091C77A768003CECC7 /* Maximum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Maximum.swift; path = ../Maximum.swift; sourceTree = SOURCE_ROOT; }; 7B80C40A1C77A768003CECC7 /* Minimum.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Minimum.swift; path = ../Minimum.swift; sourceTree = SOURCE_ROOT; }; 7B80C40B1C77A768003CECC7 /* MinimumMaximumPairs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MinimumMaximumPairs.swift; path = ../MinimumMaximumPairs.swift; sourceTree = SOURCE_ROOT; }; 7B80C40F1C77A770003CECC7 /* MaximumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaximumTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C4101C77A770003CECC7 /* MinimumTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimumTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C4111C77A770003CECC7 /* MinimumMaximumPairsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimumMaximumPairsTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C4121C77A770003CECC7 /* TestHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHelper.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B2BBC941C779E7B0067B71D /* Info.plist */, 7B80C4091C77A768003CECC7 /* Maximum.swift */, 7B80C40F1C77A770003CECC7 /* MaximumTests.swift */, 7B80C40A1C77A768003CECC7 /* Minimum.swift */, 7B80C4101C77A770003CECC7 /* MinimumTests.swift */, 7B80C40B1C77A768003CECC7 /* MinimumMaximumPairs.swift */, 7B80C4111C77A770003CECC7 /* MinimumMaximumPairsTests.swift */, 7B80C4121C77A770003CECC7 /* TestHelper.swift */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0820; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C40D1C77A768003CECC7 /* Minimum.swift in Sources */, 7B80C40E1C77A768003CECC7 /* MinimumMaximumPairs.swift in Sources */, 7B80C4141C77A770003CECC7 /* MinimumTests.swift in Sources */, 7B80C40C1C77A768003CECC7 /* Maximum.swift in Sources */, 7B80C4131C77A770003CECC7 /* MaximumTests.swift in Sources */, 7B80C4161C77A770003CECC7 /* TestHelper.swift in Sources */, 7B80C4151C77A770003CECC7 /* MinimumMaximumPairsTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Select Minimum Maximum/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Selection Sampling/README.markdown ================================================ # Selection Sampling Goal: Select *k* items at random from a collection of *n* items. Let's say you have a deck of 52 playing cards and you need to draw 10 cards at random. This algorithm lets you do that. Here's a very fast version: ```swift func select(from a: [T], count k: Int) -> [T] { var a = a for i in 0..(from a: [T], count k: Int) -> [T] { precondition(a.count >= k) var result = [T]() // 1 for i in 0..(from a: [T], count requested: Int) -> [T] { var examined = 0 var selected = 0 var b = [T]() while selected < requested { // 1 let r = Double(arc4random()) / 0x100000000 // 2 let leftToExamine = a.count - examined // 3 let leftToAdd = requested - selected if Double(leftToExamine) * r < Double(leftToAdd) { // 4 selected += 1 b.append(a[examined]) } examined += 1 } return b } ``` This algorithm uses probability to decide whether to include a number in the selection or not. 1. The loop steps through the array from beginning to end. It keeps going until we've selected *k* items from our set of *n*. Here, *k* is called `requested` and *n* is `a.count`. 2. Calculate a random number between 0 and 1. We want `0.0 <= r < 1.0`. The higher bound is exclusive; we never want it to be exactly 1. That's why we divide the result from `arc4random()` by `0x100000000` instead of the more usual `0xffffffff`. 3. `leftToExamine` is how many items we still haven't looked at. `leftToAdd` is how many items we still need to select before we're done. 4. This is where the magic happens. Basically, we're flipping a coin. If it was heads, we add the current array element to the selection; if it was tails, we skip it. Interestingly enough, even though we use probability, this approach always guarantees that we end up with exactly *k* items in the output array. Let's walk through the same example again. The input array is: [ "a", "b", "c", "d", "e", "f", "g" ] The loop looks at each element in turn, so we start at `"a"`. We get a random number between 0 and 1, let's say it is 0.841. The formula at `// 4` multiplies the number of items left to examine with this random number. There are still 7 elements left to examine, so the result is: 7 * 0.841 = 5.887 We compare this to 3 because we wanted to select 3 items. Since 5.887 is greater than 3, we skip `"a"` and move on to `"b"`. Again, we get a random number, let's say 0.212. Now there are only 6 elements left to examine, so the formula gives: 6 * 0.212 = 1.272 This *is* less than 3 and we add `"b"` to the selection. This is the first item we've selected, so two left to go. On to the next element, `"c"`. The random number is 0.264, giving the result: 5 * 0.264 = 1.32 There are only 2 elements left to select, so this number must be less than 2. It is, and we also add `"c"` to the selection. The total selection is `[ "b", "c" ]`. Only one item left to select but there are still 4 candidates to look at. Suppose the next random number is 0.718. The formula now gives: 4 * 0.718 = 2.872 For this element to be selected the number has to be less than 1, as there is only 1 element left to be picked. It isn't, so we skip `"d"`. Only three possibilities left -- will we make it before we run out of elements? The random number is 0.346. The formula gives: 3 * 0.346 = 1.038 Just a tiny bit too high. We skip `"e"`. Only two candidates left... Note that now literally we're dealing with a coin toss: if the random number is less than 0.5 we select `"f"` and we're done. If it's greater than 0.5, we go on to the final element. Let's say we get 0.583: 2 * 0.583 = 1.166 We skip `"f"` and look at the very last element. Whatever random number we get here, it should always select `"g"` or we won't have selected enough elements and the algorithm doesn't work! Let's say our final random number is 0.999 (remember, it can never be 1.0 or higher). Actually, no matter what we choose here, the formula will always give a value less than 1: 1 * 0.999 = 0.999 And so the last element will always be chosen if we didn't have a big enough selection yet. The final selection is `[ "b", "c", "g" ]`. Notice that the elements are still in their original order, because we examined the array from left to right. Maybe you're not convinced yet... What if we always got 0.999 as the random value (the maximum possible), would that still select 3 items? Well, let's do the math: 7 * 0.999 = 6.993 is this less than 3? no 6 * 0.999 = 5.994 is this less than 3? no 5 * 0.999 = 4.995 is this less than 3? no 4 * 0.999 = 3.996 is this less than 3? no 3 * 0.999 = 2.997 is this less than 3? YES 2 * 0.999 = 1.998 is this less than 2? YES 1 * 0.999 = 0.999 is this less than 1? YES It always works! But does this mean that elements closer to the end of the array have a higher probability of being chosen than those in the beginning? Nope, all elements are equally likely to be selected. (Don't take my word for it: see the playground for a quick test that shows this in practice.) Here's an example of how to test this algorithm: ```swift let input = [ "there", "once", "was", "a", "man", "from", "nantucket", "who", "kept", "all", "of", "his", "cash", "in", "a", "bucket", "his", "daughter", "named", "nan", "ran", "off", "with", "a", "man", "and", "as", "for", "the", "bucket", "nan", "took", "it", ] let output = select(from: input, count: 10) print(output) print(output.count) ``` The performance of this second algorithm is **O(n)** as it may require a pass through the entire input array. > **Note:** If `k > n/2`, then it's more efficient to do it the other way around and choose `a.count - k` items to remove. Based on code from Algorithm Alley, Dr. Dobb's Magazine, October 1993. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Selection Sampling/SelectionSampling.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif import Foundation /* Returns a random integer in the range min...max, inclusive. */ public func random(min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } /* func select(from a: [T], count k: Int) -> [T] { var a = a for i in 0..(from a: [T], count requested: Int) -> [T] { var examined = 0 var selected = 0 var b = [T]() while selected < requested { // Calculate random variable 0.0 <= r < 1.0 (exclusive!). let r = Double(arc4random()) / 0x100000000 let leftToExamine = a.count - examined let leftToAdd = requested - selected // Decide whether to use the next record from the input. if Double(leftToExamine) * r < Double(leftToAdd) { selected += 1 b.append(a[examined]) } examined += 1 } return b } let poem = [ "there", "once", "was", "a", "man", "from", "nantucket", "who", "kept", "all", "of", "his", "cash", "in", "a", "bucket", "his", "daughter", "named", "nan", "ran", "off", "with", "a", "man", "and", "as", "for", "the", "bucket", "nan", "took", "it", ] let output = select(from: poem, count: 10) print(output) output.count // Use this to verify that all input elements have the same probability // of being chosen. The "counts" dictionary should have a roughly equal // count for each input element. /* let input = [ "a", "b", "c", "d", "e", "f", "g" ] var counts = [String: Int]() for x in input { counts[x] = 0 } for _ in 0...1000 { let output = select(from: input, count: 3) for x in output { counts[x] = counts[x]! + 1 } } print(counts) */ ================================================ FILE: Selection Sampling/SelectionSampling.playground/contents.xcplayground ================================================ ================================================ FILE: Selection Sampling/SelectionSampling.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Selection Sampling/SelectionSampling.swift ================================================ //: Playground - noun: a place where people can play import Foundation /* Returns a random integer in the range min...max, inclusive. */ public func random(min min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } /* Selects k items at random from an array of size n. Does not keep the elements in the original order. Performance: O(k). */ func select(from a: [T], count k: Int) -> [T] { var a = a for i in 0..(from a: [T], count k: Int) -> [T] { precondition(a.count >= k) var result = [T]() // Fill the result array with first k elements. for i in 0.. size/2`, then it's more efficient to do it the other way around and choose `count` items to remove. Based on code from Algorithm Alley, Dr. Dobb's Magazine, October 1993. */ func select(from a: [T], count requested: Int) -> [T] { var examined = 0 var selected = 0 var b = [T]() while selected < requested { // Calculate random variable 0.0 <= r < 1.0 (exclusive!). let r = Double(arc4random()) / 0x100000000 let leftToExamine = a.count - examined let leftToAdd = requested - selected // Decide whether to use the next record from the input. if Double(leftToExamine) * r < Double(leftToAdd) { selected += 1 b.append(a[examined]) } examined += 1 } return b } ================================================ FILE: Selection Sort/README.markdown ================================================ # Selection Sort Goal: To sort an array from low to high (or high to low). You are given an array of numbers and need to put them in the right order. The selection sort algorithm divides the array into two parts: the beginning of the array is sorted, while the rest of the array consists of the numbers that still remain to be sorted. [ ...sorted numbers... | ...unsorted numbers... ] This is similar to [insertion sort](../Insertion%20Sort/), but the difference is in how new numbers are added to the sorted portion. It works as follows: - Find the lowest number in the array. You must start at index 0, loop through all the numbers in the array, and keep track of what the lowest number is. - Swap the lowest number with the number at index 0. Now, the sorted portion consists of just the number at index 0. - Go to index 1. - Find the lowest number in the rest of the array. This time you start looking from index 1. Again you loop until the end of the array and keep track of the lowest number you come across. - Swap the lowest number with the number at index 1. Now, the sorted portion contains two numbers and extends from index 0 to index 1. - Go to index 2. - Find the lowest number in the rest of the array, starting from index 2, and swap it with the one at index 2. Now, the array is sorted from index 0 to 2; this range contains the three lowest numbers in the array. - And continue until no numbers remain to be sorted. It is called a "selection" sort because at every step you search through the rest of the array to select the next lowest number. ## An example Suppose the numbers to sort are `[ 5, 8, 3, 4, 6 ]`. We also keep track of where the sorted portion of the array ends, denoted by the `|` symbol. Initially, the sorted portion is empty: [| 5, 8, 3, 4, 6 ] Now we find the lowest number in the array. We do that by scanning through the array from left to right, starting at the `|` bar. We find the number `3`. To put this number into the sorted position, we swap it with the number next to the `|`, which is `5`: [ 3 | 8, 5, 4, 6 ] * * The sorted portion is now `[ 3 ]` and the rest is `[ 8, 5, 4, 6 ]`. Again, we look for the lowest number, starting from the `|` bar. We find `4` and swap it with `8` to get: [ 3, 4 | 5, 8, 6 ] * * With every step, the `|` bar moves one position to the right. We again look through the rest of the array and find `5` as the lowest number. There is no need to swap `5` with itself, and we simply move forward: [ 3, 4, 5 | 8, 6 ] * This process repeats until the array is sorted. Note that everything to the left of the `|` bar is always in sorted order and always contains the lowest numbers in the array. Finally, we end up with: [ 3, 4, 5, 6, 8 |] The selection sort is an *in-place* sort because everything happens in the same array without using additional memory. You can also implement this as a *stable* sort so that identical elements do not get swapped around relative to each other (note that the version given below is not stable). ## The code Here is an implementation of selection sort in Swift: ```swift func selectionSort(_ array: [Int]) -> [Int] { guard array.count > 1 else { return array } // 1 var a = array // 2 for x in 0 ..< a.count - 1 { // 3 var lowest = x for y in x + 1 ..< a.count { // 4 if a[y] < a[lowest] { lowest = y } } if x != lowest { // 5 a.swapAt(x, lowest) } } return a } ``` Put this code in a playground and test it like so: ```swift let list = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] selectionSort(list) ``` A step-by-step explanation of how the code works: 1. If the array is empty or only contains a single element, then there is no need to sort. 2. Make a copy of the array. This is necessary because we cannot modify the contents of the `array` parameter directly in Swift. Like the Swift's `sort()` function, the `selectionSort()` function will return a sorted *copy* of the original array. 3. There are two loops inside this function. The outer loop looks at each of the elements in the array in turn; this is what moves the `|` bar forward. 4. This is the inner loop. It finds the lowest number in the rest of the array. 5. Swap the lowest number with the current array index. The `if` check is necessary because you can't `swap()` an element with itself in Swift. In summary: For each element of the array, the selection sort swaps positions with the lowest value from the rest of the array. As a result, the array gets sorted from the left to the right. (You can also do it right-to-left, in which case you always look for the largest number in the array. Give that a try!) > **Note:** The outer loop ends at index `a.count - 2`. The very last element will automatically be in the correct position because at that point there are no other smaller elements left. The source file [SelectionSort.swift](SelectionSort.swift) has a version of this function that uses generics, so you can also use it to sort strings and other data types. ## Performance The selection sort is easy to understand but it performs slow as **O(n^2)**. It is worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble%20Sort/). Finding the lowest element in the rest of the array is slow, especially since the inner loop will be performed repeatedly. The [Heap sort](../Heap%20Sort/) uses the same principle as selection sort but has a fast method for finding the minimum value in the rest of the array. The heap sort' performance is **O(n log n)**. ## See also [Selection sort on Wikipedia](https://en.wikipedia.org/wiki/Selection_sort) *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Selection Sort/SelectionSort.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play let list = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] selectionSort(list) selectionSort(list, <) selectionSort(list, >) ================================================ FILE: Selection Sort/SelectionSort.playground/Sources/SelectionSort.swift ================================================ /// Performs the Selection sort algorithm on a array /// /// - Parameter array: array of elements that conform to the Comparable protocol /// - Returns: an array in ascending order public func selectionSort(_ array: [T]) -> [T] { return selectionSort(array, <) } /// Performs the Selection sort algorithm on a array using the provided comparisson method /// /// - Parameters: /// - array: array of elements that conform to the Comparable protocol /// - isLowerThan: returns true if the two provided elements are in the correct order /// - Returns: a sorted array public func selectionSort(_ array: [T], _ isLowerThan: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } var a = array for x in 0 ..< a.count - 1 { // Find the lowest value in the rest of the array. var lowest = x for y in x + 1 ..< a.count { if isLowerThan(a[y], a[lowest]) { lowest = y } } // Swap the lowest value with the current array index. if x != lowest { a.swapAt(x, lowest) } } return a } ================================================ FILE: Selection Sort/SelectionSort.playground/contents.xcplayground ================================================ ================================================ FILE: Selection Sort/SelectionSort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Selection Sort/SelectionSort.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Selection Sort/SelectionSort.swift ================================================ public func selectionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { guard array.count > 1 else { return array } var a = array for x in 0 ..< a.count - 1 { // Find the lowest value in the rest of the array. var lowest = x for y in x + 1 ..< a.count { if isOrderedBefore(a[y], a[lowest]) { lowest = y } } // Swap the lowest value with the current array index. if x != lowest { a.swapAt(x, lowest) } } return a } ================================================ FILE: Selection Sort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Selection Sort/Tests/SelectionSortTests.swift ================================================ import XCTest class SelectionSortTests: XCTestCase { func testSelectionSort() { checkSortAlgorithm(selectionSort) } } ================================================ FILE: Selection Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */; }; 7B80C3F01C77A590003CECC7 /* SelectionSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3EF1C77A590003CECC7 /* SelectionSortTests.swift */; }; 7B80C3F21C77A598003CECC7 /* SelectionSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F11C77A598003CECC7 /* SelectionSort.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = ../../Quicksort/Tests/SortingTestHelpers.swift; sourceTree = SOURCE_ROOT; }; 7B80C3EF1C77A590003CECC7 /* SelectionSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectionSortTests.swift; sourceTree = SOURCE_ROOT; }; 7B80C3F11C77A598003CECC7 /* SelectionSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SelectionSort.swift; path = ../SelectionSort.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3F11C77A598003CECC7 /* SelectionSort.swift */, 7B80C3EF1C77A590003CECC7 /* SelectionSortTests.swift */, 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3F01C77A590003CECC7 /* SelectionSortTests.swift in Sources */, 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */, 7B80C3F21C77A598003CECC7 /* SelectionSort.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Selection Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Selection Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Set Cover (Unweighted)/README.markdown ================================================ # Set Cover (Unweighted) If you have a group of sets, this algorithm finds a subset of those sets within that group whose union will cover an initial set that you're trying to match. The initial set is also known as the universe. For example, suppose you have a universe of `{1, 5, 7}` and you want to find the sets which cover the universe within the following group of sets: > {8, 4, 2} > {3, 1} > {7, 6, 5, 4} > {2} > {1, 2, 3} You can see that the sets `{3, 1} {7, 6, 5, 4}` when unioned together will cover the universe of `{1, 5, 7}`. Yes, there may be additional elements in the sets returned by the algorithm, but every element in the universe is represented in the cover itself. There may be cases where no cover exists. For example, if your universe is `{7, 9}`, there is no combination of sets within the group above that will yield a cover. ## The algorithm The Greedy Set Cover algorithm (unweighted) is provided here. It's known as greedy because it uses the largest intersecting set from the group of sets first before examining other sets in the group. This is part of the reason why the cover may have additional elements which are not part of the universe. The function (named `cover`) is provided as an extension of the Swift type `Set`. The function takes a single parameter, which is an array of sets. This array represents the group, and the set itself represents the universe. One of the first things done in `cover` is to make a copy of the universe in `remainingSet`. Then, the algorithm enters a `while` loop in which a call to `largestIntersectingSet` is made. The value returned from `largestIntersectingSet` is the set which has the most elements in common with the remaining universe identified by `remainingSet`. If all sets have nothing in common, `largestIntersectingSet` returns `nil`. If the result from `largestIntersectingSet` is not nil, that result is subtracted from `remainingSet` (reducing its size), and the loop continues until `remainingSet` has zero length (meaning a cover has been found) or until `largestIntersectingSet` returns `nil`. If there is no cover within the group of sets, `cover` returns `nil`. ## See also [Set cover problem on Wikipedia](https://en.wikipedia.org/wiki/Set_cover_problem) *Written for Swift Algorithm Club by [Michael C. Rael](https://github.com/mrael2)* *Migrated to Swift 3 by Jaap Wijnen* ================================================ FILE: Set Cover (Unweighted)/SetCover.playground/Contents.swift ================================================ // SetCover let universe1 = Set(1...7) let array1 = randomArrayOfSets(covering: universe1) let cover1 = universe1.cover(within: array1) let universe2 = Set(1...10) let array2: Array> = [[1, 2, 3, 4, 5, 6, 7], [8, 9]] let cover2 = universe2.cover(within: array2) let universe3 = Set(["tall", "heavy"]) let array3: Array> = [["tall", "light"], ["short", "heavy"], ["tall", "heavy", "young"]] let cover3 = universe3.cover(within: array3) let universe4 = Set(["tall", "heavy", "green"]) let cover4 = universe4.cover(within: array3) let universe5: Set = [16, 32, 64] let array5: Array> = [[16, 17, 18], [16, 32, 128], [1, 2, 3], [32, 64, 128]] let cover5 = universe5.cover(within: array5) let universe6: Set = [24, 89, 132, 90, 22] let array6 = randomArrayOfSets(covering: universe6) let cover6 = universe6.cover(within: array6) let universe7: Set = ["fast", "cheap", "good"] let array7 = randomArrayOfSets(covering: universe7, minArraySizeFactor: 20.0, maxSetSizeFactor: 0.7) let cover7 = universe7.cover(within: array7) let emptySet = Set() let coverTest1 = emptySet.cover(within: array1) let coverTest2 = universe1.cover(within: Array>()) let coverTest3 = emptySet.cover(within: Array>()) ================================================ FILE: Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift ================================================ import Foundation public func randomArrayOfSets(covering universe: Set, minArraySizeFactor: Double = 0.8, maxSetSizeFactor: Double = 0.6) -> Array> { var result = [Set]() var ongoingUnion = Set() let minArraySize = Int(Double(universe.count) * minArraySizeFactor) var maxSetSize = Int(Double(universe.count) * maxSetSizeFactor) if maxSetSize > universe.count { maxSetSize = universe.count } while true { var generatedSet = Set() let targetSetSize = Int.random(in: 0...maxSetSize) + 1 while true { let randomUniverseIndex = Int.random(in: 0...universe.count) for (setIndex, value) in universe.enumerated() { if setIndex == randomUniverseIndex { generatedSet.insert(value) break } } if generatedSet.count == targetSetSize { result.append(generatedSet) ongoingUnion = ongoingUnion.union(generatedSet) break } } if result.count >= minArraySize { if ongoingUnion == universe { break } } } return result } ================================================ FILE: Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift ================================================ public extension Set { func cover(within array: Array>) -> Array>? { var result: [Set]? = [Set]() var remainingSet = self func largestIntersectingSet() -> Set? { var largestIntersectionLength = 0 var largestSet: Set? for set in array { let intersectionLength = remainingSet.intersection(set).count if intersectionLength > largestIntersectionLength { largestIntersectionLength = intersectionLength largestSet = set } } return largestSet } while !remainingSet.isEmpty { guard let largestSet = largestIntersectingSet() else { break } result!.append(largestSet) remainingSet = remainingSet.subtracting(largestSet) } if !remainingSet.isEmpty || isEmpty { result = nil } return result } } ================================================ FILE: Set Cover (Unweighted)/SetCover.playground/contents.xcplayground ================================================ ================================================ FILE: Set Cover (Unweighted)/SetCover.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Set Cover (Unweighted)/SetCover.swift ================================================ extension Set { func cover(within array: Array>) -> Array>? { var result: [Set]? = [Set]() var remainingSet = self func largestIntersectingSet() -> Set? { var largestIntersectionLength = 0 var largestSet: Set? for set in array { let intersectionLength = remainingSet.intersect(set).count if intersectionLength > largestIntersectionLength { largestIntersectionLength = intersectionLength largestSet = set } } return largestSet } while !remainingSet.isEmpty { guard let largestSet = largestIntersectingSet() else { break } result!.append(largestSet) remainingSet = remainingSet.subtract(largestSet) } if !remainingSet.isEmpty || isEmpty { result = nil } return result } } ================================================ FILE: Shell Sort/README.markdown ================================================ # Shell Sort Shell sort is based on [insertion sort](../Insertion%20Sort/) as a general way to improve its performance, by breaking the original list into smaller sublists which are then individually sorted using insertion sort. [There is a nice video created at Sapientia University](https://www.youtube.com/watch?v=CmPA7zE8mx0) which shows the process as a Hungarian folk dance. ## How it works Instead of comparing elements that are side-by-side and swapping them if they are out of order, the way insertion sort does it, the shell sort algorithm compares elements that are far apart. The distance between elements is known as the *gap*. If the elements being compared are in the wrong order, they are swapped across the gap. This eliminates many in-between copies that are common with insertion sort. The idea is that by moving the elements over large gaps, the array becomes partially sorted quite quickly. This makes later passes faster because they don't have to swap so many items anymore. Once a pass has been completed, the gap is made smaller and a new pass starts. This repeats until the gap has size 1, at which point the algorithm functions just like insertion sort. But since the data is already fairly well sorted by then, the final pass can be very quick. ## An example Suppose we want to sort the array `[64, 20, 50, 33, 72, 10, 23, -1, 4]` using shell sort. We start by dividing the length of the array by 2: n = floor(9/2) = 4 This is the gap size. We create `n` sublists. In each sublist, the items are spaced apart by a gap of size `n`. In our example, we need to make four of these sublists. The sublists are sorted by the `insertionSort()` function. That may not have made a whole lot of sense, so let's take a closer look at what happens. The first pass is as follows. We have `n = 4`, so we make four sublists: sublist 0: [ 64, xx, xx, xx, 72, xx, xx, xx, 4 ] sublist 1: [ xx, 20, xx, xx, xx, 10, xx, xx, xx ] sublist 2: [ xx, xx, 50, xx, xx, xx, 23, xx, xx ] sublist 3: [ xx, xx, xx, 33, xx, xx, xx, -1, xx ] As you can see, each sublist contains only every 4th item from the original array. The items that are not in a sublist are marked with `xx`. So the first sublist is `[ 64, 72, 4 ]` and the second is `[ 20, 10 ]`, and so on. The reason we use this "gap" is so that we don't have to actually make new arrays. Instead, we interleave them in the original array. We now call `insertionSort()` once on each sublist. This particular version of [insertion sort](../Insertion%20Sort/) sorts from the back to the front. Each item in the sublist is compared against the others. If they're in the wrong order, the value is swapped and travels all the way down until we reach the start of the sublist. So for sublist 0, we swap `4` with `72`, then swap `4` with `64`. After sorting, this sublist looks like: sublist 0: [ 4, xx, xx, xx, 64, xx, xx, xx, 72 ] The other three sublists after sorting: sublist 1: [ xx, 10, xx, xx, xx, 20, xx, xx, xx ] sublist 2: [ xx, xx, 23, xx, xx, xx, 50, xx, xx ] sublist 3: [ xx, xx, xx, -1, xx, xx, xx, 33, xx ] The total array looks like this now: [ 4, 10, 23, -1, 64, 20, 50, 33, 72 ] It's not entirely sorted yet but it's more sorted than before. This completes the first pass. In the second pass, we divide the gap size by two: n = floor(4/2) = 2 That means we now create only two sublists: sublist 0: [ 4, xx, 23, xx, 64, xx, 50, xx, 72 ] sublist 1: [ xx, 10, xx, -1, xx, 20, xx, 33, xx ] Each sublist contains every 2nd item. Again, we call `insertionSort()` to sort these sublists. The result is: sublist 0: [ 4, xx, 23, xx, 50, xx, 64, xx, 72 ] sublist 1: [ xx, -1, xx, 10, xx, 20, xx, 33, xx ] Note that in each list only two elements were out of place. So the insertion sort is really fast. That's because we already sorted the array a little in the first pass. The total array looks like this now: [ 4, -1, 23, 10, 50, 20, 64, 33, 72 ] This completes the second pass. The gap size of the final pass is: n = floor(2/2) = 1 A gap size of 1 means we only have a single sublist, the array itself, and once again we call `insertionSort()` to sort it. The final sorted array is: [ -1, 4, 10, 20, 23, 33, 50, 64, 72 ] The performance of shell sort is **O(n^2)** in most cases or **O(n log n)** if you get lucky. This algorithm produces an unstable sort; it may change the relative order of elements with equal values. ## The gap sequence The "gap sequence" determines the initial size of the gap and how it is made smaller with each iteration. A good gap sequence is important for shell sort to perform well. The gap sequence in this implementation is the one from Shell's original version: the initial value is half the array size and then it is divided by 2 each time. There are other ways to calculate the gap sequence. ## Just for fun... This is an old Commodore 64 BASIC version of shell sort that Matthijs used a long time ago and ported to pretty much every programming language he ever used: 61200 REM S is the array to be sorted 61205 REM AS is the number of elements in S 61210 W1=AS 61220 IF W1<=0 THEN 61310 61230 W1=INT(W1/2): W2=AS-W1 61240 V=0 61250 FOR N1=0 TO W2-1 61260 W3=N1+W1 61270 IF S(N1)>S(W3) THEN SH=S(N1): S(N1)=S(W3): S(W3)=SH: V=1 61280 NEXT N1 61290 IF V>0 THEN 61240 61300 GOTO 61220 61310 RETURN ## The Code: Here is an implementation of Shell Sort in Swift: ``` var arr = [64, 20, 50, 33, 72, 10, 23, -1, 4, 5] public func shellSort(_ list: inout [Int]) { var sublistCount = list.count / 2 while sublistCount > 0 { for pos in 0..=4.0) print("Hello, Swift 4!") #endif public func insertionSort(_ list: inout [Int], start: Int, gap: Int) { for i in stride(from: (start + gap), to: list.count, by: gap) { let currentValue = list[i] var pos = i while pos >= gap && list[pos - gap] > currentValue { list[pos] = list[pos - gap] pos -= gap } list[pos] = currentValue } } public func shellSort(_ list: inout [Int]) { var sublistCount = list.count / 2 while sublistCount > 0 { for pos in 0.. ================================================ FILE: Shell Sort/ShellSortExample.swift ================================================ // // ShellSortExample.swift // // // Created by Cheer on 2017/2/26. // // import Foundation public func shellSort(_ list : inout [Int]) { var sublistCount = list.count / 2 while sublistCount > 0 { for var index in 0.. list[index + sublistCount] { swap(&list[index], &list[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } while index > 0 && list[index - 1] > list[index] { swap(&list[index - 1], &list[index]) index -= 1 } } sublistCount = sublistCount / 2 } } ================================================ FILE: Shell Sort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Shell Sort/Tests/ShellSortTests.swift ================================================ import XCTest class ShellSortTests: XCTestCase { func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testShellSort() { checkSortAlgorithm { (a: [Int]) -> [Int] in var b = a shellSort(&b) return b } } } ================================================ FILE: Shell Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */; }; 7B80C3F41C77A5D3003CECC7 /* ShellSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F31C77A5D3003CECC7 /* ShellSort.swift */; }; 7B80C3F61C77A5D9003CECC7 /* ShellSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3F51C77A5D9003CECC7 /* ShellSortTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SortingTestHelpers.swift; path = ../../Quicksort/Tests/SortingTestHelpers.swift; sourceTree = SOURCE_ROOT; }; 7B80C3F31C77A5D3003CECC7 /* ShellSort.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShellSort.swift; path = ../ShellSort.swift; sourceTree = SOURCE_ROOT; }; 7B80C3F51C77A5D9003CECC7 /* ShellSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShellSortTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C3F31C77A5D3003CECC7 /* ShellSort.swift */, 7B80C3F51C77A5D9003CECC7 /* ShellSortTests.swift */, 7B80C3E81C77A4D0003CECC7 /* SortingTestHelpers.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C3F61C77A5D9003CECC7 /* ShellSortTests.swift in Sources */, 7B80C3EA1C77A4D0003CECC7 /* SortingTestHelpers.swift in Sources */, 7B80C3F41C77A5D3003CECC7 /* ShellSort.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_VERSION = 4.0; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Shell Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Shell Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Shell Sort/shellsort.swift ================================================ // The MIT License (MIT) // Copyright (c) 2016 Mike Taghavi (mitghi[at]me.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. public func insertionSort(_ list: inout [Int], start: Int, gap: Int) { for i in stride(from: (start + gap), to: list.count, by: gap) { let currentValue = list[i] var pos = i while pos >= gap && list[pos - gap] > currentValue { list[pos] = list[pos - gap] pos -= gap } list[pos] = currentValue } } public func shellSort(_ list: inout [Int]) { var sublistCount = list.count / 2 while sublistCount > 0 { for pos in 0.. Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label) queue.enqueue(element: sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } } return shortestPathGraph } ``` Put this code in a playground and test it like so: ```swift let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA) print(shortestPathGraph.nodes) ``` This will output: Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1), Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2), Node(label: g, distance: 2), Node(label: h, distance: 3) > **Note:** This version of `breadthFirstSearchShortestPath()` does not actually produce the tree, it only computes the distances. See [minimum spanning tree](../Minimum%20Spanning%20Tree%20(Unweighted)/) on how you can convert the graph into a tree by removing edges. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* ================================================ FILE: Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift ================================================ // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label) queue.enqueue(element: sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } } return shortestPathGraph } let graph = Graph() let nodeA = graph.addNode(label: "a") let nodeB = graph.addNode(label: "b") let nodeC = graph.addNode(label: "c") let nodeD = graph.addNode(label: "d") let nodeE = graph.addNode(label: "e") let nodeF = graph.addNode(label: "f") let nodeG = graph.addNode(label: "g") let nodeH = graph.addNode(label: "h") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeD) graph.addEdge(nodeB, neighbor: nodeE) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA) print(shortestPathGraph.nodes) ================================================ FILE: Shortest Path (Unweighted)/ShortestPath.playground/Sources/Edge.swift ================================================ public class Edge: Equatable { public var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor } } public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } ================================================ FILE: Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift ================================================ public class Graph: CustomStringConvertible, Equatable { public private(set) var nodes: [Node] public init() { self.nodes = [] } public func addNode(label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } public var description: String { var description = "" for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } public func findNodeWithLabel(label: String) -> Node { return nodes.filter { $0.label == label }.first! } public func duplicate() -> Graph { let duplicated = Graph() for node in nodes { duplicated.addNode(label: node.label) } for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(label: node.label) let neighbour = duplicated.findNodeWithLabel(label: edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } return duplicated } } public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } ================================================ FILE: Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift ================================================ public class Node: CustomStringConvertible, Equatable { public var neighbors: [Edge] public private(set) var label: String public var distance: Int? public var visited: Bool public init(label: String) { self.label = label neighbors = [] visited = false } public var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } public var hasDistance: Bool { return distance != nil } public func remove(edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } ================================================ FILE: Shortest Path (Unweighted)/ShortestPath.playground/Sources/Queue.swift ================================================ public struct Queue { private var array: [T] public init() { array = [] } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public func peek() -> T? { return array.first } } ================================================ FILE: Shortest Path (Unweighted)/ShortestPath.playground/contents.xcplayground ================================================ ================================================ FILE: Shortest Path (Unweighted)/ShortestPath.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Shortest Path (Unweighted)/ShortestPath.swift ================================================ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label) queue.enqueue(element: sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 while let current = queue.dequeue() { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } } return shortestPathGraph } ================================================ FILE: Shortest Path (Unweighted)/Tests/Graph.swift ================================================ // MARK: - Edge open class Edge: Equatable { open var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor } } public func == (lhs: Edge, rhs: Edge) -> Bool { return lhs.neighbor == rhs.neighbor } // MARK: - Node open class Node: CustomStringConvertible, Equatable { open var neighbors: [Edge] open fileprivate(set) var label: String open var distance: Int? open var visited: Bool public init(label: String) { self.label = label neighbors = [] visited = false } open var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } open var hasDistance: Bool { return distance != nil } open func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } public func == (lhs: Node, rhs: Node) -> Bool { return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors } // MARK: - Graph open class Graph: CustomStringConvertible, Equatable { open fileprivate(set) var nodes: [Node] public init() { self.nodes = [] } open func addNode(label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } open func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } open var description: String { var description = "" for node in nodes { if !node.neighbors.isEmpty { description += "[node: \(node.label) edges: \(node.neighbors.map { $0.neighbor.label})]" } } return description } open func findNodeWithLabel(label: String) -> Node { return nodes.filter { $0.label == label }.first! } open func duplicate() -> Graph { let duplicated = Graph() for node in nodes { duplicated.addNode(label: node.label) } for node in nodes { for edge in node.neighbors { let source = duplicated.findNodeWithLabel(label: node.label) let neighbour = duplicated.findNodeWithLabel(label: edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } return duplicated } } public func == (lhs: Graph, rhs: Graph) -> Bool { return lhs.nodes == rhs.nodes } ================================================ FILE: Shortest Path (Unweighted)/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Shortest Path (Unweighted)/Tests/Queue.swift ================================================ public struct Queue { fileprivate var array: [T] public init() { array = [] } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func enqueue(element: T) { array.append(element) } public mutating func dequeue() -> T? { if isEmpty { return nil } else { return array.removeFirst() } } public func peek() -> T? { return array.first } } ================================================ FILE: Shortest Path (Unweighted)/Tests/ShortestPathTests.swift ================================================ import XCTest class ShortestPathTests: XCTestCase { func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testShortestPathWhenGivenTree() { let tree = Graph() let nodeA = tree.addNode(label: "a") let nodeB = tree.addNode(label: "b") let nodeC = tree.addNode(label: "c") let nodeD = tree.addNode(label: "d") let nodeE = tree.addNode(label: "e") let nodeF = tree.addNode(label: "f") let nodeG = tree.addNode(label: "g") let nodeH = tree.addNode(label: "h") tree.addEdge(nodeA, neighbor: nodeB) tree.addEdge(nodeA, neighbor: nodeC) tree.addEdge(nodeB, neighbor: nodeD) tree.addEdge(nodeB, neighbor: nodeE) tree.addEdge(nodeC, neighbor: nodeF) tree.addEdge(nodeC, neighbor: nodeG) tree.addEdge(nodeE, neighbor: nodeH) let shortestPaths = breadthFirstSearchShortestPath(graph: tree, source: nodeA) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeA.label).distance, 0) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeB.label).distance, 1) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeC.label).distance, 1) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeD.label).distance, 2) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeE.label).distance, 2) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeF.label).distance, 2) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeG.label).distance, 2) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeH.label).distance, 3) } func testShortestPathWhenGivenGraph() { let graph = Graph() let nodeA = graph.addNode(label:"a") let nodeB = graph.addNode(label:"b") let nodeC = graph.addNode(label:"c") let nodeD = graph.addNode(label:"d") let nodeE = graph.addNode(label:"e") let nodeF = graph.addNode(label:"f") let nodeG = graph.addNode(label:"g") let nodeH = graph.addNode(label:"h") let nodeI = graph.addNode(label:"i") graph.addEdge(nodeA, neighbor: nodeB) graph.addEdge(nodeA, neighbor: nodeH) graph.addEdge(nodeB, neighbor: nodeA) graph.addEdge(nodeB, neighbor: nodeC) graph.addEdge(nodeB, neighbor: nodeH) graph.addEdge(nodeC, neighbor: nodeB) graph.addEdge(nodeC, neighbor: nodeD) graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeI) graph.addEdge(nodeD, neighbor: nodeC) graph.addEdge(nodeD, neighbor: nodeE) graph.addEdge(nodeD, neighbor: nodeF) graph.addEdge(nodeE, neighbor: nodeD) graph.addEdge(nodeE, neighbor: nodeF) graph.addEdge(nodeF, neighbor: nodeC) graph.addEdge(nodeF, neighbor: nodeD) graph.addEdge(nodeF, neighbor: nodeE) graph.addEdge(nodeF, neighbor: nodeG) graph.addEdge(nodeG, neighbor: nodeF) graph.addEdge(nodeG, neighbor: nodeH) graph.addEdge(nodeG, neighbor: nodeI) graph.addEdge(nodeH, neighbor: nodeA) graph.addEdge(nodeH, neighbor: nodeB) graph.addEdge(nodeH, neighbor: nodeG) graph.addEdge(nodeH, neighbor: nodeI) graph.addEdge(nodeI, neighbor: nodeC) graph.addEdge(nodeI, neighbor: nodeG) graph.addEdge(nodeI, neighbor: nodeH) let shortestPaths = breadthFirstSearchShortestPath(graph: graph, source: nodeA) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeA.label).distance, 0) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeB.label).distance, 1) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeC.label).distance, 2) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeD.label).distance, 3) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeE.label).distance, 4) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeF.label).distance, 3) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeG.label).distance, 2) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeH.label).distance, 1) XCTAssertEqual(shortestPaths.findNodeWithLabel(label: nodeI.label).distance, 2) } } ================================================ FILE: Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 83AACB441C8456D200DDAFC7 /* ShortestPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83AACB431C8456D200DDAFC7 /* ShortestPathTests.swift */; }; 83F9C96A1C84437C00B3A87F /* ShortestPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9671C84437C00B3A87F /* ShortestPath.swift */; }; 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C96E1C84449D00B3A87F /* Graph.swift */; }; 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83F9C9701C84449D00B3A87F /* Queue.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 83AACB431C8456D200DDAFC7 /* ShortestPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortestPathTests.swift; sourceTree = SOURCE_ROOT; }; 83F9C9671C84437C00B3A87F /* ShortestPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShortestPath.swift; path = ../ShortestPath.swift; sourceTree = SOURCE_ROOT; }; 83F9C96E1C84449D00B3A87F /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = SOURCE_ROOT; }; 83F9C9701C84449D00B3A87F /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 83F9C9671C84437C00B3A87F /* ShortestPath.swift */, 83AACB431C8456D200DDAFC7 /* ShortestPathTests.swift */, 83F9C96E1C84449D00B3A87F /* Graph.swift */, 83F9C9701C84449D00B3A87F /* Queue.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0820; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 83AACB441C8456D200DDAFC7 /* ShortestPathTests.swift in Sources */, 83F9C9721C84449D00B3A87F /* Graph.swift in Sources */, 83F9C9741C84449D00B3A87F /* Queue.swift in Sources */, 83F9C96A1C84437C00B3A87F /* ShortestPath.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_VERSION = 4.0; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Shortest Path (Unweighted)/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Shuffle/README.markdown ================================================ # Shuffle Goal: Rearrange the contents of an array. Imagine you're making a card game and you need to shuffle a deck of cards. You can represent the deck by an array of `Card` objects and shuffling the deck means to change the order of those objects in the array. (It's like the opposite of sorting.) Here is a naive way to approach this in Swift: ```swift extension Array { public mutating func shuffle() { var temp = [Element]() while !isEmpty { let i = random(count) let obj = remove(at: i) temp.append(obj) } self = temp } } ``` To try it out, copy the code into a playground and then do: ```swift var list = [ "a", "b", "c", "d", "e", "f", "g" ] list.shuffle() list.shuffle() list.shuffle() ``` You should see three different arrangements -- or [permutations](../Combinatorics/) to use math-speak -- of the objects in the array. This shuffle works *in place*, it modifies the contents of the original array. The algorithm works by creating a new array, `temp`, that is initially empty. Then we randomly choose an element from the original array and append it to `temp`, until the original array is empty. Finally, the temporary array is copied back into the original one. This code works just fine but it's not very efficient. Removing an element from an array is an **O(n)** operation and we perform this **n** times, making the total algorithm **O(n^2)**. We can do better! ## The Fisher-Yates / Knuth shuffle Here is a much-improved version of the shuffle algorithm: ```swift extension Array { public mutating func shuffle() { for i in stride(from: count - 1, through: 1, by: -1) { let j = Int.random(in: 0...i) if i != j { swap(&self[i], &self[j]) } } } } ``` Again, this picks objects at random. In the naive version, we placed those objects into a new temporary array so we could keep track of which objects were already shuffled and which still remained to be done. In this improved algorithm, however, we'll move the shuffled objects to the end of the original array. Let's walk through the example. We have the array: [ "a", "b", "c", "d", "e", "f", "g" ] The loop starts at the end of the array and works its way back to the beginning. The very first random number can be any element from the entire array. Let's say it returns 2, the index of `"c"`. We swap `"c"` with `"g"` to move it to the end: [ "a", "b", "g", "d", "e", "f" | "c" ] * * The array now consists of two regions, indicated by the `|` bar. Everything to the right of the bar is shuffled already. The next random number is chosen from the range 0...6, so only from the region `[ "a", "b", "g", "d", "e", "f" ]`. It will never choose `"c"` since that object is done and we'll no longer touch it. Let's say the random number generator picks 0, the index of `"a"`. Then we swap `"a"` with `"f"`, which is the last element in the unshuffled portion, and the array looks like this: [ "f", "b", "g", "d", "e" | "a", "c" ] * * The next random number is somewhere in `[ "f", "b", "g", "d", "e" ]`, so let's say it is 3. We swap `"d"` with `"e"`: [ "f", "b", "g", "e" | "d", "a", "c" ] * * And so on... This continues until there is only one element remaining in the left portion. For example: [ "b" | "e", "f", "g", "d", "a", "c" ] There's nothing left to swap that `"b"` with, so we're done. Because we only look at each array element once, this algorithm has a guaranteed running time of **O(n)**. It's as fast as you could hope to get! ## Creating a new array that is shuffled There is a slight variation on this algorithm that is useful for when you want to create a new array instance that contains the values `0` to `n-1` in random order. Here is the code: ```swift public func shuffledArray(_ n: Int) -> [Int] { var a = [Int](repeating: 0, count: n) for i in 0.. [Int] { var a = Array(repeating: 0, count: n) for i in 0.. ================================================ FILE: Shuffle/Shuffle.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Shuffle/Shuffle.swift ================================================ import Foundation /* Returns a random integer between 0 and n-1. */ public func random(_ n: Int) -> Int { return Int(arc4random_uniform(UInt32(n))) } extension Array { /* Randomly shuffles the array in-place This is the Fisher-Yates algorithm, also known as the Knuth shuffle. Time complexity: O(n) */ public mutating func shuffle() { for i in (1...count-1).reversed() { let j = random(i + 1) if i != j { let t = self[i] self[i] = self[j] self[j] = t } } } } /* Simultaneously initializes an array with the values 0...n-1 and shuffles it. */ public func shuffledArray(_ n: Int) -> [Int] { var a = Array(repeating: 0, count: n) for i in 0.. Bool { return left.precedence <= right.precedence } func < (left: OperatorToken, right: OperatorToken) -> Bool { return left.precedence < right.precedence } public struct Token: CustomStringConvertible { let tokenType: TokenType init(tokenType: TokenType) { self.tokenType = tokenType } init(operand: Double) { tokenType = .operand(operand) } init(operatorType: OperatorType) { tokenType = .Operator(OperatorToken(operatorType: operatorType)) } var isOpenBracket: Bool { switch tokenType { case .openBracket: return true default: return false } } var isOperator: Bool { switch tokenType { case .Operator(_): return true default: return false } } var operatorToken: OperatorToken? { switch tokenType { case .Operator(let operatorToken): return operatorToken default: return nil } } public var description: String { return tokenType.description } } public class InfixExpressionBuilder { private var expression = [Token]() public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } public func addOperand(_ operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } public func addOpenBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .openBracket)) return self } public func addCloseBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .closeBracket)) return self } public func build() -> [Token] { // Maybe do some validation here return expression } } // This returns the result of the shunting yard algorithm public func reversePolishNotation(_ expression: [Token]) -> String { var tokenStack = Stack() var reversePolishNotation = [Token]() for token in expression { switch token.tokenType { case .operand(_): reversePolishNotation.append(token) case .openBracket: tokenStack.push(token) case .closeBracket: while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) } case .Operator(let operatorToken): for tempToken in tokenStack.makeIterator() { if !tempToken.isOperator { break } if let tempOperatorToken = tempToken.operatorToken { if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { reversePolishNotation.append(tokenStack.pop()!) } else { break } } } tokenStack.push(token) } } while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } return reversePolishNotation.map({token in token.description}).joined(separator: " ") } // Simple demo let expr = InfixExpressionBuilder() .addOperand(3) .addOperator(.add) .addOperand(4) .addOperator(.multiply) .addOperand(2) .addOperator(.divide) .addOpenBracket() .addOperand(1) .addOperator(.subtract) .addOperand(5) .addCloseBracket() .addOperator(.exponent) .addOperand(2) .addOperator(.exponent) .addOperand(3) .build() print(expr.description) print(reversePolishNotation(expr)) ================================================ FILE: Shunting Yard/ShuntingYard.playground/Sources/Stack.swift ================================================ import Foundation public struct Stack { fileprivate var array = [T]() public init() { } public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func push(_ element: T) { array.append(element) } public mutating func pop() -> T? { return array.popLast() } public var top: T? { return array.last } } extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self return AnyIterator { curr.pop() } } } ================================================ FILE: Shunting Yard/ShuntingYard.playground/contents.xcplayground ================================================ ================================================ FILE: Shunting Yard/ShuntingYard.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Shunting Yard/ShuntingYard.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Shunting Yard/ShuntingYard.swift ================================================ // // ShuntingYardAlgorithm.swift // // // Created by Ali Hafizji on 2016-02-25. // // internal enum OperatorAssociativity { case leftAssociative case rightAssociative } public enum OperatorType: CustomStringConvertible { case add case subtract case divide case multiply case percent case exponent public var description: String { switch self { case .add: return "+" case .subtract: return "-" case .divide: return "/" case .multiply: return "*" case .percent: return "%" case .exponent: return "^" } } } public enum TokenType: CustomStringConvertible { case openBracket case closeBracket case Operator(OperatorToken) case operand(Double) public var description: String { switch self { case .openBracket: return "(" case .closeBracket: return ")" case .Operator(let operatorToken): return operatorToken.description case .operand(let value): return "\(value)" } } } public struct OperatorToken: CustomStringConvertible { let operatorType: OperatorType init(operatorType: OperatorType) { self.operatorType = operatorType } var precedence: Int { switch operatorType { case .add, .subtract: return 0 case .divide, .multiply, .percent: return 5 case .exponent: return 10 } } var associativity: OperatorAssociativity { switch operatorType { case .add, .subtract, .divide, .multiply, .percent: return .leftAssociative case .exponent: return .rightAssociative } } public var description: String { return operatorType.description } } func <= (left: OperatorToken, right: OperatorToken) -> Bool { return left.precedence <= right.precedence } func < (left: OperatorToken, right: OperatorToken) -> Bool { return left.precedence < right.precedence } public struct Token: CustomStringConvertible { let tokenType: TokenType init(tokenType: TokenType) { self.tokenType = tokenType } init(operand: Double) { tokenType = .operand(operand) } init(operatorType: OperatorType) { tokenType = .Operator(OperatorToken(operatorType: operatorType)) } var isOpenBracket: Bool { switch tokenType { case .openBracket: return true default: return false } } var isOperator: Bool { switch tokenType { case .Operator(_): return true default: return false } } var operatorToken: OperatorToken? { switch tokenType { case .Operator(let operatorToken): return operatorToken default: return nil } } public var description: String { return tokenType.description } } public class InfixExpressionBuilder { private var expression = [Token]() public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } public func addOperand(_ operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } public func addOpenBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .openBracket)) return self } public func addCloseBracket() -> InfixExpressionBuilder { expression.append(Token(tokenType: .closeBracket)) return self } public func build() -> [Token] { // Maybe do some validation here return expression } } // This returns the result of the shunting yard algorithm public func reversePolishNotation(_ expression: [Token]) -> String { var tokenStack = Stack() var reversePolishNotation = [Token]() for token in expression { switch token.tokenType { case .operand(_): reversePolishNotation.append(token) case .openBracket: tokenStack.push(token) case .closeBracket: while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) } case .Operator(let operatorToken): for tempToken in tokenStack.makeIterator() { if !tempToken.isOperator { break } if let tempOperatorToken = tempToken.operatorToken { if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { reversePolishNotation.append(tokenStack.pop()!) } else { break } } } tokenStack.push(token) } } while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } return reversePolishNotation.map({token in token.description}).joined(separator: " ") } ================================================ FILE: Simulated annealing/README.md ================================================ # Simulated annealing Simulated Annealing is a nature inspired global optimization technique and a metaheuristic to approximate global maxima in a (often discrete)large search space. The name comes from the process of annealing in metallurgy where a material is heated and cooled down under controlled conditions in order to improve its strength and durabilility. The objective is to find a minimum cost solution in the search space by exploiting properties of a thermodynamic system. Unlike hill climbing techniques which usually gets stuck in a local maxima ( downward moves are not allowed ), simulated annealing can escape local maxima. The interesting property of simulated annealing is that probability of allowing downward moves is high at the high temperatures and gradually reduced as it cools down. In other words, high temperature relaxes the acceptance criteria for the search space and triggers chaotic behavior of acceptance function in the algorithm (e.x initial/high temperature stages) which should make it possible to escape from local maxima and cooler temperatures narrows it and focuses on improvements. Pseucocode Input: initial, temperature, coolingRate, acceptance Output: Sbest Scurrent <- CreateInitialSolution(initial) Sbest <- Scurrent while temperature is not minimum: Snew <- FindNewSolution(Scurrent) if acceptance(Energy(Scurrent), Energy(Snew), temperature) > Rand(): Scurrent = Snew if Energy(Scurrent) < Energy(Sbest): Sbest = Scurrent temperature = temperature * (1-coolingRate) Common acceptance criteria : P(accept) <- exp((e-ne)/T) where e is the current energy ( current solution ), ne is new energy ( new solution ), T is current temperature. We use this algorithm to solve a Travelling salesman problem instance with 20 cities. The code is in `simann_example.swift` #See also [Simulated annealing on Wikipedia](https://en.wikipedia.org/wiki/Simulated_annealing) [Travelling salesman problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) Written for Swift Algorithm Club by [Mike Taghavi](https://github.com/mitghi) ================================================ FILE: Simulated annealing/simann.swift ================================================ // The MIT License (MIT) // Copyright (c) 2017 Mike Taghavi (mitghi[at]me.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #if os(OSX) import Foundation #elseif os(Linux) import Glibc #endif protocol Clonable { init(current: Self) } // MARK: - create a clone from instance extension Clonable { func clone() -> Self { return Self.init(current: self) } } protocol SAObject: Clonable { var count: Int { get } func randSwap(a: Int, b: Int) func currentEnergy() -> Double func shuffle() } // MARK: - create a new copy of elements extension Array where Element: Clonable { func clone() -> Array { var newArray = Array() for elem in self { newArray.append(elem.clone()) } return newArray } } typealias AcceptanceFunc = (Double, Double, Double) -> Double func SimulatedAnnealing(initial: T, temperature: Double, coolingRate: Double, acceptance: AcceptanceFunc) -> T { // Step 1: // Calculate the initial feasible solution based on a random permutation. // Set best and current solutions to initial solution var temp: Double = temperature var currentSolution = initial.clone() currentSolution.shuffle() var bestSolution = currentSolution.clone() // Step 2: // Repeat while the system is still hot // Randomly modify the current solution by swapping its elements // Randomly decide if the new solution ( neighbor ) is acceptable and set current solution accordingly // Update the best solution *iff* it had improved ( lower energy = improvement ) // Reduce temperature while temp > 1 { let newSolution: T = currentSolution.clone() let pos1: Int = Int.random(in: 0 ..< newSolution.count) let pos2: Int = Int.random(in: 0 ..< newSolution.count) newSolution.randSwap(a: pos1, b: pos2) let currentEnergy: Double = currentSolution.currentEnergy() let newEnergy: Double = newSolution.currentEnergy() if acceptance(currentEnergy, newEnergy, temp) > Double.random(in: 0 ..< 1) { currentSolution = newSolution.clone() } if currentSolution.currentEnergy() < bestSolution.currentEnergy() { bestSolution = currentSolution.clone() } temp *= 1-coolingRate } return bestSolution } ================================================ FILE: Simulated annealing/simann_example.swift ================================================ // The MIT License (MIT) // Copyright (c) 2017 Mike Taghavi (mitghi[at]me.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #if os(OSX) import Foundation import Cocoa #elseif os(Linux) import Glibc #endif protocol Clonable { init(current: Self) } extension Clonable { func clone() -> Self { return Self.init(current: self) } } protocol SAObject: Clonable { var count: Int { get } func randSwap(a: Int, b: Int) func currentEnergy() -> Double func shuffle() } // MARK: - create a new copy of elements extension Array where Element: Clonable { func clone() -> Array { var newArray = Array() for elem in self { newArray.append(elem.clone()) } return newArray } } typealias Points = [Point] typealias AcceptanceFunc = (Double, Double, Double) -> Double class Point: Clonable { var x: Int var y: Int init(x: Int, y: Int) { self.x = x self.y = y } required init(current: Point){ self.x = current.x self.y = current.y } } // MARK: - string representation extension Point: CustomStringConvertible { public var description: String { return "Point(\(x), \(y))" } } // MARK: - return distance between two points using operator '<->' infix operator <->: AdditionPrecedence extension Point { static func <-> (left: Point, right: Point) -> Double { let xDistance = (left.x - right.x) let yDistance = (left.y - right.y) return Double((xDistance * xDistance) + (yDistance * yDistance)).squareRoot() } } class Tour: SAObject { var tour: Points var energy: Double = 0.0 var count: Int { get { return self.tour.count } } init(points: Points){ self.tour = points.clone() } required init(current: Tour) { self.tour = current.tour.clone() } } // MARK: - calculate current tour distance ( energy ). extension Tour { func randSwap(a: Int, b: Int) -> Void { let (cpos1, cpos2) = (self[a], self[b]) self[a] = cpos2 self[b] = cpos1 } func currentEnergy() -> Double { if self.energy == 0 { var tourEnergy: Double = 0.0 for i in 0..destCity tourEnergy = tourEnergy + e } self.energy = tourEnergy } return self.energy } func shuffle() { self.tour.shuffle() } } // MARK: - subscript to manipulate elements of Tour. extension Tour { subscript(index: Int) -> Point { get { return self.tour[index] } set(newValue) { self.tour[index] = newValue } } } func SimulatedAnnealing(initial: T, temperature: Double, coolingRate: Double, acceptance: AcceptanceFunc) -> T { var temp: Double = temperature var currentSolution = initial.clone() currentSolution.shuffle() var bestSolution = currentSolution.clone() print("Initial solution: ", bestSolution.currentEnergy()) while temp > 1 { let newSolution: T = currentSolution.clone() let pos1: Int = Int.random(in: 0 ..< newSolution.count) let pos2: Int = Int.random(in: 0 ..< newSolution.count) newSolution.randSwap(a: pos1, b: pos2) let currentEnergy: Double = currentSolution.currentEnergy() let newEnergy: Double = newSolution.currentEnergy() if acceptance(currentEnergy, newEnergy, temp) > Double.random(in: 0 ..< 1) { currentSolution = newSolution.clone() } if currentSolution.currentEnergy() < bestSolution.currentEnergy() { bestSolution = currentSolution.clone() } temp *= 1-coolingRate } print("Best solution: ", bestSolution.currentEnergy()) return bestSolution } let points: [Point] = [ (60 , 200), (180, 200), (80 , 180), (140, 180), (20 , 160), (100, 160), (200, 160), (140, 140), (40 , 120), (100, 120), (180, 100), (60 , 80) , (120, 80) , (180, 60) , (20 , 40) , (100, 40) , (200, 40) , (20 , 20) , (60 , 20) , (160, 20) , ].map{ Point(x: $0.0, y: $0.1) } let acceptance : AcceptanceFunc = { (e: Double, ne: Double, te: Double) -> Double in if ne < e { return 1.0 } return exp((e - ne) / te) } let result: Tour = SimulatedAnnealing(initial : Tour(points: points), temperature : 100000.0, coolingRate : 0.003, acceptance : acceptance) ================================================ FILE: Single-Source Shortest Paths (Weighted)/README.markdown ================================================ # Single-Source Shortest Paths The Single-Source shortest path problem finds the shortest paths from a given source vertex to all other vertices in a directed weighted graph. Many variations exist on the problem, specifying whether or not edges may have negative values, whether cycles exist, or whether a path between a specific pair of vertices. ## Bellman-Ford The Bellman-Ford shortest paths algorithm finds the shortest paths to all vertices from a given source vertex `s` in a directed graph that may contain negative edge weights. It iterates over all edges for each other vertex in the graph, applying a relaxation to the current state of known shortest path weights. The intuition here is that a path will not contain more vertices than are present in the graph, so performing a pass over all edges `|V|-1` number of times is sufficient to compare all possible paths. At each step, a value is stored for each vertex `v`, which is the weight of the current known shortest path `s`~>`v`. This value remains 0 for the source vertex itself, and all others are initially `∞`. Then, they are "relaxed" by applying the following test to each edge `e = (u, v)` (where `u` is a source vertex and `v` is a destination vertex for the directed edge): if weights[v] > weights[u] + e.weight { weights[v] = weights[u] + e.weight } Bellman-Ford in essence only computes the lengths of the shortest paths, but can optionally maintain a structure that memoizes the predecessor of each vertex on its shortest path from the source vertex. Then the paths themselves can be reconstructed by recursing through this structure from a destination vertex to the source vertex. This is maintained by simply adding the statement predecessors[v] = u inside of the `if` statement's body above. ### Example For the following weighted directed graph: let's compute the shortest paths from vertex `s`. First, we prepare our `weights` and `predecessors` structures thusly: | weights | predecessors | | ------------- |:-------------:| | `weights[s] = 0` | `predecessors[s] = 1` | | `weights[t] = ∞` | `predecessors[t] = ø` | | `weights[x] = ∞` | `predecessors[x] = ø` | | `weights[y] = ∞` | `predecessors[y] = ø` | | `weights[z] = ∞` | `predecessors[z] = ø` | Here are their states after each relaxation iteration (each iteration is a pass over all edges, and there are 4 iterations total for this graph): ###### Iteration 1: | weights | predecessors | | ------------- |:-------------:| | `weights[s] = 0` | `predecessors[s] = s` | | `weights[t] = 6` | `predecessors[t] = s` | | `weights[x] = 4` | `predecessors[x] = y` | | `weights[y] = 7` | `predecessors[y] = s` | | `weights[z] = 2` | `predecessors[z] = t` | ###### Iteration 2: | weights | predecessors | | ------------- |:-------------:| | `weights[s] = 0` | `predecessors[s] = s` | | `weights[t] = 2` | `predecessors[t] = x` | | `weights[x] = 4` | `predecessors[x] = y` | | `weights[y] = 7` | `predecessors[y] = s` | | `weights[z] = 2` | `predecessors[z] = t` | ###### Iteration 3: | weights | predecessors | | ------------- |:-------------:| | `weights[s] = 0` | `predecessors[s] = s` | | `weights[t] = 2` | `predecessors[t] = x` | | `weights[x] = 4` | `predecessors[x] = y` | | `weights[y] = 7` | `predecessors[y] = s` | | `weights[z] = -2` | `predecessors[z] = t` | ###### Iteration 4: | weights | predecessors | | ------------- |:-------------:| | `weights[s] = 0` | `predecessors[s] = s` | | `weights[t] = 2` | `predecessors[t] = x` | | `weights[x] = 4` | `predecessors[x] = y` | | `weights[y] = 7` | `predecessors[y] = s` | | `weights[z] = -2` | `predecessors[z] = t` | #### Negative weight cycles An additional useful property of the solution structure is that it can answer whether or not a negative weight cycle exists in the graph and is reachable from the source vertex. A negative weight cycle is a cycle whose sum of edge weights is negative. This means that shortest paths are not well defined in the graph from the specified source, because you can decrease the weight of a path by reentering the cycle, pushing the path's weight towards `-∞`. After fully relaxing the paths, simply running a check over each edge `e = (u, v)` to see if the weight of the shortest path to `v` is greater than the path to `u`, plus the edge weight itself, signals that the edge has a negative weight and would decrease the shortest path's weight further. Since we know we've already performed the relaxations enough times according to the intuition stated above, we can safely assume this further decrease of weight will continue infinitely. ##### Example For this example, we try to compute the shortest paths from `a`: The cycle `a`->`t`->`s`->`a` has a total edge weight of -9, therefore shortest paths for `a`~>`t` and `a`~>`s` are not well-defined. `a`~>`b` is also not well-defined because `b`->`t`->`s` is also a negative weight cycle. This is confirmed after running the relaxation loop, and checking all the edges as mentioned above. For this graph, we would have after relaxation: | weights | | ------------- | | `weights[a] = -5` | | `weights[b] = -5` | | `weights[s] = -18` | | `weights[t] = -3` | One of the edge checks we would perform afterwards would be the following: e = (s, a) e.weight = 4 weight[a] > weight[s] + e.weight => -5 > -18 + 4 => -5 > -14 => true Because this check is true, we know the graph has a negative weight cycle reachable from `a`. #### Complexity The relaxation step requires constant time (`O(1)`) as it simply performs comparisons. That step is performed once per edge (`Θ(|E|)`), and the edges are iterated over `|V|-1` times. This would mean a total complexity of `Θ(|V||E|)`, but there is an optimization we can make: if the outer loop executes and no changes are made to the recorded weights, we can safely terminate the relaxation phase, which means it may execute in `O(|V|)` steps instead of `Θ(|V|)` steps (that is, the best case for any size graph is actually a constant number of iterations; the worst case is still iterating `|V|-1` times). The check for negative weight cycles at the end is `O(|E|)` if we return once we find a hit. To find all negative weight cycles reachable from the source vertex, we'd have to iterate `Θ(|E|)` times (we currently do not attempt to report the cycles, we simply return a `nil` result if such a cycle is present). The total running time of Bellman-Ford is therefore `O(|V||E|)`. ## TODO - Dijkstra's algorithm for computing SSSP on a directed non-negative weighted graph # References - Chapter 24 of Introduction to Algorithms, Third Edition by Cormen, Leiserson, Rivest and Stein [https://mitpress.mit.edu/books/introduction-algorithms](https://mitpress.mit.edu/books/introduction-algorithms) - Wikipedia: [Bellman–Ford algorithm](https://en.wikipedia.org/wiki/Bellman–Ford_algorithm) *Written for Swift Algorithm Club by [Andrew McKnight](https://github.com/armcknight)* ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift ================================================ // // BellmanFord.swift // SSSP // // Created by Andrew McKnight on 5/8/16. // import Foundation import Graph public struct BellmanFord where T: Hashable { public typealias Q = T } /** Encapsulation of the Bellman-Ford Single-Source Shortest Paths algorithm, which operates on a general directed graph that may contain negative edge weights. - note: In all complexity bounds, `V` is the number of vertices in the graph, and `E` is the number of edges. */ extension BellmanFord: SSSPAlgorithm { /** Compute the shortest path from `source` to each other vertex in `graph`, if such paths exist. Also report negative weight cycles reachable from `source`, which are cycles whose sum of edge weights is negative. - precondition: `graph` must have no negative weight cycles - complexity: `O(VE)` time, `Θ(V)` space - returns a `BellmanFordResult` struct which can be queried for shortest paths and their total weights, or `nil` if a negative weight cycle exists */ public static func apply(_ graph: AbstractGraph, source: Vertex) -> BellmanFordResult? { let vertices = graph.vertices let edges = graph.edges var predecessors = Array(repeating: nil, count: vertices.count) var weights = Array(repeating: Double.infinity, count: vertices.count) predecessors[source.index] = source.index weights[source.index] = 0 for _ in 0 ..< vertices.count - 1 { var weightsUpdated = false edges.forEach { edge in let weight = edge.weight! let relaxedDistance = weights[edge.from.index] + weight let nextVertexIdx = edge.to.index if relaxedDistance < weights[nextVertexIdx] { predecessors[nextVertexIdx] = edge.from.index weights[nextVertexIdx] = relaxedDistance weightsUpdated = true } } if !weightsUpdated { break } } // check for negative weight cycles reachable from the source vertex // TO DO: modify to incorporate solution to 24.1-4, pg 654, to set the // weight of a path containing a negative weight cycle to -∞, // instead of returning nil for the entire result for edge in edges { if weights[edge.to.index] > weights[edge.from.index] + edge.weight! { return nil } } return BellmanFordResult(predecessors: predecessors, weights: weights) } } /** `BellmanFordResult` encapsulates the result of the computation, namely the minimized distances, and the predecessor indices. It conforms to the `SSSPResult` procotol which provides methods to retrieve distances and paths between given pairs of start and end nodes. */ public struct BellmanFordResult where T: Hashable { fileprivate var predecessors: [Int?] fileprivate var weights: [Double] } extension BellmanFordResult: SSSPResult { /** - returns: the total weight of the path from the source vertex to a destination. This value is the minimal connected weight between the two vertices, or `nil` if no path exists - complexity: `Θ(1)` time/space */ public func distance(to: Vertex) -> Double? { let distance = weights[to.index] guard distance != Double.infinity else { return nil } return distance } /** - returns: the reconstructed path from the source vertex to a destination, as an array containing the data property of each vertex, or `nil` if no path exists - complexity: `Θ(V)` time, `Θ(V^2)` space */ public func path(to: Vertex, inGraph graph: AbstractGraph) -> [T]? { guard weights[to.index] != Double.infinity else { return nil } guard let path = recursePath(to: to, inGraph: graph, path: [to]) else { return nil } return path.map { vertex in return vertex.data } } /** The recursive component to rebuilding the shortest path between two vertices using predecessors. - returns: the list of predecessors discovered so far, or `nil` if the next vertex has no predecessor */ fileprivate func recursePath(to: Vertex, inGraph graph: AbstractGraph, path: [Vertex]) -> [Vertex]? { guard let predecessorIdx = predecessors[to.index] else { return nil } let predecessor = graph.vertices[predecessorIdx] if predecessor.index == to.index { return [ to ] } guard let buildPath = recursePath(to: predecessor, inGraph: graph, path: path) else { return nil } return buildPath + [ to ] } } ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP/SSSP.h ================================================ // // SSSP.h // SSSP // // Created by Andrew McKnight on 5/8/16. // #import //! Project version number for SSSP. FOUNDATION_EXPORT double SSSPVersionNumber; //! Project version string for SSSP. FOUNDATION_EXPORT const unsigned char SSSPVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift ================================================ // // SSSP.swift // SSSP // // Created by Andrew McKnight on 5/8/16. // import Foundation import Graph /** `SSSPAlgorithm` is a protocol for encapsulating a Single-Source Shortest Path algorithm. It provides a single function `apply` that accepts a subclass of `AbstractGraph` and returns an object conforming to `SSSPResult`. */ protocol SSSPAlgorithm { associatedtype Q: Equatable, Hashable associatedtype P: SSSPResult static func apply(_ graph: AbstractGraph, source: Vertex) -> P? } /** `SSSPResult` is a protocol defining functions `distance` and `path`, allowing for opaque queries into the actual data structures that represent the SSSP solution according to the algorithm used. */ protocol SSSPResult { associatedtype T: Equatable, Hashable func distance(to: Vertex) -> Double? func path(to: Vertex, inGraph graph: AbstractGraph) -> [T]? } ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift ================================================ import Graph import SSSP // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif let graph = AdjacencyMatrixGraph() let s = graph.createVertex("s") let t = graph.createVertex("t") let x = graph.createVertex("x") let y = graph.createVertex("y") let z = graph.createVertex("z") graph.addDirectedEdge(s, to: t, withWeight: 6) graph.addDirectedEdge(s, to: y, withWeight: 7) graph.addDirectedEdge(t, to: x, withWeight: 5) graph.addDirectedEdge(t, to: y, withWeight: 8) graph.addDirectedEdge(t, to: z, withWeight: -4) graph.addDirectedEdge(x, to: t, withWeight: -2) graph.addDirectedEdge(y, to: x, withWeight: -3) graph.addDirectedEdge(y, to: z, withWeight: 9) graph.addDirectedEdge(z, to: s, withWeight: 2) graph.addDirectedEdge(z, to: x, withWeight: 7) let result = BellmanFord.apply(graph, source: s)! let path = result.path(to: z, inGraph: graph) ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP.playground/contents.xcplayground ================================================ ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 49763FF21CF08FC500202EA9 /* Graph.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49763FEF1CF08FB100202EA9 /* Graph.framework */; }; 49BFA2971CDF86E100522D66 /* SSSP.h in Headers */ = {isa = PBXBuildFile; fileRef = 49BFA2961CDF86E100522D66 /* SSSP.h */; settings = {ATTRIBUTES = (Public, ); }; }; 49BFA29E1CDF86E100522D66 /* SSSP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49BFA2931CDF86E100522D66 /* SSSP.framework */; }; 49BFA2A31CDF86E100522D66 /* SSSPTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2A21CDF86E100522D66 /* SSSPTests.swift */; }; 49BFA2AE1CDF86FD00522D66 /* SSSP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2AD1CDF86FD00522D66 /* SSSP.swift */; }; 49BFA2B01CDF870600522D66 /* BellmanFord.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49BFA2AF1CDF870600522D66 /* BellmanFord.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 49763FEE1CF08FB100202EA9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */; proxyType = 2; remoteGlobalIDString = 49BFA2FD1CDF886B00522D66; remoteInfo = Graph; }; 49763FF01CF08FB100202EA9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */; proxyType = 2; remoteGlobalIDString = 49BFA3071CDF886B00522D66; remoteInfo = GraphTests; }; 49763FF31CF08FC900202EA9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */; proxyType = 1; remoteGlobalIDString = 49BFA2FC1CDF886B00522D66; remoteInfo = Graph; }; 49BFA29F1CDF86E100522D66 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 49BFA28A1CDF86E100522D66 /* Project object */; proxyType = 1; remoteGlobalIDString = 49BFA2921CDF86E100522D66; remoteInfo = SSSP; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Graph.xcodeproj; path = ../Graph/Graph.xcodeproj; sourceTree = ""; }; 49BFA2931CDF86E100522D66 /* SSSP.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSSP.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 49BFA2961CDF86E100522D66 /* SSSP.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSSP.h; sourceTree = ""; }; 49BFA2981CDF86E100522D66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49BFA29D1CDF86E100522D66 /* SSSPTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SSSPTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 49BFA2A21CDF86E100522D66 /* SSSPTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSSPTests.swift; sourceTree = ""; }; 49BFA2A41CDF86E100522D66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49BFA2AD1CDF86FD00522D66 /* SSSP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSSP.swift; sourceTree = ""; }; 49BFA2AF1CDF870600522D66 /* BellmanFord.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BellmanFord.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 49BFA28F1CDF86E100522D66 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 49763FF21CF08FC500202EA9 /* Graph.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 49BFA29A1CDF86E100522D66 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 49BFA29E1CDF86E100522D66 /* SSSP.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 49763FEA1CF08FB100202EA9 /* Products */ = { isa = PBXGroup; children = ( 49763FEF1CF08FB100202EA9 /* Graph.framework */, 49763FF11CF08FB100202EA9 /* GraphTests.xctest */, ); name = Products; sourceTree = ""; }; 49BFA2891CDF86E100522D66 = { isa = PBXGroup; children = ( 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */, 49BFA2951CDF86E100522D66 /* SSSP */, 49BFA2A11CDF86E100522D66 /* SSSPTests */, 49BFA2941CDF86E100522D66 /* Products */, ); sourceTree = ""; }; 49BFA2941CDF86E100522D66 /* Products */ = { isa = PBXGroup; children = ( 49BFA2931CDF86E100522D66 /* SSSP.framework */, 49BFA29D1CDF86E100522D66 /* SSSPTests.xctest */, ); name = Products; sourceTree = ""; }; 49BFA2951CDF86E100522D66 /* SSSP */ = { isa = PBXGroup; children = ( 49BFA2961CDF86E100522D66 /* SSSP.h */, 49BFA2AD1CDF86FD00522D66 /* SSSP.swift */, 49BFA2AF1CDF870600522D66 /* BellmanFord.swift */, 49BFA2981CDF86E100522D66 /* Info.plist */, ); path = SSSP; sourceTree = ""; }; 49BFA2A11CDF86E100522D66 /* SSSPTests */ = { isa = PBXGroup; children = ( 49BFA2A21CDF86E100522D66 /* SSSPTests.swift */, 49BFA2A41CDF86E100522D66 /* Info.plist */, ); path = SSSPTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 49BFA2901CDF86E100522D66 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 49BFA2971CDF86E100522D66 /* SSSP.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 49BFA2921CDF86E100522D66 /* SSSP */ = { isa = PBXNativeTarget; buildConfigurationList = 49BFA2A71CDF86E100522D66 /* Build configuration list for PBXNativeTarget "SSSP" */; buildPhases = ( 49BFA28E1CDF86E100522D66 /* Sources */, 49BFA28F1CDF86E100522D66 /* Frameworks */, 49BFA2901CDF86E100522D66 /* Headers */, 49BFA2911CDF86E100522D66 /* Resources */, ); buildRules = ( ); dependencies = ( 49763FF41CF08FC900202EA9 /* PBXTargetDependency */, ); name = SSSP; productName = SSSP; productReference = 49BFA2931CDF86E100522D66 /* SSSP.framework */; productType = "com.apple.product-type.framework"; }; 49BFA29C1CDF86E100522D66 /* SSSPTests */ = { isa = PBXNativeTarget; buildConfigurationList = 49BFA2AA1CDF86E100522D66 /* Build configuration list for PBXNativeTarget "SSSPTests" */; buildPhases = ( 49BFA2991CDF86E100522D66 /* Sources */, 49BFA29A1CDF86E100522D66 /* Frameworks */, 49BFA29B1CDF86E100522D66 /* Resources */, ); buildRules = ( ); dependencies = ( 49BFA2A01CDF86E100522D66 /* PBXTargetDependency */, ); name = SSSPTests; productName = SSSPTests; productReference = 49BFA29D1CDF86E100522D66 /* SSSPTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 49BFA28A1CDF86E100522D66 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 49BFA2921CDF86E100522D66 = { CreatedOnToolsVersion = 7.3; LastSwiftMigration = 0810; }; 49BFA29C1CDF86E100522D66 = { CreatedOnToolsVersion = 7.3; LastSwiftMigration = 0810; }; }; }; buildConfigurationList = 49BFA28D1CDF86E100522D66 /* Build configuration list for PBXProject "SSSP" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 49BFA2891CDF86E100522D66; productRefGroup = 49BFA2941CDF86E100522D66 /* Products */; projectDirPath = ""; projectReferences = ( { ProductGroup = 49763FEA1CF08FB100202EA9 /* Products */; ProjectRef = 49763FE91CF08FB100202EA9 /* Graph.xcodeproj */; }, ); projectRoot = ""; targets = ( 49BFA2921CDF86E100522D66 /* SSSP */, 49BFA29C1CDF86E100522D66 /* SSSPTests */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ 49763FEF1CF08FB100202EA9 /* Graph.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; path = Graph.framework; remoteRef = 49763FEE1CF08FB100202EA9 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 49763FF11CF08FB100202EA9 /* GraphTests.xctest */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; path = GraphTests.xctest; remoteRef = 49763FF01CF08FB100202EA9 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ 49BFA2911CDF86E100522D66 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 49BFA29B1CDF86E100522D66 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 49BFA28E1CDF86E100522D66 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 49BFA2B01CDF870600522D66 /* BellmanFord.swift in Sources */, 49BFA2AE1CDF86FD00522D66 /* SSSP.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 49BFA2991CDF86E100522D66 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 49BFA2A31CDF86E100522D66 /* SSSPTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 49763FF41CF08FC900202EA9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Graph; targetProxy = 49763FF31CF08FC900202EA9 /* PBXContainerItemProxy */; }; 49BFA2A01CDF86E100522D66 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 49BFA2921CDF86E100522D66 /* SSSP */; targetProxy = 49BFA29F1CDF86E100522D66 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 49BFA2A51CDF86E100522D66 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 49BFA2A61CDF86E100522D66 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 49BFA2A81CDF86E100522D66 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = SSSP/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; 49BFA2A91CDF86E100522D66 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = SSSP/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 4.0; }; name = Release; }; 49BFA2AB1CDF86E100522D66 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = SSSPTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; }; 49BFA2AC1CDF86E100522D66 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = SSSPTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSPTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 49BFA28D1CDF86E100522D66 /* Build configuration list for PBXProject "SSSP" */ = { isa = XCConfigurationList; buildConfigurations = ( 49BFA2A51CDF86E100522D66 /* Debug */, 49BFA2A61CDF86E100522D66 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 49BFA2A71CDF86E100522D66 /* Build configuration list for PBXNativeTarget "SSSP" */ = { isa = XCConfigurationList; buildConfigurations = ( 49BFA2A81CDF86E100522D66 /* Debug */, 49BFA2A91CDF86E100522D66 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 49BFA2AA1CDF86E100522D66 /* Build configuration list for PBXNativeTarget "SSSPTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 49BFA2AB1CDF86E100522D66 /* Debug */, 49BFA2AC1CDF86E100522D66 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 49BFA28A1CDF86E100522D66 /* Project object */; } ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme ================================================ ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSPTests.xcscheme ================================================ ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSP.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSPTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift ================================================ // // SSSPTests.swift // SSSPTests // // Created by Andrew McKnight on 5/8/16. // import Graph import XCTest @testable import SSSP class SSSPTests: XCTestCase { func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } /** See Figure 24.4 of “Introduction to Algorithms” by Cormen et al, 3rd ed., pg 652 */ func testExampleFromBook() { let graph = AdjacencyMatrixGraph() let s = graph.createVertex("s") let t = graph.createVertex("t") let x = graph.createVertex("x") let y = graph.createVertex("y") let z = graph.createVertex("z") graph.addDirectedEdge(s, to: t, withWeight: 6) graph.addDirectedEdge(s, to: y, withWeight: 7) graph.addDirectedEdge(t, to: x, withWeight: 5) graph.addDirectedEdge(t, to: y, withWeight: 8) graph.addDirectedEdge(t, to: z, withWeight: -4) graph.addDirectedEdge(x, to: t, withWeight: -2) graph.addDirectedEdge(y, to: x, withWeight: -3) graph.addDirectedEdge(y, to: z, withWeight: 9) graph.addDirectedEdge(z, to: s, withWeight: 2) graph.addDirectedEdge(z, to: x, withWeight: 7) let result = BellmanFord.apply(graph, source: s)! let expectedPath = ["s", "y", "x", "t", "z"] let computedPath = result.path(to: z, inGraph: graph)! XCTAssertEqual(expectedPath, computedPath, "expected path of \(expectedPath) but got \(computedPath)") let expectedWeight = -2.0 let computedWeight = result.distance(to: z) XCTAssertEqual(expectedWeight, computedWeight, "expected weight of \(expectedWeight) but got \(computedWeight)") } func testSimpleExample() { let graph = AdjacencyMatrixGraph() let a = graph.createVertex("a") let b = graph.createVertex("b") let c = graph.createVertex("c") let d = graph.createVertex("d") let e = graph.createVertex("e") graph.addDirectedEdge(a, to: b, withWeight: 4) graph.addDirectedEdge(a, to: c, withWeight: 5) graph.addDirectedEdge(a, to: d, withWeight: 8) graph.addDirectedEdge(b, to: c, withWeight: -2) graph.addDirectedEdge(c, to: e, withWeight: 4) graph.addDirectedEdge(d, to: e, withWeight: 2) graph.addDirectedEdge(e, to: d, withWeight: 1) let result = BellmanFord.apply(graph, source: a)! let expectedPath = ["a", "b", "c", "e", "d"] let computedPath = result.path(to: d, inGraph: graph)! XCTAssertEqual(expectedPath, computedPath, "expected path of \(expectedPath) but got \(computedPath)") let expectedWeight = 7.0 let computedWeight = result.distance(to: d) XCTAssertEqual(expectedWeight, computedWeight, "expected weight of \(expectedWeight) but got \(computedWeight)") } /** Construct a nearly bipartite graph, except one vertex only has out-edges. Then no path should exist from the source to that vertex. */ func testGraphWithUnreachableVertex() { let graph = AdjacencyMatrixGraph() let a = graph.createVertex("a") let b = graph.createVertex("b") let s = graph.createVertex("s") let t = graph.createVertex("t") graph.addDirectedEdge(a, to: s, withWeight: 9) graph.addDirectedEdge(a, to: t, withWeight: 2) graph.addDirectedEdge(b, to: a, withWeight: 1) graph.addDirectedEdge(b, to: s, withWeight: 2) graph.addDirectedEdge(b, to: t, withWeight: 3) graph.addDirectedEdge(s, to: a, withWeight: 4) graph.addDirectedEdge(s, to: t, withWeight: 1) graph.addDirectedEdge(t, to: a, withWeight: 7) graph.addDirectedEdge(t, to: s, withWeight: 5) let result = BellmanFord.apply(graph, source: a)! XCTAssertNil(result.path(to: b, inGraph: graph), "a path should not be defined from a ~> b") XCTAssertNil(result.distance(to: b), "a path should not be defined from a ~> b") XCTAssertNotNil(result.path(to: s, inGraph: graph), "a path should be defined from a ~> s") XCTAssertNotNil(result.distance(to: s), "a path should be defined from a ~> s") XCTAssertNotNil(result.path(to: t, inGraph: graph), "a path should be defined from a ~> t") XCTAssertNotNil(result.distance(to: t), "a path should be defined from a ~> t") } func testNegativeWeightCycle() { let graph = AdjacencyMatrixGraph() let a = graph.createVertex("a") let b = graph.createVertex("b") let s = graph.createVertex("s") let t = graph.createVertex("t") graph.addDirectedEdge(a, to: t, withWeight: 2) graph.addDirectedEdge(b, to: t, withWeight: 5) graph.addDirectedEdge(s, to: a, withWeight: 4) graph.addDirectedEdge(s, to: b, withWeight: 4) graph.addDirectedEdge(t, to: s, withWeight: -15) XCTAssertNil(BellmanFord.apply(graph, source: s), "negative weight cycle not reported") } } ================================================ FILE: Singly Linked List/KeyValuePair.swift ================================================ /// Conformers of this protocol represent a pair of comparable values /// This can be useful in many data structures and algorithms where items /// stored contain a value, but are ordered or retrieved according to a key. public protocol KeyValuePair : Comparable { associatedtype K : Comparable, Hashable associatedtype V : Comparable, Hashable // Identifier used in many algorithms to search by, order by, etc var key : K {get set} // A data container var value : V {get set} /// Initializer /// /// - Parameters: /// - key: Identifier used in many algorithms to search by, order by, etc. /// - value: A data container. init(key: K, value: V) /// Creates a copy /// /// - Abstract: Conformers of this class can be either value or reference types. /// Some algorithms might need to guarantee that a conformer instance gets copied. /// This will perform an innecessary in the case of value types. /// TODO: is there a better way? /// - Returns: A new instance with the old one's values copied. func copy() -> Self } /// Conformance to Equatable and Comparable protocols extension KeyValuePair { // MARK: - Equatable protocol public static func ==(lhs: Self, rhs: Self) -> Bool { return lhs.key == rhs.key } // MARK: - Comparable protocol public static func <(lhs: Self, rhs: Self) -> Bool { return lhs.key < rhs.key } public static func <=(lhs: Self, rhs: Self) -> Bool { return lhs.key <= rhs.key } public static func >=(lhs: Self, rhs: Self) -> Bool { return lhs.key >= rhs.key } public static func >(lhs: Self, rhs: Self) -> Bool { return lhs.key > rhs.key } } /// Concrete impletation of a KeyValuePair where both the key and the value /// are Integers. struct IntegerPair : KeyValuePair { // MARK - KeyValuePair protocol var key : Int var value : Int func copy() -> IntegerPair { return IntegerPair(key: self.key, value: self.value) } } ================================================ FILE: Singly Linked List/README.markdown ================================================ # Singly-Linked List #### How is this different to the Linked List implementation? The existing Linked list implementation represents the same concept. However, the existing implementation has reference semantics and does not conform to the Collection protocol implemented in the Swift's standard Library. What SinglyLinkedList aims to contribute is a more idiomatic Swift implementation, that uses value semantics and copy-on-write as well as conforms to the collection protocol. #### Conceptual representation A Singly linked list is a non-contiguous sequence of data items in memory. Each element links to the next via a memory reference. Additionally, this implementation keeps track of the last element, which can be retrived in order O(1). However, the list can only be traversed from head to tail. +--------+ +--------+ +--------+ +--------+ | | | | | | | | | node 0 |--->| node 1 |--->| node 2 |--->| node 3 |---> nil | | | | | | | | +--------+ +--------+ +--------+ +--------+ ^ ^ | | Head Tail Each element in the list is represented with an instance of SinglyLinkedListNode class, which basically contains some data and a reference of optional type to the next node, which means that the last node's next reference is `nil`. #### In-memory representation In Swift, data types can have value or reference semantics. This implementation of a singly-linked list uses value semantics. Support for copy-on-write has been added in order to improve performance and delay copying the elements of the array until strictly necessary. The image below shows how initially, after variable `l2` is assigned `l1`, a new instance of the struct SinglyLinkedList is created. Nevertheless, the indirect storage is still shared as indicated by the references that both l1 and l2 have pointing to a common area in memory. ![alt text](Images/SharedIndirectStorage.png "Two linked lists sharing the indirect storage") Once a mutating operation happens --for example on `l2` to append a new element--, then the indirect storage and all nodes in the list is actually copied and the references from `l1` and `l2` are updated. This is ilustrated in the following figure. ![alt text](Images/CopiedIndirectStorage.png "A copy is created after editing one of the lists") #### Implementation details 1. Direct access to the tail in O(1) by keeping a reference that gets updated only when an operation to the list modifies the tail. 2. Value semantics. This implementation of a singly-linked list uses a struct. When the list struct is assigned into another variable or passed as an argument to a function, a copy of the struct is made. 3. Copy-on write. Instances of SinglyLinkedList have an internal reference to an indirect storage allocated in the heap. When a copy of the list is made (according to its value semantics) the indirect storage is initialy shared between the copies. This means that a potentially large list can be accessed to read values in it without an expensive copy having to take place. However, as soon as there is a write access to the indirect storage when there are more than one instances referencing to it, a copy will be performed to guarantee value semantics. 4. Conformance to the Collection protocol. ## Performance of linked lists EDITION - *append*: Appends a new node to the end of the list. This method will modify the list's tail. If the list is empty, it will also modify the head. This operation's time complexity is *O(1)* since there's a reference to the tail node in this implementation. - *prepend*: Inserts a new node at the start of the list. If the list is empty, it will also modify the head. This operation's time complexity is *O(1)* since there's a reference to the head node. - *delete*: Finds a node in the list and deletes it. This operation's time complexity has an upper bound described by a linear function; O(n). SEARCH - find k-th to last element. Given a list with `n` number of elements and `k` being the passed parameter with `0` <= `k` <= `n`, this method has *O(k)*. ## Conforming to the Collection protocol Collections are sequences, therefore the first step is to conform to the Sequence protocol. ``` extension SinglyLinkedList: Sequence { public func makeIterator() -> SinglyLinkedListForwardIterator { return SinglyLinkedListForwardIterator(head: self.storage.head) } } ``` We have used `SinglyLinkedListForwardIterator` an iterator class to keep track of the progress while iterating the structure: ``` public struct SinglyLinkedListForwardIterator : IteratorProtocol { public typealias Element = T private(set) var head: SinglyLinkedListNode? mutating public func next() -> T? { let result = self.head?.value self.head = self.head?.next return result } } ``` Next, a collection needs to be indexable. Indexes are implemented by the data structure class. We have encapsulated this knowledge in instances of the class `SinglyLinkedListIndex`. ``` public struct SinglyLinkedListIndex: Comparable { fileprivate let node: SinglyLinkedListNode? fileprivate let tag: Int public static func==(lhs: SinglyLinkedListIndex, rhs: SinglyLinkedListIndex) -> Bool { return (lhs.tag == rhs.tag) } public static func< (lhs: SinglyLinkedListIndex, rhs: SinglyLinkedListIndex) -> Bool { return (lhs.tag < rhs.tag) } } ``` Finally, the methods in the collection to manipulate indexes are implemented below: - startIndex: Index of the first element. Can be calculated with O(1). - endIndex: Index that follows the last valid index in the collection. That is, the index that follows the tail's index. Can be calculated with O(1) if the count of elements is kept internally. However, the implementation below is O(n) with `n` being the number of elements in the list. ``` extension SinglyLinkedList : Collection { public typealias Index = SinglyLinkedListIndex public var startIndex: Index { get { return SinglyLinkedListIndex(node: self.storage.head, tag: 0) } } public var endIndex: Index { get { if let h = self.storage.head { let (_, numberOfElements) = findTail(in: h) return SinglyLinkedListIndex(node: h, tag: numberOfElements) } else { return SinglyLinkedListIndex(node: nil, tag: self.startIndex.tag) } } } public subscript(position: Index) -> T { get { return position.node!.value } } public func index(after idx: Index) -> Index { return SinglyLinkedListIndex(node: idx.node?.next, tag: idx.tag+1) } } ``` Conforming to the Collection protocol allows our class SinglyLinkedList to take adventage of all the collection methods included in the Stardard Library. *Written by Borja Arias Drake* ================================================ FILE: Singly Linked List/SinglyLinkedList.playground/Contents.swift ================================================ //: # Linked Lists // For best results, don't forget to select "Show Rendered Markup" from XCode's "Editor" menu //: Linked List Class Declaration: // last checked with Xcode 9M136h #if swift(>=4.0) print("Hello, Swift 4!") #endif //: We will start by defining a protocol that elements inserted into this implementation of a List will conform to. This is useful, because many algorithms are only interested in a key that all elements have. /// Conformers of this protocol represent a pair of comparable values /// This can be useful in many data structures and algorithms where items /// stored contain a value, but are ordered or retrieved according to a key. public protocol KeyValuePair : Comparable { associatedtype K : Comparable, Hashable associatedtype V : Comparable, Hashable // Identifier used in many algorithms to search by, order by, etc var key : K {get set} // A data container var value : V {get set} /// Initializer /// /// - Parameters: /// - key: Identifier used in many algorithms to search by, order by, etc. /// - value: A data container. init(key: K, value: V) /// Creates a copy /// /// - Abstract: Conformers of this class can be either value or reference types. /// Some algorithms might need to guarantee that a conformer instance gets copied. /// This will perform an innecessary in the case of value types. /// TODO: is there a better way? /// - Returns: A new instance with the old one's values copied. func copy() -> Self } /// Conformance to Equatable and Comparable protocols extension KeyValuePair { // MARK: - Equatable protocol public static func ==(lhs: Self, rhs: Self) -> Bool { return lhs.key == rhs.key } // MARK: - Comparable protocol public static func <(lhs: Self, rhs: Self) -> Bool { return lhs.key < rhs.key } public static func <=(lhs: Self, rhs: Self) -> Bool { return lhs.key <= rhs.key } public static func >=(lhs: Self, rhs: Self) -> Bool { return lhs.key >= rhs.key } public static func >(lhs: Self, rhs: Self) -> Bool { return lhs.key > rhs.key } } //: Concrete impletation of a KeyValuePair where both the key and the value that we'll use in the examples in this playground struct IntegerPair : KeyValuePair { // MARK - KeyValuePair protocol var key : Int var value : Int func copy() -> IntegerPair { return IntegerPair(key: self.key, value: self.value) } } //: Lists are usually used as queues. As an example, we'll define these expectations in a protocol and we'll make the the SinglyLinkedList class conform to it. /// Data structure that provides FIFO access protocol Queue { associatedtype Item /// Adds an element to the queue /// /// - Parameter item: Item to be added /// - Throws: There are cases where the operation might fail. For example if there is not enough space. mutating func enqueue(item: Item) throws /// Returns the oldest element in the queue. /// /// - Returns: The oldest element in the queue. It does not dequeue it. func getFirst() -> Item? /// Dequeues the oldest element in the queue. /// /// - Returns: The oldest element in the queue, which gets removed from it. mutating func dequeue() -> Item? } //: Next, we are going to implement a list that has value semantics. Value semantics imply that the values will be copied when assigned and passed as a parameter to functions and methods. In order to prevent unnecesasry copies, Swift uses a technique called copy-on-write; copies are only performed when a mutating operation is performed on an instance that is referenced by more than one objects. In Swift, this is ahieved with an additional level of indirection, an internal class instance, therefore with reference semantics, that will be shared, until a mutating operation occurs. /// Helper class to implement copy-on-write fileprivate class IndirectStorage { var head: SinglyLinkedListNode? var tail: SinglyLinkedListNode? init(head: SinglyLinkedListNode?, tail: SinglyLinkedListNode?) { self.head = head self.tail = tail } convenience init() { self.init(head: nil, tail: nil) } } //: Node of the list // MARK: - NODE - /// A node is the building block of a linked list. /// It can be used on its own to create linked lists. However users of this class, /// will need to manipulate references directly. public class SinglyLinkedListNode { /// Data container public var value: T /// Link to the next node public var next: SinglyLinkedListNode? /// Designated initializer /// /// - Parameter value: A value public init(value: T) { self.value = value } } //: The list with value semantics // MARK: - LINKED LIST - /// Data structure to hold a collection of items. /// Each nodes contains a reference to the next node. /// The last node does not reference any other node. /// This class implements value semantics based on copy-on-write. /// /// However, the elements contained in the list, will be shallow copied if they /// implement reference semantics. public struct SinglyLinkedList { // MARK: PROPERTIES // A level of inderiction, with reference semantics to allow easy // detection of when there are more than one references of the storage. private var storage: IndirectStorage /// Whenever there's a change that potentially can change the value, this reference to the /// storage should be used to guarantee that a new copy is created and written on. private var storageForWritting: IndirectStorage { mutating get { if !isKnownUniquelyReferenced(&self.storage) { self.storage = self.copyStorage() } return self.storage } } /// Returns the last element in the collection public var last: T? { get { return self.storage.tail?.value } } // MARK: INITIALIZERS /// Creates a list with the given node. /// NOTE: This method can break value semantics by accepting a node. /// /// - Parameter head: First node internal init(head: SinglyLinkedListNode) { self.storage = IndirectStorage() self.append(node: head) } /// Creates a list with a single element /// /// - Parameter value: element to populate the list with public init(value: T) { let node = SinglyLinkedListNode(value: value) self.init(head: node) } /// Creates an empty list public init() { self.storage = IndirectStorage() } // MARK: EDITION /// Convenience method to append a value directly to the list /// /// - Parameter value: value to be added public mutating func append(value: T) { let node = SinglyLinkedListNode(value: value) self.append(node: node) } /// Convenience method to prepend a value directly to the list /// /// - Parameter value: value to be added as the new head of the list public mutating func prepend(value: T) { let node = SinglyLinkedListNode(value: value) self.prepend(node: node) } public mutating func deleteItem(at index:Int) -> T { precondition((index >= 0) && (index < self.count)) var previous: SinglyLinkedListNode? = nil var current = self.storageForWritting.head var i = 0 var elementToDelete: SinglyLinkedListNode while (i < index) { previous = current current = current?.next i += 1 } // Current is now the element to delete (at index position.tag) elementToDelete = current! if (self.storage.head === current) { self.storageForWritting.head = current?.next } if (self.storage.tail === current) { self.storageForWritting.tail = previous } previous?.next = current?.next return elementToDelete.value } // MARK: SEARCH /// Returns the node located at the k-th to last position /// /// - Parameter kthToLast: 1 <= k <= N private func find(kthToLast: UInt, startingAt node: SinglyLinkedListNode?, count: UInt) -> SinglyLinkedListNode? { guard kthToLast <= count else { return nil } guard (node != nil) else { return nil } let i = (count - kthToLast) if (i == 0) { return node } return find(kthToLast: kthToLast, startingAt: node?.next, count: (count - 1)) } /// Returns the kth-to-last element in the list /// /// - Parameter kthToLast: Reversed ordinal number of the node to fetch. public func find(kthToLast: UInt) -> SinglyLinkedListNode? { return self.find(kthToLast: kthToLast, startingAt: self.storage.head, count: UInt(self.count)) } // MARK: LOOP DETECTION /// A singly linked list contains a loop if one node references back to a previous node. /// /// - Returns: Whether the linked list contains a loop public func containsLoop() -> Bool { /// Advances a node at a time var current = self.storage.head /// Advances twice as fast var runner = self.storage.head while (runner != nil) && (runner?.next != nil) { current = current?.next runner = runner?.next?.next if runner === current { return true } } return false } } // MARK:- Private Methods private extension SinglyLinkedList { /// Adds a new node to the current head. This method can easily break value semantics. It is left /// for internal use. /// /// - Parameter node: the node that will be the new head of the list. private mutating func prepend(node: SinglyLinkedListNode) { let (tailFromNewNode, _) = findTail(in: node) tailFromNewNode.next = self.storageForWritting.head self.storageForWritting.head = node if self.storage.tail == nil { self.storageForWritting.tail = tailFromNewNode } } /// Appends a new node to the list. This method can easily break value semantics. It is left /// for internal use. /// - Discussion: If the node to be inserted contains a loop, the node is appended but tail is set to nil. /// This is a private method, therefore this can only happen directly under the control of this class. /// - Parameter node: node to be appended. (It can be a list, even contain loops). private mutating func append(node: SinglyLinkedListNode) { if self.storage.tail != nil { // Copy on write: we are about to modify next a property in // a potentially shared node. Make sure it's new if necessary. self.storageForWritting.tail?.next = node if !self.containsLoop() { let (tail, _) = findTail(in: node) self.storageForWritting.tail = tail // There } else { self.storageForWritting.tail = nil } } else { // This also means that there's no head. // Otherwise the state would be inconsistent. // This will be checked when adding and deleting nodes. self.storageForWritting.head = node if !self.containsLoop() { let (tail, _) = findTail(in: node) self.storageForWritting.tail = tail // There } else { self.storageForWritting.tail = nil } } } /// Creates a copy of the linked list in a diffent memory location. /// /// - Returns: The copy to a new storage or a reference to the old one if no copy was necessary. private func copyStorage() -> IndirectStorage { // If the list is empty, next time an item will be created, it won't affect // other instances of the list that came from copies derived from value types. // like assignments or parameters guard (self.storage.head != nil) && (self.storage.tail != nil) else { return IndirectStorage(head: nil, tail: nil) } // Create a new position in memory. // Note that we are shallow copying the value. If it was reference type // we just make a copy of the reference. let copiedHead = SinglyLinkedListNode(value: self.storage.head!.value) var previousCopied: SinglyLinkedListNode = copiedHead // Iterate through current list of nodes and copy them. var current: SinglyLinkedListNode? = self.storage.head?.next while (current != nil) { // Create a copy let currentCopy = SinglyLinkedListNode(value: current!.value) // Create links previousCopied.next = currentCopy // Update pointers current = current?.next previousCopied = currentCopy } return IndirectStorage(head: copiedHead, tail: previousCopied) } } // MARK:- Extensions when comparable extension SinglyLinkedList where T: Comparable { /// Deletes node containing a given value /// /// - Parameter v: value of the node to be deleted. public mutating func deleteNode(withValue v: T) { guard self.storage.head != nil else { return } var previous: SinglyLinkedListNode? = nil var current = self.storage.head while (current != nil) && (current?.value != v) { previous = current current = current?.next } if let foundNode = current { if (self.storage.head === foundNode) { self.storageForWritting.head = foundNode.next } if (self.storage.tail === foundNode) { self.storage.tail = previous } previous?.next = foundNode.next foundNode.next = nil } } /// Deletes duplicates without using additional structures like a set to keep track the visited nodes. /// - Complexity: O(N^2) public mutating func deleteDuplicatesInPlace() { // Copy on write: this updates self.storage if necessary. var current = self.storageForWritting.head while (current != nil) { var previous: SinglyLinkedListNode? = current var next = current?.next while (next != nil) { if (current?.value == next?.value) { if (self.storage.head === next) { self.storage.head = next?.next } if (self.storage.tail === next) { self.storage.tail = previous } // Delete next previous?.next = next?.next } previous = next next = next?.next } current = current?.next } } } // MARK: - ITERATOR - public struct SinglyLinkedListForwardIterator : IteratorProtocol { public typealias Element = T private(set) var head: SinglyLinkedListNode? mutating public func next() -> T? { let result = self.head?.value self.head = self.head?.next return result } } // MARK: - SEQUENCE - extension SinglyLinkedList : Sequence { public func makeIterator() -> SinglyLinkedListForwardIterator { return SinglyLinkedListForwardIterator(head: self.storage.head) } } // MARK: - COLLECTION - extension SinglyLinkedList : Collection { public typealias Index = SinglyLinkedListIndex public var startIndex: Index { get { return SinglyLinkedListIndex(node: self.storage.head, tag: 0) } } public var endIndex: Index { get { if let h = self.storage.head { let (_, numberOfElements) = findTail(in: h) return SinglyLinkedListIndex(node: h, tag: numberOfElements) } else { return SinglyLinkedListIndex(node: nil, tag: self.startIndex.tag) } } } public subscript(position: Index) -> T { get { return position.node!.value } } public func index(after idx: Index) -> Index { return SinglyLinkedListIndex(node: idx.node?.next, tag: idx.tag+1) } } // MARK: - QUEUE - extension SinglyLinkedList : Queue { typealias Item = T /// Returns the oldest element in the queue. /// /// - Returns: The oldest element in the queue. It does not dequeue it. func getFirst() -> T? { return self.storage.head?.value } /// Adds an element to the queue /// /// - Parameter item: Item to be added /// - Throws: There are cases where the operation might fail. For example if there is not enough space. mutating func enqueue(item: T) throws { self.append(node: SinglyLinkedListNode(value: item)) } /// Dequeues the oldest element in the queue. /// /// - Returns: The oldest element in the queue, which gets removed from it. mutating func dequeue() -> T? { guard self.count > 0 else { return nil } return self.deleteItem(at: 0) } } // MARK: - EXPRESSIBLE-BY-ARRAY-LITERAL - extension SinglyLinkedList : ExpressibleByArrayLiteral { public typealias Element = T public init(arrayLiteral elements: Element...) { var headSet = false var current : SinglyLinkedListNode? var numberOfElements = 0 self.storage = IndirectStorage() for element in elements { numberOfElements += 1 if headSet == false { self.storage.head = SinglyLinkedListNode(value: element) current = self.storage.head headSet = true } else { let newNode = SinglyLinkedListNode(value: element) current?.next = newNode current = newNode } } self.storage.tail = current } } // MARK: - FORWARD-INDEX - public struct SinglyLinkedListIndex : Comparable { fileprivate let node: SinglyLinkedListNode? fileprivate let tag: Int public static func==(lhs: SinglyLinkedListIndex, rhs: SinglyLinkedListIndex) -> Bool { return (lhs.tag == rhs.tag) } public static func< (lhs: SinglyLinkedListIndex, rhs: SinglyLinkedListIndex) -> Bool { return (lhs.tag < rhs.tag) } } extension SinglyLinkedList where T : KeyValuePair { public func find(elementWithKey key: T.K) -> T? { let searchResults = self.filter { (keyValuePair) -> Bool in return keyValuePair.key == key } return searchResults.first } } // MARK: - HELPERS - func findTail(in node: SinglyLinkedListNode) -> (tail: SinglyLinkedListNode, count: Int) { // Assign the tail // Note that the passed node can already be linking to other nodes, // so the tail needs to be calculated. var current: SinglyLinkedListNode? = node var count = 1 while (current?.next != nil) { current = current?.next count += 1 } if current != nil { return (tail: current!, count: count) } else { return (tail: node, count: 1) } } //: EXAMPLES //: Let's create a list var l1: SinglyLinkedList = [1,2,3,4,5,6,7] //: Because it has value semantics, if we assign it, a new value will be created. However, internally the storage is shared. var l2 = l1 //: If we modify l2, l1 will remain unaffected. l2.append(value: 67) assert(l1.count == 7) assert(l1.contains(67) == false) //: However, as expected, l2 has changed assert(l2.count == 8) assert(l2.contains(67) == true) //: Notice that because our implementation conforms to the Collection protocol, we can use a lot of methods already implemented for us in Swift's standard library, for example, contains, dropLast, etc. let l3 = l2.dropLast() assert(l3.count == 7) assert(l3.contains(67) == false) ================================================ FILE: Singly Linked List/SinglyLinkedList.playground/contents.xcplayground ================================================ ================================================ FILE: Singly Linked List/SinglyLinkedList.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Singly Linked List/SinglyLinkedList.swift ================================================ import Foundation /// Helper class to implement copy-on-write fileprivate class IndirectStorage { var head: SinglyLinkedListNode? var tail: SinglyLinkedListNode? init(head: SinglyLinkedListNode?, tail: SinglyLinkedListNode?) { self.head = head self.tail = tail } convenience init() { self.init(head: nil, tail: nil) } } // MARK: - NODE - /// A node is the building block of a linked list. /// It can be used on its own to create linked lists. However users of this class, /// will need to manipulate references directly. public class SinglyLinkedListNode { /// Data container public var value: T /// Link to the next node public var next: SinglyLinkedListNode? /// Designated initializer /// /// - Parameter value: A value public init(value: T) { self.value = value } } // MARK: - LINKED LIST - /// Data structure to hold a collection of items. /// Each nodes contains a reference to the next node. /// The last node does not reference any other node. /// This class implements value semantics based on copy-on-write. /// /// However, the elements contained in the list, will be shallow copied if they /// implement reference semantics. public struct SinglyLinkedList { // MARK: PROPERTIES // A level of inderiction, with reference semantics to allow easy // detection of when there are more than one references of the storage. private var storage: IndirectStorage /// Whenever there's a change that potentially can change the value, this reference to the /// storage should be used to guarantee that a new copy is created and written on. private var storageForWritting: IndirectStorage { mutating get { if !isKnownUniquelyReferenced(&storage) { storage = copyStorage() } return storage } } /// Returns the last element in the collection public var last: T? { get { return storage.tail?.value } } // MARK: INITIALIZERS /// Creates an empty list public init() { self.storage = IndirectStorage() } // MARK: EDITION /// Convenience method to append a value directly to the list /// /// - Parameter value: value to be added public mutating func append(value: T) { let node = SinglyLinkedListNode(value: value) append(node: node) } /// Convenience method to prepend a value directly to the list /// /// - Parameter value: value to be added as the new head of the list public mutating func prepend(value: T) { let node = SinglyLinkedListNode(value: value) prepend(node: node) } public mutating func deleteItem(at index:Int) -> T { precondition((index >= 0) && (index < count)) var previous: SinglyLinkedListNode? = nil var current = storageForWritting.head var i = 0 var elementToDelete: SinglyLinkedListNode while i < index { previous = current current = current?.next i += 1 } // Current is now the element to delete (at index position.tag) elementToDelete = current! if storage.head === current { storageForWritting.head = current?.next } if storage.tail === current { storageForWritting.tail = previous } previous?.next = current?.next return elementToDelete.value } // MARK: SEARCH /// Returns the node located at the k-th to last position /// /// - Parameter kthToLast: 1 <= k <= N private func find(kthToLast: UInt, startingAt node: SinglyLinkedListNode?, count: UInt) -> SinglyLinkedListNode? { guard kthToLast <= count else { return nil } guard (node != nil) else { return nil } let i = (count - kthToLast) if i == 0 { return node } return find(kthToLast: kthToLast, startingAt: node?.next, count: (count - 1)) } /// Returns the kth-to-last element in the list /// /// - Parameter kthToLast: Reversed ordinal number of the node to fetch. public func find(kthToLast: UInt) -> SinglyLinkedListNode? { return find(kthToLast: kthToLast, startingAt: storage.head, count: UInt(count)) } } // MARK:- Private Methods private extension SinglyLinkedList { /// Adds a new node to the current head. This method can easily break value semantics. It is left /// for internal use. /// /// - Parameter node: the node that will be the new head of the list. private mutating func prepend(node: SinglyLinkedListNode) { let (tailFromNewNode, _) = findTail(in: node) tailFromNewNode.next = storageForWritting.head storageForWritting.head = node if storage.tail == nil { storageForWritting.tail = tailFromNewNode } } /// Appends a new node to the list. This method can easily break value semantics. It is left /// for internal use. /// - Discussion: If the node to be inserted contains a loop, the node is appended but tail is set to nil. /// This is a private method, therefore this can only happen directly under the control of this class. /// - Parameter node: node to be appended. (It can be a list, even contain loops). private mutating func append(node: SinglyLinkedListNode) { if storage.tail != nil { // Copy on write: we are about to modify next a property in // a potentially shared node. Make sure it's new if necessary. storageForWritting.tail?.next = node let (tail, _) = findTail(in: node) storageForWritting.tail = tail // There } else { // This also means that there's no head. // Otherwise the state would be inconsistent. // This will be checked when adding and deleting nodes. storageForWritting.head = node let (tail, _) = findTail(in: node) storageForWritting.tail = tail // There } } /// Creates a copy of the linked list in a diffent memory location. /// /// - Returns: The copy to a new storage or a reference to the old one if no copy was necessary. private func copyStorage() -> IndirectStorage { // If the list is empty, next time an item will be created, it won't affect // other instances of the list that came from copies derived from value types. // like assignments or parameters guard (storage.head != nil) && (storage.tail != nil) else { return IndirectStorage(head: nil, tail: nil) } // Create a new position in memory. // Note that we are shallow copying the value. If it was reference type // we just make a copy of the reference. let copiedHead = SinglyLinkedListNode(value: storage.head!.value) var previousCopied: SinglyLinkedListNode = copiedHead // Iterate through current list of nodes and copy them. var current: SinglyLinkedListNode? = storage.head?.next while current != nil { // Create a copy let currentCopy = SinglyLinkedListNode(value: current!.value) // Create links previousCopied.next = currentCopy // Update pointers current = current?.next previousCopied = currentCopy } return IndirectStorage(head: copiedHead, tail: previousCopied) } } // MARK:- Extensions when comparable extension SinglyLinkedList where T: Comparable { /// Deletes node containing a given value /// /// - Parameter v: value of the node to be deleted. public mutating func deleteNode(withValue v: T) { guard storage.head != nil else { return } var previous: SinglyLinkedListNode? = nil var current = storage.head while (current != nil) && (current?.value != v) { previous = current current = current?.next } if let foundNode = current { if storage.head === foundNode { storageForWritting.head = foundNode.next } if storage.tail === foundNode { storage.tail = previous } previous?.next = foundNode.next foundNode.next = nil } } /// Deletes duplicates without using additional structures like a set to keep track the visited nodes. /// - Complexity: O(N^2) public mutating func deleteDuplicatesInPlace() { // Copy on write: this updates storage if necessary. var current = storageForWritting.head while current != nil { var previous: SinglyLinkedListNode? = current var next = current?.next while next != nil { if current?.value == next?.value { if storage.head === next { storage.head = next?.next } if storage.tail === next { storage.tail = previous } // Delete next previous?.next = next?.next } previous = next next = next?.next } current = current?.next } } } // MARK: - COLLECTION - extension SinglyLinkedList : Collection { public typealias Index = SinglyLinkedListIndex public var startIndex: Index { get { return SinglyLinkedListIndex(node: storage.head, tag: 0) } } public var endIndex: Index { get { if let h = storage.head { let (_, numberOfElements) = findTail(in: h) return SinglyLinkedListIndex(node: h, tag: numberOfElements) } else { return SinglyLinkedListIndex(node: nil, tag: startIndex.tag) } } } public subscript(position: Index) -> T { get { return position.node!.value } } public func index(after idx: Index) -> Index { return SinglyLinkedListIndex(node: idx.node?.next, tag: idx.tag+1) } } // MARK: - EXPRESSIBLE-BY-ARRAY-LITERAL - extension SinglyLinkedList : ExpressibleByArrayLiteral { public typealias Element = T public init(arrayLiteral elements: Element...) { var headSet = false var current : SinglyLinkedListNode? var numberOfElements = 0 storage = IndirectStorage() for element in elements { numberOfElements += 1 if headSet == false { storage.head = SinglyLinkedListNode(value: element) current = storage.head headSet = true } else { let newNode = SinglyLinkedListNode(value: element) current?.next = newNode current = newNode } } storage.tail = current } } // MARK: - FORWARD-INDEX - public struct SinglyLinkedListIndex : Comparable { fileprivate let node: SinglyLinkedListNode? fileprivate let tag: Int public static func==(lhs: SinglyLinkedListIndex, rhs: SinglyLinkedListIndex) -> Bool { return (lhs.tag == rhs.tag) } public static func< (lhs: SinglyLinkedListIndex, rhs: SinglyLinkedListIndex) -> Bool { return (lhs.tag < rhs.tag) } } extension SinglyLinkedList where T : KeyValuePair { public func find(elementWithKey key: T.K) -> T? { let searchResults = filter { (keyValuePair) -> Bool in return keyValuePair.key == key } return searchResults.first } } // MARK: - HELPERS - func findTail(in node: SinglyLinkedListNode) -> (tail: SinglyLinkedListNode, count: Int) { // Assign the tail // Note that the passed node can already be linking to other nodes, // so the tail needs to be calculated. var current: SinglyLinkedListNode? = node var count = 1 while current?.next != nil { current = current?.next count += 1 } if current != nil { return (tail: current!, count: count) } else { return (tail: node, count: 1) } } ================================================ FILE: Singly Linked List/Tests/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Singly Linked List/Tests/Tests/SinglyLinkedListTests.swift ================================================ import XCTest class FindTailInNodeTests: XCTestCase { func testExample() { let n1 = SinglyLinkedListNode(value: 34) let n2 = SinglyLinkedListNode(value: 35) let n3 = SinglyLinkedListNode(value: 36) let n4 = SinglyLinkedListNode(value: 37) n1.next = n2 n2.next = n3 n3.next = n4 XCTAssertTrue(findTail(in: n1).tail === n4) XCTAssertTrue(findTail(in: n2).tail === n4) XCTAssertTrue(findTail(in: n4).tail === n4) XCTAssertTrue(findTail(in: n4).tail === n4) } } class SinglyLinkedListTests: XCTestCase { func testAppendOneNodeFromEmptyList() { var list = SinglyLinkedList() list.append(value: 34) XCTAssertTrue(list.first == 34) XCTAssertTrue(list.count == 1, "Found \(list.count)") } func testAppendMultipleNodesFromEmptyList() { var list = SinglyLinkedList() list.append(value: 34) list.append(value: 35) list.append(value: 36) list.append(value: 34) XCTAssertTrue(list.first == 34) let second = list.index(list.startIndex, offsetBy: 1) let third = list.index(list.startIndex, offsetBy: 2) let fouth = list.index(list.startIndex, offsetBy: 3) XCTAssertTrue(list[second] == 35) XCTAssertTrue(list[third] == 36) XCTAssertTrue(list[fouth] == 34) XCTAssertTrue(list.count == 4, "Found \(list.count)") } func testDelete() { var list: SinglyLinkedList = [1] list.append(value: 2) list.append(value: 3) list.append(value: 4) list.append(value: 5) list.deleteNode(withValue: 1) var second = list.index(list.startIndex, offsetBy: 1) var third = list.index(list.startIndex, offsetBy: 2) XCTAssertTrue(list.first == 2) XCTAssertTrue(list[second] == 3) XCTAssertTrue(list[third] == 4) XCTAssertTrue(list.last == 5) XCTAssertTrue(list.count == 4) list.deleteNode(withValue: 5) second = list.index(list.startIndex, offsetBy: 1) third = list.index(list.startIndex, offsetBy: 2) XCTAssertTrue(list.first == 2) XCTAssertTrue(list[second] == 3) XCTAssertTrue(list.last == 4) XCTAssertTrue(list.count == 3) list.deleteNode(withValue: 3) XCTAssertTrue(list.first == 2) XCTAssertTrue(list.last == 4) XCTAssertTrue(list.count == 2) list.deleteNode(withValue: 2) XCTAssertTrue(list.first == 4) XCTAssertTrue(list.last == 4) XCTAssertTrue(list.count == 1) list.deleteNode(withValue: 4) XCTAssertTrue(list.first == nil) XCTAssertTrue(list.last == nil) XCTAssertTrue(list.count == 0) } func testDeleteDuplicatesInPlace() { var list: SinglyLinkedList = [1] list.append(value: 2) list.append(value: 2) list.append(value: 3) list.append(value: 5) list.append(value: 2) list.append(value: 4) list.append(value: 2) list.append(value: 5) list.deleteDuplicatesInPlace() let second = list.index(list.startIndex, offsetBy: 1) let third = list.index(list.startIndex, offsetBy: 2) let fourth = list.index(list.startIndex, offsetBy: 3) XCTAssertTrue(list.first == 1) XCTAssertTrue(list[second] == 2) XCTAssertTrue(list[third] == 3) XCTAssertTrue(list[fourth] == 5) XCTAssertTrue(list.last == 4) XCTAssertTrue(list.count == 5) } func testFindKthToLast() { let list: SinglyLinkedList = [2,2,3,5,2,4,2,5] XCTAssertTrue(list.find(kthToLast: 1)?.value == 5) XCTAssertTrue(list.find(kthToLast: 2)?.value == 2) XCTAssertTrue(list.find(kthToLast: 3)?.value == 4) XCTAssertTrue(list.find(kthToLast: 4)?.value == 2) XCTAssertTrue(list.find(kthToLast: 5)?.value == 5) XCTAssertTrue(list.find(kthToLast: 6)?.value == 3) XCTAssertTrue(list.find(kthToLast: 7)?.value == 2) XCTAssertTrue(list.find(kthToLast: 8)?.value == 2) XCTAssertTrue(list.find(kthToLast: 9)?.value == nil) } func testConstructorFromArrayLiteralWhenEmpty() { let list: SinglyLinkedList = [] XCTAssertTrue(list.first == nil) XCTAssertTrue(list.last == nil) XCTAssertTrue(list.count == 0, "Found \(list.count)") } func testConstructorFromArrayLiteralWithSingleElement() { let list: SinglyLinkedList = [5] XCTAssertTrue(list.first == 5) XCTAssertTrue(list.last == 5) XCTAssertTrue(list.count == 1, "Found \(list.count)") } func testAppendValue() { var list = SinglyLinkedList() list.append(value: 1) list.append(value: 1) list.append(value: 2) list.append(value: 2) list.append(value: 4) let result = string(from: list) XCTAssertTrue(result == "11224", "Found \(result)") XCTAssertTrue(list.count == 5, "Found \(list.count)") XCTAssertTrue(list.last == 4, "Found \(String(describing: list.last))") } func testPrependValue() { var list = SinglyLinkedList() list.prepend(value: 1) list.prepend(value: 2) list.prepend(value: 3) list.prepend(value: 4) list.prepend(value: 5) list.prepend(value: 6) let result = string(from: list) XCTAssertTrue(result == "654321", "Found \(result)") XCTAssertTrue(list.count == 6, "Found \(list.count)") XCTAssertTrue(list.last == 1, "Found \(String(describing: list.last))") } func testDeleteHeadInListWithMultipleItems() { var list: SinglyLinkedList = [1,2,3,4,5,6,7,8] let _ = list.deleteItem(at: 0) let result = string(from: list) XCTAssertTrue(result == "2345678", "Found \(result)") XCTAssertTrue(list.first == 2, "Found \(String(describing: list.first))") XCTAssertTrue(list.count == 7, "Found \(list.count)") } func testDeleteTailInListWithMultipleItems() { var list: SinglyLinkedList = [1,2,3,4,5,6,7,8] let _ = list.deleteItem(at: 7) let result = string(from: list) XCTAssertTrue(result == "1234567", "Found \(result)") XCTAssertTrue(list.last == 7, "Found \(String(describing: list.last))") XCTAssertTrue(list.count == 7, "Found \(list.count)") } func testDeleteItemInListWithMultipleItems() { var list: SinglyLinkedList = [1,2,3,4,5,6,7,8] let _ = list.deleteItem(at: 4) let result = string(from: list) XCTAssertTrue(result == "1234678", "Found \(result)") XCTAssertTrue(list.first == 1, "Found \(String(describing: list.first))") XCTAssertTrue(list.last == 8, "Found \(String(describing: list.last))") XCTAssertTrue(list.count == 7, "Found \(list.count)") } func testDeleteHeadInListWithSingleElement() { var list: SinglyLinkedList = [1] let _ = list.deleteItem(at: 0) let result = string(from: list) XCTAssertTrue(result == "", "Found \(result)") XCTAssertTrue(list.first == nil, "Found \(String(describing: list.first))") XCTAssertTrue(list.last == nil, "Found \(String(describing: list.last))") XCTAssertTrue(list.count == 0, "Found \(list.count)") } func testDirectIndexAccess() { let list: SinglyLinkedList = [1,2,3,4,5,6,7,8] let fifthElementIndex = list.index(list.startIndex, offsetBy: 5) XCTAssertTrue(list[fifthElementIndex] == 6 , "Found \(list.count)") } func string(from list: SinglyLinkedList) -> String { var result = "" var iterator = list.makeIterator() while let current = iterator.next() { result += String(describing: current) } return result } func testCopyOnWriteUsingLiterals() { var l1: SinglyLinkedList = [1,2,3,4,5,6,7,8] l1.append(value: 0) var l2 = l1 _ = l2.deleteItem(at: 3) XCTAssertTrue(l1.count == 9) XCTAssertTrue(l2.count == 8) _ = l1.deleteItem(at: 0) _ = l1.deleteItem(at: 0) _ = l1.deleteItem(at: 0) _ = l1.deleteItem(at: 0) _ = l1.deleteItem(at: 0) _ = l1.deleteItem(at: 0) _ = l1.deleteItem(at: 0) _ = l1.deleteItem(at: 0) _ = l1.deleteItem(at: 0) XCTAssertTrue(l1.count == 0) XCTAssertTrue(l2.count == 8) } } ================================================ FILE: Singly Linked List/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 006104711F361359007A6F50 /* SinglyLinkedListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 006104701F361359007A6F50 /* SinglyLinkedListTests.swift */; }; 006104791F36144E007A6F50 /* KeyValuePair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 006104761F36144E007A6F50 /* KeyValuePair.swift */; }; 0061047B1F36144E007A6F50 /* SinglyLinkedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 006104781F36144E007A6F50 /* SinglyLinkedList.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 0061046D1F361359007A6F50 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 006104701F361359007A6F50 /* SinglyLinkedListTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SinglyLinkedListTests.swift; sourceTree = ""; }; 006104721F361359007A6F50 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 006104761F36144E007A6F50 /* KeyValuePair.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = KeyValuePair.swift; path = ../../KeyValuePair.swift; sourceTree = ""; }; 006104781F36144E007A6F50 /* SinglyLinkedList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SinglyLinkedList.swift; path = ../../SinglyLinkedList.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 0061046A1F361359007A6F50 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 006104621F36104C007A6F50 = { isa = PBXGroup; children = ( 0061046F1F361359007A6F50 /* Tests */, 0061046E1F361359007A6F50 /* Products */, ); sourceTree = ""; }; 0061046E1F361359007A6F50 /* Products */ = { isa = PBXGroup; children = ( 0061046D1F361359007A6F50 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 0061046F1F361359007A6F50 /* Tests */ = { isa = PBXGroup; children = ( 006104701F361359007A6F50 /* SinglyLinkedListTests.swift */, 006104761F36144E007A6F50 /* KeyValuePair.swift */, 006104781F36144E007A6F50 /* SinglyLinkedList.swift */, 006104721F361359007A6F50 /* Info.plist */, ); path = Tests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 0061046C1F361359007A6F50 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 006104731F361359007A6F50 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 006104691F361359007A6F50 /* Sources */, 0061046A1F361359007A6F50 /* Frameworks */, 0061046B1F361359007A6F50 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = 0061046D1F361359007A6F50 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 006104631F36104C007A6F50 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; LastUpgradeCheck = 0830; TargetAttributes = { 0061046C1F361359007A6F50 = { CreatedOnToolsVersion = 8.3.3; LastSwiftMigration = 0900; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 006104661F36104C007A6F50 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 006104621F36104C007A6F50; productRefGroup = 0061046E1F361359007A6F50 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 0061046C1F361359007A6F50 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 0061046B1F361359007A6F50 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 006104691F361359007A6F50 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 006104711F361359007A6F50 /* SinglyLinkedListTests.swift in Sources */, 0061047B1F36144E007A6F50 /* SinglyLinkedList.swift in Sources */, 006104791F36144E007A6F50 /* KeyValuePair.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 006104671F36104C007A6F50 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Debug; }; 006104681F36104C007A6F50 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Release; }; 006104741F361359007A6F50 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.0; }; name = Debug; }; 006104751F361359007A6F50 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Tests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 006104661F36104C007A6F50 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 006104671F36104C007A6F50 /* Debug */, 006104681F36104C007A6F50 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 006104731F361359007A6F50 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 006104741F361359007A6F50 /* Debug */, 006104751F361359007A6F50 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 006104631F36104C007A6F50 /* Project object */; } ================================================ FILE: Singly Linked List/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Singly Linked List/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Skip-List/README.md ================================================ # Skip List Skip List is a probablistic data-structure with same logarithmic time bound and efficiency as AVL/ or Red-Black tree and provides a clever compromise to efficiently support search and update operations and is relatively simpler to implement compared to other map data structures. A skip list *S* consists of series of sorted linked lists *{L0, ..., Ln}*, layered hierarchicaly and each layer *L* stores a subset of items in layer *L0* in incremental order. The items in layers *{L1, ... Ln}* are chosen at random based on a coin flipping function with probability 1/2 . For traversing, every item in a layer hold references to the node below and the next node. This layers serve as express lanes to the layer underneath them, effectively making fast O(log n) searching possible by skipping lanes and reducing travel distance and in worse case searching degrades to O (n), as expected with regular linked list. For a skip list *S*: 1. List *L0* contains every inserted item. 2. For lists *{L1, ..., Ln}*, *Li* contains a randomly generated subset of the items in *Li-1* 3. Height is determined by coin-flipping. ![Schematic view](Images/Intro.png) Figure 1 #Searching Searching for element *N* starts by traversing from top most layer *Ln* until *L0*. Our objective is to find an element *K* such that its value at the rightmost position of current layer, is less-than target item and its subsequent node has a greater-equal value or nil ( *K.key < N.key <= (K.next.key or nil)* ). if value of *K.next* is equal to *N*, search is terminated and we return *K.next*, otherwise drop underneath using *K.down* to the node below ( at layer Ln-1 ) and repeat the process until *L0* where *K.down* is `nil` which indicates that level is *L0* and item doesn't exists. ###Example: ![Inserting first element](Images/Search1.png) #Inserting Inserting element *N* has a similar process as searching. It starts by traversing from top most layer *Ln* until *L0*. We need to keep track of our traversal path using a stack. It helps us to traverse the path upward when coin-flipping starts, so we can insert our new element and update references to it. Our objective is to find a element *K* such that its value at the rightmost position of layer *Ln*, is less-than new item and its subsequent node has a greater-equal value or nil ( *K.key < N.key < (K.next.key or nil)* ). Push element *K* to the stack and with element *K*, go down using *K.down* to the node below ( at layer Ln-1 ) and repeat the process ( forward searching ) up until *L0* where *K.down* is `nil` which indicates that level is *L0*. We terminate the process when *K.down* is nil. At *L0*, *N* can be inserted after *K*. Here is the interesting part. We use coin flipping function to randomly create layers. When coin flip function returns 0, the whole process is finished but when returns 1, there are two possibilities: 1. Stack is empty ( Level is *L0* /- *Ln* or at uninitialized stage) 2. Stack has items ( traversing upward is possible ) In case 1: A new layer M* is created with a head node *NM* referencing head node of layer below and *NM.next* referencing new element *N*. New element *N* referecing element *N* at previous layer. In case 2: repeat until stack is empty Pop an item *F* from stack and update the references accordingly. *F.next* will be *K.next* and *K.next* will be *F* when stack is empty Create a new layer consisintg of a head node *NM* referencing head node of layer below and *NM.next* referencing new element *N*. New element *N* referencing element *N* at previous layer. ###Example: Inserting 13. with coin flips (0) ![Inserting first element](Images/Insert5.png) ![Inserting first element](Images/Insert6.png) ![Inserting first element](Images/insert7.png) ![Inserting first element](Images/Insert8.png) ![Inserting first element](Images/Insert9.png) Inserting 20. with 4 times coin flips (1) ![Inserting first element](Images/Insert9.png) ![Inserting first element](Images/Insert10.png) ![Inserting first element](Images/Insert11.png) ![Inserting first element](Images/Insert12.png) #Removing Removing works similar to insert procedure. TODO #See also [Skip List on Wikipedia](https://en.wikipedia.org/wiki/Skip_list) Written for Swift Algorithm Club by [Mike Taghavi](https://github.com/mitghi) ================================================ FILE: Skip-List/SkipList.playground/Contents.swift ================================================ // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif // SkipList is ready for Swift 4. // TODO: Add Test let k = SkipList() k.insert(key: 10, data: "10") k.insert(key: 12, data: "12") k.insert(key: 13, data: "13") k.insert(key: 20, data: "20") k.insert(key: 24, data: "24") if let value = k.get(key: 20) { print(value) } else { print("not found!") } ================================================ FILE: Skip-List/SkipList.playground/Sources/SkipList.swift ================================================ // The MIT License (MIT) // Copyright (c) 2016 Mike Taghavi (mitghi[at]me.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. import Foundation // Stack from : https://github.com/raywenderlich/swift-algorithm-club/tree/master/Stack public struct Stack { fileprivate var array: [T] = [] public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func push(_ element: T) { array.append(element) } public mutating func pop() -> T? { return array.popLast() } public func peek() -> T? { return array.last } } extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self return AnyIterator { curr.pop() } } } private func coinFlip() -> Bool { return arc4random_uniform(2) == 1 } public class DataNode { public typealias Node = DataNode var data: Payload? fileprivate var key: Key? var next: Node? var down: Node? public init(key: Key, data: Payload) { self.key = key self.data = data } public init(asHead head: Bool) {} } open class SkipList { public typealias Node = DataNode fileprivate(set) var head: Node? public init() {} } // MARK: - Search lanes for a node with a given key extension SkipList { func findNode(key: Key) -> Node? { var currentNode: Node? = head var isFound: Bool = false while !isFound { if let node = currentNode { switch node.next { case .none: currentNode = node.down case .some(let value) where value.key != nil: if value.key == key { isFound = true break } else { if key < value.key! { currentNode = node.down } else { currentNode = node.next } } default: continue } } else { break } } if isFound { return currentNode } else { return nil } } func search(key: Key) -> Payload? { guard let node = findNode(key: key) else { return nil } return node.next!.data } } // MARK: - Insert a node into lanes depending on skip list status ( bootstrap base-layer if head is empty / start insertion from current head ). extension SkipList { private func bootstrapBaseLayer(key: Key, data: Payload) { head = Node(asHead: true) var node = Node(key: key, data: data) head!.next = node var currentTopNode = node while coinFlip() { let newHead = Node(asHead: true) node = Node(key: key, data: data) node.down = currentTopNode newHead.next = node newHead.down = head head = newHead currentTopNode = node } } private func insertItem(key: Key, data: Payload) { var stack = Stack() var currentNode: Node? = head while currentNode != nil { if let nextNode = currentNode!.next { if nextNode.key! > key { stack.push(currentNode!) currentNode = currentNode!.down } else { currentNode = nextNode } } else { stack.push(currentNode!) currentNode = currentNode!.down } } let itemAtLayer = stack.pop() var node = Node(key: key, data: data) node.next = itemAtLayer!.next itemAtLayer!.next = node var currentTopNode = node while coinFlip() { if stack.isEmpty { let newHead = Node(asHead: true) node = Node(key: key, data: data) node.down = currentTopNode newHead.next = node newHead.down = head head = newHead currentTopNode = node } else { let nextNode = stack.pop() node = Node(key: key, data: data) node.down = currentTopNode node.next = nextNode!.next nextNode!.next = node currentTopNode = node } } } public func insert(key: Key, data: Payload) { if head != nil { if let node = findNode(key: key) { // replace, in case of key already exists. var currentNode = node.next while currentNode != nil && currentNode!.key == key { currentNode!.data = data currentNode = currentNode!.down } } else { insertItem(key: key, data: data) } } else { bootstrapBaseLayer(key: key, data: data) } } } // MARK: - Remove a node with a given key. First, find its position in layers at the top, then remove it from each lane by traversing down to the base layer. extension SkipList { public func remove(key: Key) { guard let item = findNode(key: key) else { return } var currentNode = Optional(item) while currentNode != nil { let node = currentNode!.next if node!.key != key { currentNode = node continue } let nextNode = node!.next currentNode!.next = nextNode currentNode = currentNode!.down } } } // MARK: - Get associated payload from a node with a given key. extension SkipList { public func get(key: Key) -> Payload? { return search(key: key) } } ================================================ FILE: Skip-List/SkipList.playground/contents.xcplayground ================================================ ================================================ FILE: Skip-List/SkipList.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Skip-List/SkipList.swift ================================================ // The MIT License (MIT) // Copyright (c) 2016 Mike Taghavi (mitghi[at]me.com) // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. import Foundation // Stack from : https://github.com/raywenderlich/swift-algorithm-club/tree/master/Stack public struct Stack { fileprivate var array: [T] = [] public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func push(_ element: T) { array.append(element) } public mutating func pop() -> T? { return array.popLast() } public func peek() -> T? { return array.last } } extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self return AnyIterator { curr.pop() } } } private func coinFlip() -> Bool { return arc4random_uniform(2) == 1 } public class DataNode { public typealias Node = DataNode var data: Payload? fileprivate var key: Key? var next: Node? var down: Node? public init(key: Key, data: Payload) { self.key = key self.data = data } public init(asHead head: Bool) {} } open class SkipList { public typealias Node = DataNode fileprivate(set) var head: Node? public init() {} } // MARK: - Search lanes for a node with a given key extension SkipList { func findNode(key: Key) -> Node? { var currentNode: Node? = head var isFound: Bool = false while !isFound { if let node = currentNode { switch node.next { case .none: currentNode = node.down case .some(let value) where value.key != nil: if value.key == key { isFound = true break } else { if key < value.key! { currentNode = node.down } else { currentNode = node.next } } default: continue } } else { break } } if isFound { return currentNode } else { return nil } } func search(key: Key) -> Payload? { guard let node = findNode(key: key) else { return nil } return node.next!.data } } // MARK: - Insert a node into lanes depending on skip list status ( bootstrap base-layer if head is empty / start insertion from current head ). extension SkipList { private func bootstrapBaseLayer(key: Key, data: Payload) { head = Node(asHead: true) var node = Node(key: key, data: data) head!.next = node var currentTopNode = node while coinFlip() { let newHead = Node(asHead: true) node = Node(key: key, data: data) node.down = currentTopNode newHead.next = node newHead.down = head head = newHead currentTopNode = node } } private func insertItem(key: Key, data: Payload) { var stack = Stack() var currentNode: Node? = head while currentNode != nil { if let nextNode = currentNode!.next { if nextNode.key! > key { stack.push(currentNode!) currentNode = currentNode!.down } else { currentNode = nextNode } } else { stack.push(currentNode!) currentNode = currentNode!.down } } let itemAtLayer = stack.pop() var node = Node(key: key, data: data) node.next = itemAtLayer!.next itemAtLayer!.next = node var currentTopNode = node while coinFlip() { if stack.isEmpty { let newHead = Node(asHead: true) node = Node(key: key, data: data) node.down = currentTopNode newHead.next = node newHead.down = head head = newHead currentTopNode = node } else { let nextNode = stack.pop() node = Node(key: key, data: data) node.down = currentTopNode node.next = nextNode!.next nextNode!.next = node currentTopNode = node } } } public func insert(key: Key, data: Payload) { if head != nil { if let node = findNode(key: key) { // replace, in case of key already exists. var currentNode = node.next while currentNode != nil && currentNode!.key == key { currentNode!.data = data currentNode = currentNode!.down } } else { insertItem(key: key, data: data) } } else { bootstrapBaseLayer(key: key, data: data) } } } // MARK: - Remove a node with a given key. First, find its position in layers at the top, then remove it from each lane by traversing down to the base layer. extension SkipList { public func remove(key: Key) { guard let item = findNode(key: key) else { return } var currentNode = Optional(item) while currentNode != nil { let node = currentNode!.next if node!.key != key { currentNode = node continue } let nextNode = node!.next currentNode!.next = nextNode currentNode = currentNode!.down } } } // MARK: - Get associated payload from a node with a given key. extension SkipList { public func get(key: Key) -> Payload? { return search(key: key) } } ================================================ FILE: Slow Sort/README.markdown ================================================ # Slow Sort Goal: Sort an array of numbers from low to high (or high to low). You are given an array of numbers and need to put them in the right order. The insertion sort algorithm works as follows: We can decompose the problem of sorting n numbers in ascending order into 1. find the maximum of the numbers 1. find the maximum of the first n/2 elements 2. find the maximum of the remaining n/2 elements 3. find the largest of those two maxima 2. sorting the remaining ones ## The code Here is an implementation of slow sort in Swift: ```swift func slowSort(_ i: Int, _ j: Int, _ numberList: inout [Int]) { guard if i < j else { return } let m = (i+j)/2 slowSort(i, m, &numberList) slowSort(m+1, j, &numberList) if numberList[j] < numberList[m] { let temp = numberList[j] numberList[j] = numberList[m] numberList[m] = temp } slowSort(i, j-1, &numberList) } ``` ## Performance | Case | Performance | |:-------------: |:---------------:| | Worst | slow | | Best | O(n^(log(n)/(2+e)))) | | Average | O(n^(log(n)/2)) | ## See also [Slow Sort explanation in the Internet](http://c2.com/cgi/wiki?SlowSort) *Written for Swift Algorithm Club by Lukas Schramm* (used the Insertion Sort Readme as template) ================================================ FILE: Slow Sort/SlowSort.playground/Contents.swift ================================================ var numberList = [1, 12, 9, 17, 13, 12] slowSort(0, numberList.count-1, &numberList) print(numberList) ================================================ FILE: Slow Sort/SlowSort.playground/Sources/SlowSort.swift ================================================ import Foundation public func slowSort(_ i: Int, _ j: Int, _ numberList: inout [Int]) { guard i < j else { return } let m = (i+j)/2 slowSort(i, m, &numberList) slowSort(m+1, j, &numberList) if numberList[j] < numberList[m] { let temp = numberList[j] numberList[j] = numberList[m] numberList[m] = temp } slowSort(i, j-1, &numberList) } ================================================ FILE: Slow Sort/SlowSort.playground/contents.xcplayground ================================================ ================================================ FILE: Slow Sort/SlowSort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Slow Sort/SlowSort.swift ================================================ // // SlowSort.swift // // // Created by Pope Lukas Schramm (Dabendorf Orthodox Religion) on 16-07-16. // // func slowSort(_ i: Int, _ j: Int, _ numberList: inout [Int]) { guard if i < j else { return } let m = (i+j)/2 slowSort(i, m, &numberList) slowSort(m+1, j, &numberList) if numberList[j] < numberList[m] { let temp = numberList[j] numberList[j] = numberList[m] numberList[m] = temp } slowSort(i, j-1, &numberList) } ================================================ FILE: Sorted Set/README.markdown ================================================ # Sorted Set ## Sorted Array Version An Sorted Set is a collection of unique items in sorted order. Items are usually sorted from least to greatest. The Sorted Set data type is a hybrid of: - a [Set](https://en.wikipedia.org/wiki/Set_%28mathematics%29), a collection of unique items where the order does not matter, and - a [Sequence](https://en.wikipedia.org/wiki/Sequence), an sorted list of items where each item may appear more than once. It's important to keep in mind that two items can have the same *value* but still may not be equal. For example, we could define "a" and "z" to have the same value (their lengths), but clearly "a" != "z". ## Why use an sorted set? Sorted Sets should be considered when you need to keep your collection sorted at all times, and you do lookups on the collection much more frequently than inserting or deleting items. Many of the lookup operations for an Sorted Set are **O(1)**. A good example would be keeping track of the rankings of players in a scoreboard (see example 2 below). #### These are sorted sets A set of integers: [1, 2, 3, 6, 8, 10, 1000] A set of strings: ["a", "is", "set", "this"] The "value" of these strings could be their text content, but also for example their length. #### These are not sorted sets This set violates the property of uniqueness: [1, 1, 2, 3, 5, 8] This set violates the sorted property: [1, 11, 2, 3] ## The code We'll start by creating our internal representation for the Sorted Set. Since the idea of a set is similar to that of an array, we will use an array to represent our set. Furthermore, since we'll need to keep the set sorted, we need to be able to compare the individual elements. Thus, any type must conform to the [Comparable Protocol](https://developer.apple.com/library/watchos/documentation/Swift/Reference/Swift_Comparable_Protocol/index.html). ```swift public struct SortedSet { private var internalSet = [T]() // Returns the number of elements in the SortedSet. public var count: Int { return internalSet.count } ... ``` Lets take a look at the `insert()` function first. This first checks if the item already exists in the collection. If so, it returns and does not insert the item. Otherwise, it will insert the item through straightforward iteration. ```swift public mutating func insert(_ item: T){ if exists(item) { return // don't add an item if it already exists } // Insert new the item just before the one that is larger. for i in 0.. item { internalSet.insert(item, at: i) return } } // Append to the back if the new item is greater than any other in the set. internalSet.append(item) } ``` As we'll see later on, checking if the item is already in the set has an efficiency of **O(log(n) + k)** where **k** is the number of items with the same value as the item we are inserting. To insert the new item, the `for` loop starts from the beginning of the array, and checks to see if each item is larger than the item we want to insert. Once we find such an item, we insert the new one into its place. This shifts the rest of the array over to the right by 1 position. This loop is at worst **O(n)**. The total performance of the `insert()` function is therefore **O(n)**. Next up is the `remove()` function: ```swift public mutating func remove(_ item: T) { if let index = index(of: item) { internalSet.remove(at: index) } } ``` First this checks if the item exists and then removes it from the array. Because of the `removeAtIndex()` function, the efficiency for remove is **O(n)**. The next function is `indexOf()`, which takes in an object of type `T` and returns the index of the corresponding item if it is in the set, or `nil` if it is not. Since our set is sorted, we can use a binary search to quickly search for the item. ```swift public func index(of item: T) -> Int? { var leftBound = 0 var rightBound = count - 1 while leftBound <= rightBound { let mid = leftBound + ((rightBound - leftBound) / 2) if internalSet[mid] > item { rightBound = mid - 1 } else if internalSet[mid] < item { leftBound = mid + 1 } else if internalSet[mid] == item { return mid } else { // see below } } return nil } ``` > **Note:** If you are not familiar with the concept of binary search, we have an [article that explains all about it](../Binary%20Search). However, there is an important issue to deal with here. Recall that two objects can be unequal yet still have the same "value" for the purposes of comparing them. Since a set can contain multiple items with the same value, it is important to check that the binary search has landed on the correct item. For example, consider this sorted set of `Player` objects. Each `Player` has a name and a number of points: [ ("Bill", 50), ("Ada", 50), ("Jony", 50), ("Steve", 200), ("Jean-Louis", 500), ("Woz", 1000) ] We want the set to be sorted by points, from low to high. Multiple players can have the same number of points. The name of the player is not important for this ordering. However, the name *is* important for retrieving the correct item. Let's say we do `indexOf(bill)` where `bill` is player object `("Bill", 50)`. If we did a traditional binary search we'd land on index 2, which is the object `("Jony", 50)`. The value 50 matches, but it's not the object we're looking for! Therefore, we also need to check the items with the same value to the right and left of the midpoint. The code to check the left and right side looks like this: ```swift // Check to the right. for j in mid.stride(to: count - 1, by: 1) { if internalSet[j + 1] == item { return j + 1 } else if internalSet[j] < internalSet[j + 1] { break } } // Check to the left. for j in mid.stride(to: 0, by: -1) { if internalSet[j - 1] == item { return j - 1 } else if internalSet[j] > internalSet[j - 1] { break } } return nil ``` These loops start at the current `mid` value and then look at the neighboring values until we've found the correct object. The combined runtime for `indexOf()` is **O(log(n) + k)** where **n** is the length of the set, and **k** is the number of items with the same *value* as the one that is being searched for. Since the set is sorted, the following operations are all **O(1)**: ```swift // Returns the 'maximum' or 'largest' value in the set. public func max() -> T? { return count == 0 ? nil : internalSet[count - 1] } // Returns the 'minimum' or 'smallest' value in the set. public func min() -> T? { return count == 0 ? nil : internalSet[0] } // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. public func kLargest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] } // Returns the k-th smallest element in the set, if k is in the range // [1, count]. Returns nil otherwise. public func kSmallest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[k - 1] } ``` ## Examples Below are a few examples that can be found in the playground file. ### Example 1 Here we create a set with random Integers. Printing the largest/smallest 5 numbers in the set is fairly easy. ```swift // Example 1 with type Int var mySet = SortedSet() // Insert random numbers into the set for _ in 0..<50 { mySet.insert(randomNum(50, max: 500)) } print(mySet) print(mySet.max()) print(mySet.min()) // Print the 5 largest values for k in 1...5 { print(mySet.kLargest(k)) } // Print the 5 lowest values for k in 1...5 { print(mySet.kSmallest(k)) } ``` ### Example 2 In this example we take a look at something a bit more interesting. We define a `Player` struct as follows: ```swift public struct Player: Comparable { public var name: String public var points: Int } ``` The `Player` also gets its own `==` and `<` operators. The `<` operator is used to determine the sort order of the set, while `==` determines whether two objects are really equal. Note that `==` compares both the name and the points: ```swifr func ==(x: Player, y: Player) -> Bool { return x.name == y.name && x.points == y.points } ``` But `<` only compares the points: ```swift func <(x: Player, y: Player) -> Bool { return x.points < y.points } ``` Therefore, two `Player`s can each have the same value (the number of points), but are not guaranteed to be equal (they can have different names). We create a new set and insert 20 random players. The `Player()` constructor gives each player a random name and score: ```swift var playerSet = SortedSet() // Populate the set with random players. for _ in 0..<20 { playerSet.insert(Player()) } ``` Insert another player: ```swift var anotherPlayer = Player() playerSet.insert(anotherPlayer) ``` Now we use the `indexOf()` function to find out what rank `anotherPlayer` is. ```swift let level = playerSet.count - playerSet.indexOf(anotherPlayer)! print("\(anotherPlayer.name) is ranked at level \(level) with \(anotherPlayer.points) points") ``` ### Example 3 The final example demonstrates the need to look for the right item even after the binary search has completed. We insert 9 players into the set: ```swift var repeatedSet = SortedSet() repeatedSet.insert(Player(name: "Player 1", points: 100)) repeatedSet.insert(Player(name: "Player 2", points: 100)) repeatedSet.insert(Player(name: "Player 3", points: 100)) repeatedSet.insert(Player(name: "Player 4", points: 100)) repeatedSet.insert(Player(name: "Player 5", points: 100)) repeatedSet.insert(Player(name: "Player 6", points: 50)) repeatedSet.insert(Player(name: "Player 7", points: 200)) repeatedSet.insert(Player(name: "Player 8", points: 250)) repeatedSet.insert(Player(name: "Player 9", points: 25)) ``` Notice how several of these players have the same value of 100 points. The set looks something like this: [Player 9, Player 6, Player 1, Player 2, Player 3, Player 4, Player 5, Player 7, Player 8] The next line looks for `Player 2`: ```swift print(repeatedSet.index(of: Player(name: "Player 2", points: 100))) ``` After the binary search finishes, the value of `mid` is at index 5: [Player 9, Player 6, Player 1, Player 2, Player 3, Player 4, Player 5, Player 7, Player 8] mid However, this is not `Player 2`. Both `Player 4` and `Player 2` have the same points, but a different name. The binary search only looked at the points, not the name. But we do know that `Player 2` must be either to the immediate left or the right of `Player 4`, so we check both sides of `mid`. We only need to look at the objects with the same value as `Player 4`. The others are replaced by `X`: [X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] mid The code then first checks on the right of `mid` (where the `*` is): [X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] mid * The right side did not contain the item, so we look at the left side: [X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] * mid [X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] * mid Finally, we've found `Player 2`, and return index 3. *Written By Zain Humayun* ================================================ FILE: Sorted Set/SortedSet.playground/Pages/Example 1.xcplaygroundpage/Contents.swift ================================================ //: # Example 1 with type Int var mySet = SortedSet() // Insert random numbers into the set for _ in 0..<50 { mySet.insert(random(min: 50, max: 500)) } print(mySet) print("\nMaximum:") print(mySet.max()) print("\nMinimum:") print(mySet.min()) // Print the 5 largest values print("\n5 Largest:") for k in 1...5 { print(mySet.kLargest(k)) } // Print the 5 lowest values print("\n5 Smallest:") for k in 1...5 { print(mySet.kSmallest(k)) } //: [Next](@next) ================================================ FILE: Sorted Set/SortedSet.playground/Pages/Example 1.xcplaygroundpage/timeline.xctimeline ================================================ ================================================ FILE: Sorted Set/SortedSet.playground/Pages/Example 2.xcplaygroundpage/Contents.swift ================================================ //: [Previous](@previous) //: # Example 2 with Player objects var playerSet = SortedSet() // Populate the set with random players. for _ in 0..<20 { playerSet.insert(Player()) } // We'll look for this player later. var anotherPlayer = Player() playerSet.insert(anotherPlayer) // Print all players in order from highest points to lowest points. // (Note: this is the reverse order of how they are stored in the set!) print(playerSet) //debugPrint(playerSet) // Highest and lowest players: print(playerSet.max()) print(playerSet.min()) // We'll find our player now: let level = playerSet.count - playerSet.index(of: anotherPlayer)! print("\(anotherPlayer.name) is ranked at level \(level) with \(anotherPlayer.points) points") //: [Next](@next) ================================================ FILE: Sorted Set/SortedSet.playground/Pages/Example 3.xcplaygroundpage/Contents.swift ================================================ //: [Previous](@previous) //: # Example 3: multiple entries with the same value var repeatedSet = SortedSet() repeatedSet.insert(Player(name: "Player 1", points: 100)) repeatedSet.insert(Player(name: "Player 2", points: 100)) repeatedSet.insert(Player(name: "Player 3", points: 100)) repeatedSet.insert(Player(name: "Player 4", points: 100)) repeatedSet.insert(Player(name: "Player 5", points: 100)) repeatedSet.insert(Player(name: "Player 6", points: 50)) repeatedSet.insert(Player(name: "Player 7", points: 200)) repeatedSet.insert(Player(name: "Player 8", points: 250)) repeatedSet.insert(Player(name: "Player 9", points: 25)) print(repeatedSet) //debugPrint(repeatedSet) print(repeatedSet.index(of: Player(name: "Player 5", points: 100))) print(repeatedSet.index(of: Player(name: "Random Player", points: 100))) print(repeatedSet.index(of: Player(name: "Player 5", points: 1000))) ================================================ FILE: Sorted Set/SortedSet.playground/Sources/Player.swift ================================================ // The Player data type stores a random name, and a random number of // points from 0 - 5000. public struct Player: Comparable { public var name: String public var points: Int public init() { self.name = String.random() self.points = random(min: 0, max: 5000) } public init(name: String, points: Int) { self.name = name self.points = points } } // Player x is equal to Player y if and only if both players have the // same name and number of points. public func == (x: Player, y: Player) -> Bool { return x.name == y.name && x.points == y.points } // Player x is less than Player y if x has less points than y. public func < (x: Player, y: Player) -> Bool { return x.points < y.points } // Prints a Player formatted with their name and number of points. public func print(player: Player) { print("Player: \(player.name) | Points: \(player.points)") } public func print(set: SortedSet) { for i in 0.. Int { return min + Int(arc4random_uniform(UInt32(max - min + 1))) } // Generates a random alphanumeric string of a given length. extension String { public static func random(length: Int = 8) -> String { let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" var randomString: String = "" for _ in 0.. { private var internalSet = [T]() public init() { } // Returns the number of elements in the SortedSet. public var count: Int { return internalSet.count } // Inserts an item. Performance: O(n) public mutating func insert(_ item: T) { if exists(item) { return // don't add an item if it already exists } // Insert new the item just before the one that is larger. for i in 0.. item { internalSet.insert(item, at: i) return } } // Append to the back if the new item is greater than any other in the set. internalSet.append(item) } // Removes an item if it exists. Performance: O(n) public mutating func remove(_ item: T) { if let index = index(of: item) { internalSet.remove(at: index) } } // Returns true if and only if the item exists somewhere in the set. public func exists(_ item: T) -> Bool { return index(of: item) != nil } // Returns the index of an item if it exists, or -1 otherwise. public func index(of item: T) -> Int? { var leftBound = 0 var rightBound = count - 1 while leftBound <= rightBound { let mid = leftBound + ((rightBound - leftBound) / 2) if internalSet[mid] > item { rightBound = mid - 1 } else if internalSet[mid] < item { leftBound = mid + 1 } else if internalSet[mid] == item { return mid } else { // When we get here, we've landed on an item whose value is equal to the // value of the item we're looking for, but the items themselves are not // equal. We need to check the items with the same value to the right // and to the left in order to find an exact match. // Check to the right. for j in stride(from: mid, to: count - 1, by: 1) { if internalSet[j + 1] == item { return j + 1 } else if internalSet[j] < internalSet[j + 1] { break } } // Check to the left. for j in stride(from: mid, to: 0, by: -1) { if internalSet[j - 1] == item { return j - 1 } else if internalSet[j] > internalSet[j - 1] { break } } return nil } } return nil } // Returns the item at the given index. // Assertion fails if the index is out of the range of [0, count). public subscript(index: Int) -> T { assert(index >= 0 && index < count) return internalSet[index] } // Returns the 'maximum' or 'largest' value in the set. public func max() -> T? { return count == 0 ? nil : internalSet[count - 1] } // Returns the 'minimum' or 'smallest' value in the set. public func min() -> T? { return count == 0 ? nil : internalSet[0] } // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. public func kLargest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] } // Returns the k-th smallest element in the set, if k is in the range // [1, count]. Returns nil otherwise. public func kSmallest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[k - 1] } } ================================================ FILE: Sorted Set/SortedSet.playground/contents.xcplayground ================================================ ================================================ FILE: Sorted Set/SortedSet.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Sorted Set/SortedSet.swift ================================================ /* An Sorted Set is a collection where all items in the set follow an ordering, usually sorted from 'least' to 'most'. The way you value and compare items can be user-defined. */ public struct SortedSet { private var internalSet = [T]() public init() { } // Returns the number of elements in the SortedSet. public var count: Int { return internalSet.count } // Inserts an item. Performance: O(n) public mutating func insert(_ item: T) { if exists(item) { return // don't add an item if it already exists } // Insert new the item just before the one that is larger. for i in 0.. item { internalSet.insert(item, at: i) return } } // Append to the back if the new item is greater than any other in the set. internalSet.append(item) } // Removes an item if it exists. Performance: O(n) public mutating func remove(_ item: T) { if let index = index(of: item) { internalSet.remove(at: index) } } // Returns true if and only if the item exists somewhere in the set. public func exists(_ item: T) -> Bool { return index(of: item) != nil } // Returns the index of an item if it exists, or -1 otherwise. public func index(of item: T) -> Int? { var leftBound = 0 var rightBound = count - 1 while leftBound <= rightBound { let mid = leftBound + ((rightBound - leftBound) / 2) if internalSet[mid] > item { rightBound = mid - 1 } else if internalSet[mid] < item { leftBound = mid + 1 } else if internalSet[mid] == item { return mid } else { // When we get here, we've landed on an item whose value is equal to the // value of the item we're looking for, but the items themselves are not // equal. We need to check the items with the same value to the right // and to the left in order to find an exact match. // Check to the right. for j in stride(from: mid, to: count - 1, by: 1) { if internalSet[j + 1] == item { return j + 1 } else if internalSet[j] < internalSet[j + 1] { break } } // Check to the left. for j in stride(from: mid, to: 0, by: -1) { if internalSet[j - 1] == item { return j - 1 } else if internalSet[j] > internalSet[j - 1] { break } } return nil } } return nil } // Returns the item at the given index. // Assertion fails if the index is out of the range of [0, count). public subscript(index: Int) -> T { assert(index >= 0 && index < count) return internalSet[index] } // Returns the 'maximum' or 'largest' value in the set. public func max() -> T? { return count == 0 ? nil : internalSet[count - 1] } // Returns the 'minimum' or 'smallest' value in the set. public func min() -> T? { return count == 0 ? nil : internalSet[0] } // Returns the k-th largest element in the set, if k is in the range // [1, count]. Returns nil otherwise. public func kLargest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[count - k] } // Returns the k-th smallest element in the set, if k is in the range // [1, count]. Returns nil otherwise. public func kSmallest(_ k: Int) -> T? { return k > count || k <= 0 ? nil : internalSet[k - 1] } } ================================================ FILE: Sparse Table/README.markdown ================================================ # Sparse Table I'm excited to present **Sparse Tables**. Despite being somewhat niche, Sparse Tables are simple to implement and extremely powerful. ### The Problem Let's suppose: - we have an array **a** of some type - we have some associative binary function **f** [\*]. The function can be: min, max, [gcd](../GCD/), boolean AND, boolean OR ... *[\*] where **f** is also "idempotent". Don't worry, I'll explain this in a moment.* Our task is as follows: - Given two indices **l** and **r**, answer a **query** for the interval `[l, r)` by performing `f(a[l], a[l + 1], a[l + 2], ..., a[r - 1])`; taking all the elements in the range and applying **f** to them - There will be a *huge* number **Q** of these queries to answer ... so we should be able to answer each query *quickly*! For example, if we have an array of numbers: ```swift var a = [ 20, 3, -1, 101, 14, 29, 5, 61, 99 ] ``` and our function **f** is the *min* function. Then we may be given a query for interval `[3, 8)`. That means we look at the elements: ``` 101, 14, 29, 5, 61 ``` because these are the elements of **a** with indices that lie in our range `[3, 8)` – elements from index 3 up to, but not including, index 8. We then we pass all of these numbers into the min function, which takes the minimum. The answer to the query is `5`, because that's the result of `min(101, 14, 29, 5, 61)`. Imagine we have millions of these queries to process. > - *Query 1*: Find minimum of all elements between 2 and 5 > - *Query 2*: Find minimum of all elements between 3 and 9 > - ... > - *Query 1000000*: Find minimum of all elements between 1 and 4 And our array is very large. Here, let's say **Q** = 1000000 and **N** = 500000. Both numbers are *huge*. We want to make sure that we can answer each query really quickly, or else the number of queries will overwhelm us! *So that's the problem.* The naive solution to this problem is to perform a `for` loop to compute the answer for each query. However, for very large **Q** and very large **N** this will be too slow. We can speed up the time to compute the answer by using a data structure called a **Sparse Table**. You'll notice that so far, our problem is exactly the same as that of the [Segment Tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Segment%20Tree) (assuming you're familiar). However! ... there's one crucial difference between Segment Trees and Sparse Tables ... and it concerns our choice of **f**. ### A small gotcha ... Idempotency Suppose we wanted to find the answer to **`[A, D)`**. And we already know the answer to two ranges **`[A, B)`** and **`[C, D)`**. And importantly here, ... *these ranges overlap*!! We have **C** < **B**. ![Overlapping ranges](Images/idempotency.png) So what? Well, for **f** = minimum function, we can take our answers for **`[A, B)`** and **`[C, D)`** and combine them! We can just take the minimum of the two answers: `result = min(x1, x2)` ... *voilà!*, we have the minimum for **`[A, D)`**. It didn't matter that the intervals overlap - we still found the correct minimum. But now suppose **f** is the addition operation `+`. Ok, so now we're taking sums over ranges. If we tried the same approach again, it wouldn't work. That is, if we took our answers for **`[A, B)`** and **`[C, D)`** and added them together we'd get a wrong answer for **`[A, D)`**. *Why?* Well, we'd have counted some elements twice because of the overlap. Later, we'll see that in order to answer queries, Sparse Tables use this very technique. They combine answers in the same way as shown above. Unfortunately this means we have to exclude certain binary operators from being **f**, including `+`, `*`, XOR, ... because they don't work with this technique. In order to get the best speed of a Sparse Table, we need to make sure that the **f** we're using is an **[idempotent](https://en.wikipedia.org/wiki/Idempotence)** binary operator. Mathematically, these are operators that satisfy `f(x, x) = x` for all possible **x** that could be in **a**. Practically speaking, these are the only operators that work; allowing us to combine answers from overlapping ranges. Examples of idempotent **f**'s are min, max, gcd, boolean AND, boolean OR, bitwise AND and bitwise OR. Note that for Segment Trees, **f** does not have to be idempotent. That's the crucial difference between Segment Trees and Sparse Tables. *Phew!* Now that we've got that out of the way, let's dive in! ## Structure of a Sparse Table Let's use **f** = min and use the array: ```swift var a = [ 10, 6, 5, -7, 9, -8, 2, 4, 20 ] ``` In this case, the Sparse Table looks like this: ![Sparse Table](Images/structure.png) What's going on here? There seems to be loads of intervals. *Correct!* Sparse tables are preloaded with the answers for lots of queries `[l, r)`. Here's the idea. Before we process our **Q** queries, we'll pre-populate our Sparse Table `table` with answers to loads of queries; making it act a bit like a *cache*. When we come to answer one of our queries, we can break the query down into smaller "sub-queries", each having an answer that's already in the cache. We lookup the cached answers for the sub-queries in `table` in constant time and combine the answers together to give the overall answer to the original query in speedy time. The problem is, we can't store the answers for every single possible query that we could ever have ... or else our table would be too big! After all, our Sparse Table needs to be *sparse*. So what do we do? We only pick the "best" intervals to store answers for. And as it turns out, the "best" intervals are those that have a **width that is a power of two**! For example, the answer for the query `[10, 18)` is in our table because the interval width: `18 - 10 = 8 = 2**3` is a power of two (`**` is the [exponentiation operator](https://en.wikipedia.org/wiki/Exponentiation)). Also, the answer for `[15, 31)` is in our table because its width: `31 - 15 = 16 = 2**4` is again a power of two. However, the answer for `[1, 6)` is *not* in there because the interval's width: `6 - 1 = 5` is *not* a power of two. Consequently, we don't store answers for *all* possible intervals that fit inside **a** – only the ones with a width that is a power of two. This is true irrespective of where the interval starts within **a**. We'll gradually see that this approach works and that relatively speaking, it uses very little space. A **Sparse Table** is a table where `table[w][l]` contains the answer for `[l, l + 2**w)`. It has entries `table[w][l]` where: - **w** tells us our **width** ... the number of elements or the *width* is `2**w` - **l** tells us the **lower bound** ... it's the starting point of our interval Some examples: - `table[3][0] = -8`: our width is `2**3`, we start at `l = 0` so our query is `[0, 0 + 2**3) = [0, 8)`. The answer for this query is `min(10, 6, 5, -7, 9, -8, 2, 4, 20) = -8`. - `table[2][1] = -7`: our width is `2**2`, we start at `l = 1` so our query is `[1, 1 + 2**2) = [1, 5)`. The answer for this query is `min(6, 5, -7, 9) = -7`. - `table[1][7] = 4`: our width is `2**1`, we start at `l = 7` so our query is `[7, 7 + 2**1) = [7, 9)`. The answer for this query is `min(4, 20) = 4`. - `table[0][8] = 20`: our width is `2**0`, we start at `l = 8` so our query is`[8, 8 + 2**0) = [8, 9)`. The answer for this query is `min(20) = 20`. ![Sparse Table](Images/structure_examples.png) A Sparse Table can be implemented using a [two-dimentional array](../2D%20Array). ```swift public class SparseTable { private var table: [[T]] public init(array: [T], function: @escaping (T, T) -> T, defaultT: T) { table = [[T]](repeating: [T](repeating: defaultT, count: N), count: W) } // ... } ``` ## Building a Sparse Table To build a Sparse Table, we compute each table entry starting from the bottom-left and moving up towards the top-right (in accordance with the diagram). First we'll compute all the intervals for **w** = 0, then compute all the intervals and for **w** = 1 and so on. We'll continue up until **w** is big enough such that our intervals are can cover at least half the array. For each **w**, we compute the interval for **l** = 0, 1, 2, 3, ... until we reach **N**. This is all achieved using a double `for`-`in` loop: ```swift for w in 0.. 0)**: We need to find out the answer to `[l, l + 2**w)` for some **l**. This interval, like all of our intervals in our table has a width that is a power of two (e.g. 2, 4, 8, 16) ... so we can cut it into two equal halves. - Our interval with width ``2**w`` is cut into two intervals, each of width ``2**(w - 1)``. - Because each half has a width that is a power of two, we can look them up in our Sparse Table. - We combine them together using **f**. ``` table[w][l] = f(table[w - 1][l], table[w - 1][l + 2 ** (w - 1)]) ``` ![Sparse Table](Images/recursion.png) For example for `a = [ 10, 6, 5, -7, 9, -8, 2, 4, 20 ]` and **f** = *min*: - we compute `table[0][2] = 5`. We just had to look at `a[2]` because the range has a width of one. - we compute `table[1][7] = 4`. We looked at `table[0][7]` and `table[0][8]` and apply **f** to them. - we compute `table[3][1] = -8`. We looked at `table[2][1]` and `table[2][5]` and apply **f** to them. ![Sparse Table](Images/recursion_examples.png) ```swift public init(array: [T], function: @escaping (T, T) -> T, defaultT: T) { let N = array.count let W = Int(ceil(log2(Double(N)))) table = [[T]](repeating: [T](repeating: defaultT, count: N), count: W) self.function = function self.defaultT = defaultT for w in 0.. T { let width = r - l let W = Int(floor(log2(Double(width)))) let lo = table[W][l] let hi = table[W][r - (1 << W)] return function(lo, hi) } ``` Finding answers to queries takes **O(1)** time. ## Analysing Sparse Tables - **Query Time** - Both table lookups take constant time. All other operations inside `query` take constant time. So answering a single query also takes constant time: **O(1)**. But instead of one query we're actually answering **Q** queries, and we'll need time to built the table before-hand. Overall time is: **O(NlgN + Q)** to build the table and answer all queries. The naive approach is to do a for loop for each query. The overall time for the naive approach is: **O(NQ)**. For very large **Q**, the naive approach will scale poorly. For example if `Q = O(N*N)` then the naive approach is `O(N*N*N)` where a Sparse Table takes time `O(N*N)`. - **Space**- The number of possible **w** is **lgN** and the number of possible **l** our table is **N**. So the table has uses **O(NlgN)** additional space. ### Comparison with Segment Trees - **Pre-processing** - Segment Trees take **O(N)** time to build and use **O(N)** space. Sparse Tables take **O(NlgN)** time to build and use **O(NlgN)** space. - **Queries** - Segment Tree queries are **O(lgN)** time for any **f** (idempotent or not idempotent). Sparse Table queries are **O(1)** time if **f** is idempotent and are not supported if **f** is not idempotent. [†] - **Replacing Items** - Segment Trees allow us to efficiently update an element in **a** and update the segment tree in **O(lgN)** time. Sparse Tables do not allow this to be done efficiently. If we were to update an element in **a**, we'd have to rebuild the Sparse Table all over again in **O(NlgN)** time. [†] *Although technically, it's possible to rewrite the `query` method to add support for non-idempotent functions. But in doing so, we'd bump up the time up from O(1) to O(lgn), completely defeating the original purpose of Sparse Tables - supporting lightening quick queries. In such a case, we'd be better off using a Segment Tree (or a Fenwick Tree)* ## Summary That's it! See the playground for more examples involving Sparse Tables. You'll see examples for: min, max, gcd, boolean operators and logical operators. ### See also - [Segment Trees (Swift Algorithm Club)](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Segment%20Tree) - [How to write O(lgn) time query function to support non-idempontent functions (GeeksForGeeks)](https://www.geeksforgeeks.org/range-sum-query-using-sparse-table/) - [Fenwick Trees / Binary Indexed Trees (TopCoder)](https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/) - [Semilattice (Wikipedia)](https://en.wikipedia.org/wiki/Semilattice) *Written for Swift Algorithm Club by [James Lawson](https://github.com/jameslawson)* ================================================ FILE: Sparse Table/Sparse Table.playground/Contents.swift ================================================ // // Swift Algorithm Club - Sparse Table // Author: James Lawson (github.com/jameslawson) // import Foundation // Last checked with Xcode Version 9.2 (9C40b) #if swift(>=4.0) print("Hello, Swift 4!") #endif public class SparseTable { private var defaultT: T private var table: [[T]] private var function: (T, T) -> T public init(array: [T], function: @escaping (T, T) -> T, defaultT: T) { let N = array.count let W = Int(ceil(log2(Double(N)))) table = [[T]](repeating: [T](repeating: defaultT, count: N), count: W) self.function = function self.defaultT = defaultT for w in 0.. T { let width = r - l let N = table[0].count if width <= 0 || l >= N { return defaultT } let r = min(N, r) let W = Int(floor(log2(Double(width)))) let lo = table[W][l] let hi = table[W][r - (1 << W)] return function(lo, hi) } } print("---------------------------- EXAMPLE 1 -------------------------------------") // Here we have an array of integers and we're repeatedly // finding the minimum over various ranges let intArray = [1, -11, -7, 3, 2, 4] let minIntTable = SparseTable(array: intArray, function: min, defaultT: Int.max) print(minIntTable.query(from: 0, until: 6)) // min(1, 3, -11, 3, 2, 4) = -11 print(minIntTable.query(from: 3, until: 5)) // min(3, 2) = 2 print(minIntTable.query(from: 2, until: 6)) // min(-7, 3, 2, 4) = -7 print(minIntTable.query(from: 0, until: 1)) // min(1) = 1 print(minIntTable.query(from: 0, until: 0)) // min() = Int.max print("----------------------------------------------------------------------------\n\n") print("---------------------------- EXAMPLE 2 -------------------------------------") // Now we have an array of doubles and we're repeatedly // finding the maximum over various ranges let doubleArray = [1.5, 20.0, 3.5, 15.0, 18.0, -10.0, 5.5] let maxDoubleTable = SparseTable(array: doubleArray, function: max, defaultT: -.infinity) print(maxDoubleTable.query(from: 0, until: 4)) // max(1.5, 20.0, 3.5, 15.0) = 20.0 print(maxDoubleTable.query(from: 3, until: 4)) // max(3.5, 15.0) = 15.0 print(maxDoubleTable.query(from: 4, until: 6)) // max(18.0, -10.0, 5.5) = 18.0 print(maxDoubleTable.query(from: 1, until: 2)) // max(20.0) = 20.0 print(maxDoubleTable.query(from: 0, until: 0)) // max() = -inf print("----------------------------------------------------------------------------\n\n") print("---------------------------- EXAMPLE 3 -------------------------------------") // An array of booleans and we're repeatedly // finding the boolean AND over various ranges let boolArray = [true, false, true, true, true, false, false] func and(_ x: Bool, _ y: Bool) -> Bool { return x && y } let maxBoolTable = SparseTable(array: boolArray, function: and, defaultT: false) print(maxBoolTable.query(from: 0, until: 4)) // and(T, F, T, T) = F print(maxBoolTable.query(from: 2, until: 5)) // and(T, T, T) = T print(maxBoolTable.query(from: 2, until: 6)) // and(T, T, T, F) = F print(maxBoolTable.query(from: 0, until: 1)) // and(T) = T print(maxBoolTable.query(from: 1, until: 2)) // and(F) = F print(maxBoolTable.query(from: 0, until: 0)) // and() = F print("----------------------------------------------------------------------------\n\n") print("---------------------------- EXAMPLE 4 -------------------------------------") // An array of positive integers and we're repeatedly finding // the gcd (greatest common divisor) over various ranges. The gcd operator is // associative and idempotent so we can use it with sparse tables let posIntArray = [7, 2, 3, 4, 6, 5, 25, 75, 100] func gcd(_ m: Int, _ n: Int) -> Int { var a = 0 var b = max(m, n) var r = min(m, n) while r != 0 { a = b b = r r = a % b } return b } let gcdTable = SparseTable(array: posIntArray, function: gcd, defaultT: 1) print(gcdTable.query(from: 0, until: 4)) // gcd(7, 2, 3) = 1 print(gcdTable.query(from: 3, until: 5)) // gcd(4, 6) = 2 print(gcdTable.query(from: 5, until: 7)) // gcd(5, 25, 75) = 5 print(gcdTable.query(from: 6, until: 9)) // gcd(25, 75, 100) = 25 print(gcdTable.query(from: 3, until: 4)) // gcd(4) = 4 print(gcdTable.query(from: 0, until: 0)) // gcd() = 1 print("------------------------------------------------------------------------\n\n") print("---------------------------- EXAMPLE 5 -------------------------------------") // An array of nonnegative integers where for each integer we consider its binary representation. // We're repeatedly finding the binary OR (|) over various ranges. The binary operator is // associative and idempotent so we can use it with sparse tables let binArray = [0b1001, 0b1100, 0b0000, 0b0001, 0b0010, 0b0100, 0b0000, 0b1111] let orTable = SparseTable(array: binArray, function: |, defaultT: 0b0000) print(String(orTable.query(from: 0, until: 2), radix: 2)) // binary_or(1001, 1100) = 1101 print(String(orTable.query(from: 3, until: 5), radix: 2)) // binary_or(0001, 0010) = 0011 print(String(orTable.query(from: 3, until: 6), radix: 2)) // binary_or(0001, 0010, 0100) = 0111 print(String(orTable.query(from: 6, until: 8), radix: 2)) // binary_or(0000, 1111) = 1111 print(String(orTable.query(from: 1, until: 5), radix: 2)) // binary_or(1100, 0000, 0001, 0010) = 1111 print(String(orTable.query(from: 0, until: 1), radix: 2)) // binary_or(1001) = 1001 print(String(orTable.query(from: 0, until: 0), radix: 2)) // binary_or() = 0000 print("----------------------------------------------------------------------------\n\n") ================================================ FILE: Sparse Table/Sparse Table.playground/contents.xcplayground ================================================ ================================================ FILE: Sparse Table/Sparse Table.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Splay Tree/SplayTree.playground/Contents.swift ================================================ //: Playground - Splay Tree Implementation // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif var tree = SplayTree(value: 0) tree.insert(value: 2) tree.insert(value: 3) tree.insert(value: 4) tree.insert(value: 7) _ = tree.search(value: 2) tree.remove(value: 2) ================================================ FILE: Splay Tree/SplayTree.playground/Sources/SplayTree.swift ================================================ /* * Splay Tree * * Based on Binary Search Tree Implementation written by Nicolas Ameghino and Matthijs Hollemans for Swift Algorithms Club * https://github.com/raywenderlich/swift-algorithm-club/blob/master/Binary%20Search%20Tree * And extended for the specifics of a Splay Tree by Barbara Martina Rodeker * */ /** Represent the 3 possible operations (combinations of rotations) that could be performed during the Splay phase in Splay Trees - zigZag Left child of a right child OR right child of a left child - zigZig Left child of a left child OR right child of a right child - zig Only 1 parent and that parent is the root */ public enum SplayOperation { case zigZag case zigZig case zig /** Splay the given node up to the root of the tree - Parameters: - node SplayTree node to move up to the root */ public static func splay(node: Node) { while (node.parent != nil) { operation(forNode: node).apply(onNode: node) } } /** Compares the node and its parent and determine if the rotations should be performed in a zigZag, zigZig or zig case. - Parmeters: - forNode SplayTree node to be checked - Returns - Operation Case zigZag - zigZig - zig */ public static func operation(forNode node: Node) -> SplayOperation { if let parent = node.parent, let _ = parent.parent { if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { return .zigZag } return .zigZig } return .zig } /** Applies the rotation associated to the case Modifying the splay tree and briging the received node further to the top of the tree - Parameters: - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ public func apply(onNode node: Node) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node, parent: node.parent!) rotate(child: node, parent: node.parent!) case .zigZig: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node.parent!, parent: node.parent!.parent!) rotate(child: node, parent: node.parent!) case .zig: assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") rotate(child: node, parent: node.parent!) } } /** Performs a single rotation from a node to its parent re-arranging the children properly */ public func rotate(child: Node, parent: Node) { assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") var grandchildToMode: Node? if child.isLeftChild { grandchildToMode = child.right parent.left = grandchildToMode grandchildToMode?.parent = parent let grandParent = parent.parent child.parent = grandParent if parent.isLeftChild { grandParent?.left = child } else { grandParent?.right = child } child.right = parent parent.parent = child } else { grandchildToMode = child.left parent.right = grandchildToMode grandchildToMode?.parent = parent let grandParent = parent.parent child.parent = grandParent if parent.isLeftChild { grandParent?.left = child } else { grandParent?.right = child } child.left = parent parent.parent = child } } } public class Node { fileprivate(set) public var value: T? fileprivate(set) public var parent: Node? fileprivate(set) public var left: Node? fileprivate(set) public var right: Node? init(value: T) { self.value = value } public var isRoot: Bool { return parent == nil } public var isLeaf: Bool { return left == nil && right == nil } public var isLeftChild: Bool { return parent?.left === self } public var isRightChild: Bool { return parent?.right === self } public var hasLeftChild: Bool { return left != nil } public var hasRightChild: Bool { return right != nil } public var hasAnyChild: Bool { return hasLeftChild || hasRightChild } public var hasBothChildren: Bool { return hasLeftChild && hasRightChild } /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { return (left?.count ?? 0) + 1 + (right?.count ?? 0) } } public class SplayTree { internal var root: Node? var value: T? { return root?.value } //MARK: - Initializer public init(value: T) { self.root = Node(value:value) } public func insert(value: T) { if let root = root { self.root = root.insert(value: value) } else { root = Node(value: value) } } public func remove(value: T) { root = root?.remove(value: value) } public func search(value: T) -> Node? { root = root?.search(value: value) return root } public func minimum() -> Node? { root = root?.minimum(splayed: true) return root } public func maximum() -> Node? { root = root?.maximum(splayed: true) return root } } // MARK: - Adding items extension Node { /* Inserts a new element into the node tree. - Parameters: - value T value to be inserted. Will be splayed to the root position - Returns: - Node inserted */ public func insert(value: T) -> Node { if let selfValue = self.value { if value < selfValue { if let left = left { return left.insert(value: value) } else { left = Node(value: value) left?.parent = self if let left = left { SplayOperation.splay(node: left) return left } } } else { if let right = right { return right.insert(value: value) } else { right = Node(value: value) right?.parent = self if let right = right { SplayOperation.splay(node: right) return right } } } } return self } } // MARK: - Deleting items extension Node { /* Deletes the given node from the nodes tree. Return the new tree generated by the removal. The removed node (not necessarily the one containing the value), will be splayed to the root. - Parameters: - value To be removed - Returns: - Node Resulting from the deletion and the splaying of the removed node */ fileprivate func remove(value: T) -> Node? { guard let target = search(value: value) else { return self } if let left = target.left, let right = target.right { let largestOfLeftChild = left.maximum() left.parent = nil right.parent = nil SplayOperation.splay(node: largestOfLeftChild) largestOfLeftChild.right = right return largestOfLeftChild } else if let left = target.left { replace(node: target, with: left) return left } else if let right = target.right { replace(node: target, with: right) return right } else { return nil } } private func replace(node: Node, with newNode: Node?) { guard let sourceParent = sourceNode.parent else { return } if sourceNode.isLeftChild { sourceParent.left = newNode } else { sourceParent.right = newNode } newNode?.parent = sourceParent } } // MARK: - Searching extension Node { /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ public func search(value: T) -> Node? { var node: Node? = self var nodeParent: Node? = self while case let n? = node, n.value != nil { if value < n.value! { if n.left != nil { nodeParent = n.left } node = n.left } else if value > n.value! { node = n.right if n.right != nil { nodeParent = n.right } } else { break } } if let node = node { SplayOperation.splay(node: node) return node } else if let nodeParent = nodeParent { SplayOperation.splay(node: nodeParent) return nodeParent } return nil } public func contains(value: T) -> Bool { return search(value: value) != nil } /* Returns the leftmost descendent. O(h) time. */ public func minimum(splayed: Bool = false) -> Node { var node = self while case let next? = node.left { node = next } if splayed == true { SplayOperation.splay(node: node) } return node } /* Returns the rightmost descendent. O(h) time. */ public func maximum(splayed: Bool = false) -> Node { var node = self while case let next? = node.right { node = next } if splayed == true { SplayOperation.splay(node: node) } return node } /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. */ public func depth() -> Int { var node = self var edges = 0 while case let parent? = node.parent { node = parent edges += 1 } return edges } /* Calculates the height of this node, i.e. the distance to the lowest leaf. Since this looks at all children of this node, performance is O(n). */ public func height() -> Int { if isLeaf { return 0 } else { return 1 + max(left?.height() ?? 0, right?.height() ?? 0) } } /* Finds the node whose value precedes our value in sorted order. */ public func predecessor() -> Node? { if let left = left { return left.maximum() } else { var node = self while case let parent? = node.parent, parent.value != nil, value != nil { if parent.value! < value! { return parent } node = parent } return nil } } /* Finds the node whose value succeeds our value in sorted order. */ public func successor() -> Node? { if let right = right { return right.minimum() } else { var node = self while case let parent? = node.parent, parent.value != nil , value != nil { if parent.value! > value! { return parent } node = parent } return nil } } } // MARK: - Traversal extension Node { public func traverseInOrder(process: (T) -> Void) { left?.traverseInOrder(process: process) process(value!) right?.traverseInOrder(process: process) } public func traversePreOrder(process: (T) -> Void) { process(value!) left?.traversePreOrder(process: process) right?.traversePreOrder(process: process) } public func traversePostOrder(process: (T) -> Void) { left?.traversePostOrder(process: process) right?.traversePostOrder(process: process) process(value!) } /* Performs an in-order traversal and collects the results in an array. */ public func map(formula: (T) -> T) -> [T] { var a = [T]() if let left = left { a += left.map(formula: formula) } a.append(formula(value!)) if let right = right { a += right.map(formula: formula) } return a } } /* Is this binary tree a valid binary search tree? */ extension Node { public func isBST(minValue: T, maxValue: T) -> Bool { if let value = value { if value < minValue || value > maxValue { return false } let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true return leftBST && rightBST } return false } } // MARK: - Debugging extension Node: CustomStringConvertible { public var description: String { var s = "" if let left = left { s += "left: (\(left.description)) <- " } if let v = value { s += "\(v)" } if let right = right { s += " -> (right: \(right.description))" } return s } } extension SplayTree: CustomStringConvertible { public var description: String { return root?.description ?? "Empty tree" } } extension Node: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(String(describing: value))" if let parent = parent, let v = parent.value { s += ", parent: \(v)" } if let left = left { s += ", left = [" + left.debugDescription + "]" } if let right = right { s += ", right = [" + right.debugDescription + "]" } return s } public func toArray() -> [T] { return map { $0 } } } extension SplayTree: CustomDebugStringConvertible { public var debugDescription: String { return root?.debugDescription ?? "Empty tree" } } ================================================ FILE: Splay Tree/SplayTree.playground/contents.xcplayground ================================================ ================================================ FILE: Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Splay Tree/SplayTree.swift ================================================ /* * Splay Tree * * Based on Binary Search Tree Implementation written by Nicolas Ameghino and Matthijs Hollemans for Swift Algorithms Club * https://github.com/raywenderlich/swift-algorithm-club/blob/master/Binary%20Search%20Tree * And extended for the specifics of a Splay Tree by Barbara Martina Rodeker * */ /** Represent the 3 possible operations (combinations of rotations) that could be performed during the Splay phase in Splay Trees - zigZag Left child of a right child OR right child of a left child - zigZig Left child of a left child OR right child of a right child - zig Only 1 parent and that parent is the root */ public enum SplayOperation { case zigZag case zigZig case zig /** Splay the given node up to the root of the tree - Parameters: - node SplayTree node to move up to the root */ public static func splay(node: Node) { while (node.parent != nil) { operation(forNode: node).apply(onNode: node) } } /** Compares the node and its parent and determine if the rotations should be performed in a zigZag, zigZig or zig case. - Parmeters: - forNode SplayTree node to be checked - Returns - Operation Case zigZag - zigZig - zig */ public static func operation(forNode node: Node) -> SplayOperation { if let parent = node.parent, let _ = parent.parent { if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { return .zigZag } return .zigZig } return .zig } /** Applies the rotation associated to the case Modifying the splay tree and briging the received node further to the top of the tree - Parameters: - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ public func apply(onNode node: Node) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node, parent: node.parent!) rotate(child: node, parent: node.parent!) case .zigZig: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node.parent!, parent: node.parent!.parent!) rotate(child: node, parent: node.parent!) case .zig: assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") rotate(child: node, parent: node.parent!) } } /** Performs a single rotation from a node to its parent re-arranging the children properly */ public func rotate(child: Node, parent: Node) { assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") var grandchildToMode: Node? if child.isLeftChild { grandchildToMode = child.right parent.left = grandchildToMode grandchildToMode?.parent = parent let grandParent = parent.parent child.parent = grandParent if parent.isLeftChild { grandParent?.left = child } else { grandParent?.right = child } child.right = parent parent.parent = child } else { grandchildToMode = child.left parent.right = grandchildToMode grandchildToMode?.parent = parent let grandParent = parent.parent child.parent = grandParent if parent.isLeftChild { grandParent?.left = child } else { grandParent?.right = child } child.left = parent parent.parent = child } } } public class Node { fileprivate(set) public var value: T? fileprivate(set) public var parent: Node? fileprivate(set) public var left: Node? fileprivate(set) public var right: Node? init(value: T) { self.value = value } public var isRoot: Bool { return parent == nil } public var isLeaf: Bool { return left == nil && right == nil } public var isLeftChild: Bool { return parent?.left === self } public var isRightChild: Bool { return parent?.right === self } public var hasLeftChild: Bool { return left != nil } public var hasRightChild: Bool { return right != nil } public var hasAnyChild: Bool { return hasLeftChild || hasRightChild } public var hasBothChildren: Bool { return hasLeftChild && hasRightChild } /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { return (left?.count ?? 0) + 1 + (right?.count ?? 0) } } public class SplayTree { internal var root: Node? var value: T? { return root?.value } //MARK: - Initializer public init(value: T) { self.root = Node(value:value) } public func insert(value: T) { if let root = root { self.root = root.insert(value: value) } else { root = Node(value: value) } } public func remove(value: T) { root = root?.remove(value: value) } public func search(value: T) -> Node? { root = root?.search(value: value) return root } public func minimum() -> Node? { root = root?.minimum(splayed: true) return root } public func maximum() -> Node? { root = root?.maximum(splayed: true) return root } } // MARK: - Adding items extension Node { /* Inserts a new element into the node tree. - Parameters: - value T value to be inserted. Will be splayed to the root position - Returns: - Node inserted */ public func insert(value: T) -> Node { if let selfValue = self.value { if value < selfValue { if let left = left { return left.insert(value: value) } else { left = Node(value: value) left?.parent = self if let left = left { SplayOperation.splay(node: left) return left } } } else { if let right = right { return right.insert(value: value) } else { right = Node(value: value) right?.parent = self if let right = right { SplayOperation.splay(node: right) return right } } } } return self } } // MARK: - Deleting items extension Node { /* Deletes the given node from the nodes tree. Return the new tree generated by the removal. The removed node (not necessarily the one containing the value), will be splayed to the root. - Parameters: - value To be removed - Returns: - Node Resulting from the deletion and the splaying of the removed node */ fileprivate func remove(value: T) -> Node? { guard let target = search(value: value) else { return self } if let left = target.left, let right = target.right { let largestOfLeftChild = left.maximum() left.parent = nil right.parent = nil SplayOperation.splay(node: largestOfLeftChild) largestOfLeftChild.right = right return largestOfLeftChild } else if let left = target.left { replace(node: target, with: left) return left } else if let right = target.right { replace(node: target, with: right) return right } else { return nil } } private func replace(node: Node, with newNode: Node?) { guard let sourceParent = sourceNode.parent else { return } if sourceNode.isLeftChild { sourceParent.left = newNode } else { sourceParent.right = newNode } newNode?.parent = sourceParent } } // MARK: - Searching extension Node { /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ public func search(value: T) -> Node? { var node: Node? = self var nodeParent: Node? = self while case let n? = node, n.value != nil { if value < n.value! { if n.left != nil { nodeParent = n.left } node = n.left } else if value > n.value! { node = n.right if n.right != nil { nodeParent = n.right } } else { break } } if let node = node { SplayOperation.splay(node: node) return node } else if let nodeParent = nodeParent { SplayOperation.splay(node: nodeParent) return nodeParent } return nil } public func contains(value: T) -> Bool { return search(value: value) != nil } /* Returns the leftmost descendent. O(h) time. */ public func minimum(splayed: Bool = false) -> Node { var node = self while case let next? = node.left { node = next } if splayed == true { SplayOperation.splay(node: node) } return node } /* Returns the rightmost descendent. O(h) time. */ public func maximum(splayed: Bool = false) -> Node { var node = self while case let next? = node.right { node = next } if splayed == true { SplayOperation.splay(node: node) } return node } /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. */ public func depth() -> Int { var node = self var edges = 0 while case let parent? = node.parent { node = parent edges += 1 } return edges } /* Calculates the height of this node, i.e. the distance to the lowest leaf. Since this looks at all children of this node, performance is O(n). */ public func height() -> Int { if isLeaf { return 0 } else { return 1 + max(left?.height() ?? 0, right?.height() ?? 0) } } /* Finds the node whose value precedes our value in sorted order. */ public func predecessor() -> Node? { if let left = left { return left.maximum() } else { var node = self while case let parent? = node.parent, parent.value != nil, value != nil { if parent.value! < value! { return parent } node = parent } return nil } } /* Finds the node whose value succeeds our value in sorted order. */ public func successor() -> Node? { if let right = right { return right.minimum() } else { var node = self while case let parent? = node.parent, parent.value != nil , value != nil { if parent.value! > value! { return parent } node = parent } return nil } } } // MARK: - Traversal extension Node { public func traverseInOrder(process: (T) -> Void) { left?.traverseInOrder(process: process) process(value!) right?.traverseInOrder(process: process) } public func traversePreOrder(process: (T) -> Void) { process(value!) left?.traversePreOrder(process: process) right?.traversePreOrder(process: process) } public func traversePostOrder(process: (T) -> Void) { left?.traversePostOrder(process: process) right?.traversePostOrder(process: process) process(value!) } /* Performs an in-order traversal and collects the results in an array. */ public func map(formula: (T) -> T) -> [T] { var a = [T]() if let left = left { a += left.map(formula: formula) } a.append(formula(value!)) if let right = right { a += right.map(formula: formula) } return a } } /* Is this binary tree a valid binary search tree? */ extension Node { public func isBST(minValue: T, maxValue: T) -> Bool { if let value = value { if value < minValue || value > maxValue { return false } let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true return leftBST && rightBST } return false } } // MARK: - Debugging extension Node: CustomStringConvertible { public var description: String { var s = "" if let left = left { s += "left: (\(left.description)) <- " } if let v = value { s += "\(v)" } if let right = right { s += " -> (right: \(right.description))" } return s } } extension SplayTree: CustomStringConvertible { public var description: String { return root?.description ?? "Empty tree" } } extension Node: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(value)" if let parent = parent, let v = parent.value { s += ", parent: \(v)" } if let left = left { s += ", left = [" + left.debugDescription + "]" } if let right = right { s += ", right = [" + right.debugDescription + "]" } return s } public func toArray() -> [T] { return map { $0 } } } extension SplayTree: CustomDebugStringConvertible { public var debugDescription: String { return root?.debugDescription ?? "Empty tree" } } ================================================ FILE: Splay Tree/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Splay Tree/Tests/SplayTreeTests.swift ================================================ import XCTest class SplayTreeTests: XCTestCase { var tree1: SplayTree! var tree2: SplayTree! override func setUp() { super.setUp() tree1 = SplayTree(value: 1) tree2 = SplayTree(value: 1) tree2.insert(value: 10) tree2.insert(value: 20) tree2.insert(value: 3) tree2.insert(value: 6) tree2.insert(value: 100) tree2.insert(value: 44) } func testInsertion() { tree1.insert(value: 10) assert(tree1.value == 10) tree2.insert(value: 2) assert(tree2.root?.value == 2) } func testSearchNonExisting() { let t = tree2.search(value: 5) assert(t?.value == 10) } func testSearchExisting() { let t = tree2.search(value: 6) assert(t?.value == 6) } func testDeleteExistingOnlyLeftChild() { tree2.remove(value: 3) assert(tree2.value == 6) } func testDeleteExistingOnly2Children() { tree2.remove(value: 6) assert(tree2.value == 20) } func testDeleteRoot() { tree2.remove(value: 44) assert(tree2.value == 100) } func testMinimum() { let v = tree2.minimum() assert(v?.value == 1) } func testMaximum() { let v = tree2.maximum() assert(v?.value == 100) } func testInsertionRemovals() { let splayTree = SplayTree(value: 1) splayTree.insert(value: 2) splayTree.insert(value: 10) splayTree.insert(value: 6) splayTree.remove(value: 10) splayTree.remove(value: 6) assert(splayTree.value == 2) } } ================================================ FILE: Splay Tree/Tests/Tests-Bridging-Header.h ================================================ // // Use this file to import your target's public headers that you would like to expose to Swift. // ================================================ FILE: Splay Tree/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 763F9E771E59DAEF00AC5031 /* SplayTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F9E761E59DAEF00AC5031 /* SplayTree.swift */; }; 763F9E791E59DAFE00AC5031 /* SplayTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 056E92A21E25D04D00B30F52 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 056E92A61E25D04D00B30F52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 763F9E761E59DAEF00AC5031 /* SplayTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SplayTree.swift; path = ../SplayTree.swift; sourceTree = ""; }; 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SplayTreeTests.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 056E929F1E25D04D00B30F52 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 056E92851E25D03300B30F52 = { isa = PBXGroup; children = ( 056E92A31E25D04D00B30F52 /* Tests */, 056E928F1E25D03300B30F52 /* Products */, ); sourceTree = ""; }; 056E928F1E25D03300B30F52 /* Products */ = { isa = PBXGroup; children = ( 056E92A21E25D04D00B30F52 /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 056E92A31E25D04D00B30F52 /* Tests */ = { isa = PBXGroup; children = ( 056E92A61E25D04D00B30F52 /* Info.plist */, 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */, 763F9E761E59DAEF00AC5031 /* SplayTree.swift */, ); name = Tests; sourceTree = SOURCE_ROOT; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 056E92A11E25D04D00B30F52 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 056E929E1E25D04D00B30F52 /* Sources */, 056E929F1E25D04D00B30F52 /* Frameworks */, 056E92A01E25D04D00B30F52 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = 056E92A21E25D04D00B30F52 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 056E92861E25D03300B30F52 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0820; LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 056E92A11E25D04D00B30F52 = { CreatedOnToolsVersion = 8.2; LastSwiftMigration = 0820; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 056E92851E25D03300B30F52; productRefGroup = 056E928F1E25D03300B30F52 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 056E92A11E25D04D00B30F52 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 056E92A01E25D04D00B30F52 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 056E929E1E25D04D00B30F52 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 763F9E771E59DAEF00AC5031 /* SplayTree.swift in Sources */, 763F9E791E59DAFE00AC5031 /* SplayTreeTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 056E92991E25D03300B30F52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 056E929A1E25D03300B30F52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 056E92A81E25D04D00B30F52 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Tests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 3.0; }; name = Debug; }; 056E92A91E25D04D00B30F52 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Tests-Bridging-Header.h"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 056E92991E25D03300B30F52 /* Debug */, 056E929A1E25D03300B30F52 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 056E92A81E25D04D00B30F52 /* Debug */, 056E92A91E25D04D00B30F52 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 056E92861E25D03300B30F52 /* Project object */; } ================================================ FILE: Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Splay Tree/readme.md ================================================ # Splay Tree Splay tree is a data structure, structurally identitical to a balanced binary search tree. Every operation performed on a Splay Tree causes a readjustment in order to provide fast access to recently operated values. On every access, the tree is rearranged and the node accessed is moved to the root of the tree using a set of specific rotations, which together are referred to as **Splaying**. ## Rotations There are 3 types of rotations that can form an **Splaying**: - ZigZig - ZigZag - Zig ### Zig-Zig Given a node *a* if *a* is not the root, and *a* has a child *b*, and both *a* and *b* are left children or right children, a **Zig-Zig** is performed. ### Case both nodes right children ![ZigZigCase1](Images/zigzig1.png) ### Case both nodes left children ![ZigZigCase2](Images/zigzig2.png) **IMPORTANT** is to note that a *ZigZig* performs first the rotation of the middle node with its parent (call it the grandparent) and later the rotation of the remaining node (grandchild). Doing that helps to keep the trees balanced even if it was first created by inserted a sequence of increasing values (see below worst case scenario followed by an explanation about why ZigZig rotates first to the grandparent). ### Zig-Zag Given a node *a* if *a* is not the root, and *a* has a child *b*, and *b* is the left child of *a* being the right child (or the opposite), a **Zig-Zag** is performed. ### Case right - left ![ZigZagCase1](Images/zigzag1.png) ### Case left - right ![ZigZagCase2](Images/zigzag2.png) **IMPORTANT** A *ZigZag* performs first the rotation of the grandchild node and later the same node with its new parent again. ### Zig A **Zig** is performed when the node *a* to be rotated has the root as parent. ![ZigCase](Images/zig.png) ## Splaying Splaying consists in making so many rotations as needed until the node affected by the operation is at the top and becomes the root of the tree. ``` while (node.parent != nil) { operation(forNode: node).apply(onNode: node) } ``` Where operation returns the required rotation to be applied. ``` public static func operation(forNode node: Node) -> SplayOperation { if let parent = node.parent, let _ = parent.parent { if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { return .zigZag } return .zigZig } return .zig } ``` During the applying phase, the algorithms determines which nodes are involved depending on the rotation to be applied and proceeding to re-arrange the node with its parent. ``` public func apply(onNode node: Node) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node, parent: node.parent!) rotate(child: node, parent: node.parent!) case .zigZig: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node.parent!, parent: node.parent!.parent!) rotate(child: node, parent: node.parent!) case .zig: assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") rotate(child: node, parent: node.parent!) } } ``` ## Operations on an Splay Tree ### Insertion To insert a value: - Insert it as in a binary search tree - Splay the value to the root ### Deletion To delete a value: - Perform search for the value, after performed search function if the tree contains the value, it'll be the root of the new tree. - If the tree has only left child, change left child to the root of the tree, remove the old root node - If the tree has only right child, change right child to the root of the tree, remove the old root node - Else, the tree has both two children, set parent of two children to nil, so that they're two new trees (left-tree and right-tree). - Splay the minimum node of right-tree (or minimum node of left-tree), then set left-tree as left child of new root of right-tree (or set right-tree as right child of new root of left-tree), return right-tree ### Search To search a value: - Search for it as in a binary search tree - Splay the node containing the value to the root - If not found splay the node that would had been the parent of the searched value ### Minimum and maximum - Search the tree for the required value - Splay the node to the root ## Examples ### Example 1 Lets suppose a *find(20)* operation was performed and now the values **20** needs to be splayed to the root. The sequence of steps will be the following: 1. Since we are in a *ZigZig* case, we need to rotate **9** to **4** ![ZiggEx1](Images/examplezigzig1.png) 2. We got the following tree after the first rotation: ![ZiggEx2](Images/examplezigzig2.png) 3. And finally the **20** is rotated to the **9** ![ZiggEx3](Images/examplezigzig3.png) ### Example 2 Now suppose a *insert(7)* operation was performed and we're in a *ZigZag* case. 1. First **7** is rotated to **9** ![ZigggEx21](Images/example1-1.png) 2. And the result tree is: ![ZigggEx22](Images/example1-2.png) 3. Finally **7** is rotated to **4** ![ZigggEx23](Images/example1-3.png) ## Advantages Splay trees provide an efficient way to quickly access elements that are frequently requested. This characteristic makes then a good choice to implement, for example, caches or garbage collection algorithms, or in any other problem involving frequent access to a certain numbers of elements from a data set. ## Disadvantages Splay tree are not perfectly balanced always, so in case of accessing all the elements in the tree in an increasing order, the height of the tree becomes *n*. ## Time complexity | Case | Performance | | ------------- |:-------------:| | Average | O(log n) | | Worst | n | With *n* being the number of items in the tree. # An example of the Worst Case Performance Suppose the a sequence of consecutive values are inserted in an Splay Tree. Let's take for example [1,2,3,4,5,6,7,8]. The tree construction will be like following: 1. Insert the number **1** 2. Insert **2** ![WorstCase1](Images/worst-case-1.png) 3. Splay **2** to the root ![WorstCase2](Images/worst-case-2.png) 4. Insert **3** ![WorstCase3](Images/worst-case-3.png) 5. Splay **3** to the root ![WorstCase4](Images/worst-case-4.png) 6. Insert **4** ![WorstCase5](Images/worst-case-5.png) 7. After inserting the rest of the values the tree will look like this: ![WorstCase6](Images/worst-case-6.png) If we keep insert number following the same sequence, that tree becomes inbalanced and have a height of **n** with **n** being the numbers of values inserted. After getting this tree, a *find(1)* operation for example will take **O(n)** ## ZigZig rotation order: first grandparent But thanks to the properties of the **Splay Tree** and the *ZigZig* rotations after the *find(1)* operation the tree becomes balanced again. This only happens if we respect the order of the *ZigZig* rotation, and the rotation to the grandparent happens first. The sequence of *ZigZigs* rotations will look like follows: 1. Rotate **2** to **3** ![ZigZig1](Images/example-zigzig-1.png) 2. Rotate **1** to **2** ![ZigZig2](Images/example-zigzig-2.png) 3. Rotate **4** to **5** ![ZigZig3](Images/example-zigzig-3.png) 4. Rotate **1** to **4** ![ZigZig4](Images/example-zigzig-4.png) 5. Finally after splaying **1** to the root the tree will look like this: ![ZigZig5](Images/example-zigzig-5.png) Based on the example above, we can see why it's important to rotate first to the grandparent. We got a tree of height = 6, from an initial tree of height = 8. If the tree would had been taller, we would have achieved almost half of the initial height after the splaying operation. ## ZigZig wrong rotation order If the rotations would had been taking first the parent and not the grandparent we would have finished with the following, yet unbalanced tree, just inverting the side of the elements. ![ZigZigWrong](Images/zigzig-wrongrotated.png) ## See also [Splay Tree on Wikipedia](https://en.wikipedia.org/wiki/Splay_tree) [Splay Tree by University of California in Berkeley - CS 61B Lecture 34](https://www.youtube.com/watch?v=8Zs1lj_bUV0) ---------------- *Written for Swift Algorithm Club by Barbara Martina Rodeker* ---------------- ================================================ FILE: Stack/README.markdown ================================================ # Stack > This topic has been tutorialized [here](https://www.raywenderlich.com/149213/swift-algorithm-club-swift-stack-data-structure) A stack is like an array but with limited functionality. You can only *push* to add a new element to the top of the stack, *pop* to remove the element from the top, and *peek* at the top element without popping it off. Why would you want to do this? Well, in many algorithms you want to add objects to a temporary list at some point and then pull them off this list again at a later time. Often the order in which you add and remove these objects matters. A stack gives you a LIFO or last-in first-out order. The element you pushed last is the first one to come off with the next pop. (A very similar data structure, the [queue](../Queue/), is FIFO or first-in first-out.) For example, let's push a number on the stack: ```swift stack.push(10) ``` The stack is now `[ 10 ]`. Push the next number: ```swift stack.push(3) ``` The stack is now `[ 10, 3 ]`. Push one more number: ```swift stack.push(57) ``` The stack is now `[ 10, 3, 57 ]`. Let's pop the top number off the stack: ```swift stack.pop() ``` This returns `57`, because that was the most recent number we pushed. The stack is `[ 10, 3 ]` again. ```swift stack.pop() ``` This returns `3`, and so on. If the stack is empty, popping returns `nil` or in some implementations it gives an error message ("stack underflow"). A stack is easy to create in Swift. It's just a wrapper around an array that just lets you push, pop, and look at the top element of the stack: ```swift public struct Stack { fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func push(_ element: T) { array.append(element) } public mutating func pop() -> T? { return array.popLast() } public var top: T? { return array.last } } ``` Notice that a push puts the new element at the end of the array, not the beginning. Inserting at the beginning of an array is expensive, an **O(n)** operation, because it requires all existing array elements to be shifted in memory. Adding at the end is **O(1)**; it always takes the same amount of time, regardless of the size of the array. Fun fact about stacks: Each time you call a function or a method, the CPU places the return address on a stack. When the function ends, the CPU uses that return address to jump back to the caller. That's why if you call too many functions -- for example in a recursive function that never ends -- you get a so-called "stack overflow" as the CPU stack has run out of space. *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Stack/Stack.playground/Contents.swift ================================================ /** Stack A stack is like an array but with limited functionality. You can only push to add a new element to the top of the stack, pop to remove the element from the top, and peek at the top element without popping it off. A stack gives you a LIFO or last-in first-out order. The element you pushed last is the first one to come off with the next pop. Push and pop are O(1) operations. ## Usage ``` var myStack = Stack(array: []) myStack.push(10) myStack.push(3) myStack.push(57) myStack.pop() // 57 myStack.pop() // 3 ``` */ public struct Stack { /// Datastructure consisting of a generic item. fileprivate var array = [T]() /// The number of items in the stack. public var count: Int { return array.count } /// Verifies if the stack is empty. public var isEmpty: Bool { return array.isEmpty } /** Pushes an item to the top of the stack. - Parameter element: The item being pushed. */ public mutating func push(_ element: T) { array.append(element) } /** Removes and returns the item at the top of the stack. - Returns: The item at the top of the stack. */ public mutating func pop() -> T? { return array.popLast() } /// Returns the item at the top of the stack. public var top: T? { return array.last } } // Create a stack and put some elements on it already. var stackOfNames = Stack(array: ["Carl", "Lisa", "Stephanie", "Jeff", "Wade"]) // Add an element to the top of the stack. stackOfNames.push("Mike") // The stack is now ["Carl", "Lisa", "Stephanie", "Jeff", "Wade", "Mike"] print(stackOfNames.array) // Remove and return the first element from the stack. This returns "Mike". stackOfNames.pop() // Look at the first element from the stack. // Returns "Wade" since "Mike" was popped on the previous line. stackOfNames.top // Check to see if the stack is empty. // Returns "false" since the stack still has elements in it. stackOfNames.isEmpty ================================================ FILE: Stack/Stack.playground/contents.xcplayground ================================================ ================================================ FILE: Stack/Stack.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Stack/Stack.swift ================================================ /* Last-in first-out stack (LIFO) Push and pop are O(1) operations. */ public struct Stack { fileprivate var array = [T]() public var isEmpty: Bool { return array.isEmpty } public var count: Int { return array.count } public mutating func push(_ element: T) { array.append(element) } public mutating func pop() -> T? { return array.popLast() } public var top: T? { return array.last } } extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self return AnyIterator { return curr.pop() } } } ================================================ FILE: Stack/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Stack/Tests/StackTests.swift ================================================ import Foundation import XCTest class StackTest: XCTestCase { func testEmpty() { var stack = Stack() XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } func testOneElement() { var stack = Stack() stack.push(123) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 1) XCTAssertEqual(stack.top, 123) let result = stack.pop() XCTAssertEqual(result, 123) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } func testTwoElements() { var stack = Stack() stack.push(123) stack.push(456) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 2) XCTAssertEqual(stack.top, 456) let result1 = stack.pop() XCTAssertEqual(result1, 456) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 1) XCTAssertEqual(stack.top, 123) let result2 = stack.pop() XCTAssertEqual(result2, 123) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } func testMakeEmpty() { var stack = Stack() stack.push(123) stack.push(456) XCTAssertNotNil(stack.pop()) XCTAssertNotNil(stack.pop()) XCTAssertNil(stack.pop()) stack.push(789) XCTAssertEqual(stack.count, 1) XCTAssertEqual(stack.top, 789) let result = stack.pop() XCTAssertEqual(result, 789) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } } ================================================ FILE: Stack/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B80C4061C77A70A003CECC7 /* Stack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4051C77A70A003CECC7 /* Stack.swift */; }; 7B80C4081C77A711003CECC7 /* StackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C4071C77A711003CECC7 /* StackTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B80C4051C77A70A003CECC7 /* Stack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Stack.swift; path = ../Stack.swift; sourceTree = SOURCE_ROOT; }; 7B80C4071C77A711003CECC7 /* StackTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B80C4051C77A70A003CECC7 /* Stack.swift */, 7B80C4071C77A711003CECC7 /* StackTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B80C4081C77A711003CECC7 /* StackTests.swift in Sources */, 7B80C4061C77A70A003CECC7 /* Stack.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Strassen Matrix Multiplication/README.markdown ================================================ # Strassen Matrix Multiplication ## Goal + To quickly perform a matrix multiplication operation on two matricies ## What is Matrix Multiplication?? > Note: If you are already familiar with Linear Algebra/Matrix Multiplication, feel free to skip this section Before we begin, you may ask what is matrix multiplication? Great question! It is **NOT** multiplying two matricies term-by-term. Matrix multiplication is a mathematical operation that combines two matricies into a single one. Sounds like multiplying term-by-term huh? It's not... our lives would be much easier if it were. To see how matrix multiplcation works, let's look at an example. ### Example: Matrix Multiplication ``` matrix A = |1 2|, matrix B = |5 6| |3 4| |7 8| A * B = C |1 2| * |5 6| = |1*5+2*7 1*6+2*8| = |19 22| |3 4| |7 8| |3*5+4*7 3*6+4*8| |43 50| ``` What's going on here? To start, we're multiplying matricies A & B. Our new matrix, C's, elements `[i, j]` are determined by the dot product of the first matrix's ith row and the second matrix's jth column. See [here](https://www.khanacademy.org/math/linear-algebra/vectors-and-spaces/dot-cross-products/v/vector-dot-product-and-vector-length) for a refresher on the dot product. So the upper left element `[i=1, j=1]` of our new matrix is a combination of A's 1st row and B's 1st column. A's first row = [1, 2] B's first column = [5, 7] [1, 2] dot [5, 7] = [1*5 + 2*7] = [19] = C[1, 1] Now let's try this for `[i=1, j=2]`. Because `i=1` and `j=2`, this will represent the upper right element in our new matrix, C. A's first row = [1, 2] B's second column = [6, 8] [1, 2] dot [6, 8] = [1*6 + 2*8] = [22] = C[1, 2] If we do this for each row & column of A & B we'll get our result matrix C! Here's a great graphic that visually shows you what's going on. ![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Matrix_multiplication_principle.svg/1024px-Matrix_multiplication_principle.svg.png) [Source](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Matrix_multiplication_principle.svg/1024px-Matrix_multiplication_principle.svg.png) ## Matix Multiplication Algorithm So how do we implement matrix multiplication in an algoirthm? We'll start with the basic version and from there move on to Strassen's Algorithm. + [Basic Version](#basic-version) + [Strassen's Algorithm](#strassens-algorithm) ### Basic Version Remember the method we used to solve matrix multiplication [above](#what-is-matrix-multiplication??)? Let's try to implement that first! We first assert that the two matricies are the right size. `assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R")` > **NOTE:** A's # of columns HAS to equal B's # of rows for matrix multiplication to work Next, we loop over A's columns and B's rows. Because we know both A's columns & B's rows are the same length, we set that length equal to `n`. ```swift for i in 0..) -> Matrix { let A = self assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") let n = A.columns var C = Matrix(rows: A.rows, columns: B.columns) for i in 0..) -> Matrix { let A = self assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") let n = max(A.rows, A.columns, B.rows, B.columns) let m = nextPowerOfTwo(after: n) var APrep = Matrix(size: m) var BPrep = Matrix(size: m) A.forEach { (i, j) in APrep[i,j] = A[i,j] } B.forEach { (i, j) in BPrep[i,j] = B[i,j] } let CPrep = APrep.strassenR(by: BPrep) var C = Matrix(rows: A.rows, columns: B.columns) for i in 0..) -> Matrix { let A = self assert(A.isSquare && B.isSquare, "This function requires square matricies!") guard A.rows > 1 && B.rows > 1 else { return A * B } let n = A.rows let nBy2 = n / 2 /* Assume submatricies are allocated as follows matrix A = |a b|, matrix B = |e f| |c d| |g h| */ var a = Matrix(size: nBy2) var b = Matrix(size: nBy2) var c = Matrix(size: nBy2) var d = Matrix(size: nBy2) var e = Matrix(size: nBy2) var f = Matrix(size: nBy2) var g = Matrix(size: nBy2) var h = Matrix(size: nBy2) for i in 0.. Int { return Int(pow(2, ceil(log2(Double(n))))) } } ``` ## Appendix ### Number Protocol I use a number protocol to enable by Matrix to be generic. The Number protocol ensures three things: 1. Everything that is a number can be multiplied 2. Everything that is a number can be added/subtracted 3. Everything that is a number has a zero value Extending `Int`, `Float`, and `Double` to conform to this protocol is now very straightforward. All you need to do is implement the `static var zero`! ```swift public protocol Number: Multipliable, Addable { static var zero: Self { get } } public protocol Addable { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self } public protocol Multipliable { static func *(lhs: Self, rhs: Self) -> Self } ``` ### Dot Product I extend `Array` to include a dot product function for when the Array's element conform to the `Number` protocol. ```swift extension Array where Element: Number { public func dot(_ b: Array) -> Element { let a = self assert(a.count == b.count, "Can only take the dot product of arrays of the same length!") let c = a.indices.map{ a[$0] * b[$0] } return c.reduce(Element.zero, { $0 + $1 }) } } ``` ## Resources + [Intro to Matrix Multiplication | Khan Academy](https://www.khanacademy.org/math/precalculus/precalc-matrices/multiplying-matrices-by-matrices/v/matrix-multiplication-intro) + [Matrix Multiplication | Wikipedia](https://en.wikipedia.org/wiki/Matrix_multiplication) + [Strassen Algorithm | Wikipedia](https://en.wikipedia.org/wiki/Strassen_algorithm) + [Strassen Algorithm | Wolfram MathWorld](http://mathworld.wolfram.com/StrassenFormulas.html) + [Strassens Algorithm | Geeks for Geeks](http://www.geeksforgeeks.org/strassens-matrix-multiplication/) *Written for Swift Algorithm Club by Richard Ash* ================================================ FILE: Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Foundation var A = Matrix(rows: 2, columns: 4, initialValue: 0) A[.row, 0] = [2, 3, -1, 0] A[.row, 1] = [-7, 2, 1, 10] var B = Matrix(rows: 4, columns: 2, initialValue: 0) print(B) B[.column, 0] = [3, 2, -1, 2] B[.column, 1] = [4, 1, 2, 7] let C = A.matrixMultiply(by: B) let D = A.strassenMatrixMultiply(by: B) let E = B.matrixMultiply(by: A) let F = B.strassenMatrixMultiply(by: A) print(C) print(D) print(E) print(F) ================================================ FILE: Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift ================================================ // // Matrix.swift // // // Created by Richard Ash on 10/28/16. // // import Foundation public struct Matrix { // MARK: - Martix Objects public enum Index { case row, column } public struct Size: Equatable { let rows: Int, columns: Int public static func == (lhs: Size, rhs: Size) -> Bool { return lhs.columns == rhs.columns && lhs.rows == rhs.rows } } // MARK: - Variables let rows: Int, columns: Int let size: Size var grid: [T] var isSquare: Bool { return rows == columns } // MARK: - Init public init(rows: Int, columns: Int, initialValue: T = T.zero) { self.rows = rows self.columns = columns self.size = Size(rows: rows, columns: columns) self.grid = Array(repeating: initialValue, count: rows * columns) } public init(size: Int, initialValue: T = T.zero) { self.init(rows: size, columns: size, initialValue: initialValue) } // MARK: - Private Functions fileprivate func indexIsValid(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } // MARK: - Subscript public subscript(row: Int, column: Int) -> T { get { assert(indexIsValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] } set { assert(indexIsValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } public subscript(type: Matrix.Index, value: Int) -> [T] { get { switch type { case .row: assert(indexIsValid(row: value, column: 0), "Index out of range") return Array(grid[(value * columns)..<(value * columns) + columns]) case .column: assert(indexIsValid(row: 0, column: value), "Index out of range") let column = (0.. T in let currentColumnIndex = currentRow * columns + value return grid[currentColumnIndex] } return column } } set { switch type { case .row: assert(newValue.count == columns) for (column, element) in newValue.enumerated() { grid[(value * columns) + column] = element } case .column: assert(newValue.count == rows) for (row, element) in newValue.enumerated() { grid[(row * columns) + value] = element } } } } // MARK: - Public Functions public func row(for columnIndex: Int) -> [T] { assert(indexIsValid(row: columnIndex, column: 0), "Index out of range") return Array(grid[(columnIndex * columns)..<(columnIndex * columns) + columns]) } public func column(for rowIndex: Int) -> [T] { assert(indexIsValid(row: 0, column: rowIndex), "Index out of range") let column = (0.. T in let currentColumnIndex = currentRow * columns + rowIndex return grid[currentColumnIndex] } return column } public func forEach(_ body: (Int, Int) throws -> Void) rethrows { for row in 0..) -> Matrix { let A = self assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") var C = Matrix(rows: A.rows, columns: B.columns) for i in 0..) -> Matrix { let A = self assert(A.columns == B.rows, "Two matricies can only be matrix mulitiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R") let n = max(A.rows, A.columns, B.rows, B.columns) let m = nextPowerOfTwo(after: n) var APrep = Matrix(size: m) var BPrep = Matrix(size: m) A.forEach { (i, j) in APrep[i, j] = A[i, j] } B.forEach { (i, j) in BPrep[i, j] = B[i, j] } let CPrep = APrep.strassenR(by: BPrep) var C = Matrix(rows: A.rows, columns: B.columns) for i in 0..) -> Matrix { let A = self assert(A.isSquare && B.isSquare, "This function requires square matricies!") guard A.rows > 1 && B.rows > 1 else { return A * B } let n = A.rows let nBy2 = n / 2 /* Assume submatricies are allocated as follows matrix A = |a b|, matrix B = |e f| |c d| |g h| */ var a = Matrix(size: nBy2) var b = Matrix(size: nBy2) var c = Matrix(size: nBy2) var d = Matrix(size: nBy2) var e = Matrix(size: nBy2) var f = Matrix(size: nBy2) var g = Matrix(size: nBy2) var h = Matrix(size: nBy2) for i in 0.. Int { return Int(pow(2, ceil(log2(Double(n))))) } } // Term-by-term Matrix Math extension Matrix: Addable { public static func +(lhs: Matrix, rhs: Matrix) -> Matrix { assert(lhs.size == rhs.size, "To term-by-term add matricies they need to be the same size!") let rows = lhs.rows let columns = lhs.columns var newMatrix = Matrix(rows: rows, columns: columns) for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { assert(lhs.size == rhs.size, "To term-by-term subtract matricies they need to be the same size!") let rows = lhs.rows let columns = lhs.columns var newMatrix = Matrix(rows: rows, columns: columns) for row in 0..(lhs: Matrix, rhs: Matrix) -> Matrix { assert(lhs.size == rhs.size, "To term-by-term multiply matricies they need to be the same size!") let rows = lhs.rows let columns = lhs.columns var newMatrix = Matrix(rows: rows, columns: columns) for row in 0.. Self static func - (lhs: Self, rhs: Self) -> Self } public protocol Multipliable { static func * (lhs: Self, rhs: Self) -> Self } extension Int: Number { public static var zero: Int { return 0 } } extension Double: Number { public static var zero: Double { return 0.0 } } extension Float: Number { public static var zero: Float { return 0.0 } } extension Array where Element: Number { public func dot(_ b: Array) -> Element { let a = self assert(a.count == b.count, "Can only take the dot product of arrays of the same length!") let c = a.indices.map { a[$0] * b[$0] } return c.reduce(Element.zero, { $0 + $1 }) } } ================================================ FILE: Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/contents.xcplayground ================================================ ================================================ FILE: Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Ternary Search Tree/README.markdown ================================================ # Ternary Search Tree Data structure and simple test in playground has been implemented. Documentation and examples coming soon!! :) ================================================ FILE: Ternary Search Tree/TST.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play import Cocoa import Foundation // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif let treeOfStrings = TernarySearchTree() var testStrings: [(key: String, data: String)] = [] let testCount = 30 for _ in (1...testCount) { let randomLength = Int(arc4random_uniform(10)) let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) let data = Utils.shared.randomAlphaNumericString(withLength: randomLength) // print("Key: \(key) Data: \(data)") if key != "" && data != "" { testStrings.append((key, data)) treeOfStrings.insert(data: data, withKey: key) } } for aTest in testStrings { let data = treeOfStrings.find(key: aTest.key) if data == nil { print("TEST FAILED. Key: \(aTest.key) Data: \(aTest.data)") } if data != aTest.data { print("TEST FAILED. Key: \(aTest.key) Data: \(aTest.data)") } } var testNums: [(key: String, data: Int)] = [] let treeOfInts = TernarySearchTree() for _ in (1...testCount) { let randomNum = Int(arc4random_uniform(UInt32.max)) let randomLength = Int(arc4random_uniform(10)) let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) if key != "" { testNums.append((key, randomNum)) treeOfInts.insert(data: randomNum, withKey: key) } } for aTest in testNums { let data = treeOfInts.find(key: aTest.key) if data == nil { print("TEST FAILED. Key: \(aTest.key) Data: \(aTest.data)") } if data != aTest.data { print("TEST FAILED. Key: \(aTest.key) Data: \(aTest.data)") } } ================================================ FILE: Ternary Search Tree/TST.playground/Sources/TSTNode.swift ================================================ // // TSTNode.swift // // // Created by Siddharth Atre on 3/15/16. // // import Foundation class TSTNode { //Member properties of a particular node. var key: Character var data: Element? var hasData: Bool //Children var left: TSTNode?, right: TSTNode?, middle: TSTNode? init(key: Character, data: Element?) { self.key = key self.data = data self.hasData = (data != nil) } init(key: Character) { self.key = key self.data = nil self.hasData = false } } ================================================ FILE: Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift ================================================ // // TernarySearchTree.swift // // // Created by Siddharth Atre on 3/15/16. // // import Foundation public class TernarySearchTree { var root: TSTNode? public init() {} // MARK: - Insertion public func insert(data: Element, withKey key: String) -> Bool { return insert(node: &root, withData: data, andKey: key, atIndex: 0) } private func insert(node: inout TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { //sanity check. if key.characters.count == 0 { return false } //create a new node if necessary. if node == nil { let index = key.index(key.startIndex, offsetBy: charIndex) node = TSTNode(key: key[index]) } //if current char is less than the current node's char, go left let index = key.index(key.startIndex, offsetBy: charIndex) if key[index] < node!.key { return insert(node: &node!.left, withData: data, andKey: key, atIndex: charIndex) } //if it's greater, go right. else if key[index] > node!.key { return insert(node: &node!.right, withData: data, andKey: key, atIndex: charIndex) } //current char is equal to the current nodes, go middle else { //continue down the middle. if charIndex + 1 < key.characters.count { return insert(node: &node!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } //otherwise, all done. else { node!.data = data node?.hasData = true return true } } } // MARK: - Finding public func find(key: String) -> Element? { return find(node: root, withKey: key, atIndex: 0) } private func find(node: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { //Given key does not exist in tree. if node == nil { return nil } let index = key.index(key.startIndex, offsetBy: charIndex) //go left if key[index] < node!.key { return find(node: node!.left, withKey: key, atIndex: charIndex) } //go right else if key[index] > node!.key { return find(node: node!.right, withKey: key, atIndex: charIndex) } //go middle else { if charIndex + 1 < key.characters.count { return find(node: node!.middle, withKey: key, atIndex: charIndex + 1) } else { return node!.data } } } } ================================================ FILE: Ternary Search Tree/TST.playground/Sources/Utils.swift ================================================ // // Utils.swift // // // Created by Peter Bødskov on 10/01/17. // // import Foundation public struct Utils { public static let shared = Utils() let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" //Random string generator from: //http://stackoverflow.com/questions/26845307/generate-random-alphanumeric-string-in-swift/26845710 public func randomAlphaNumericString(withLength length: Int) -> String { let allowedCharsCount = UInt32(allowedChars.characters.count) var randomString = "" for _ in (0.. ================================================ FILE: Ternary Search Tree/TST.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Ternary Search Tree/TSTNode.swift ================================================ // // TSTNode.swift // // // Created by Siddharth Atre on 3/15/16. // // import Foundation /** This class represents a node in the Ternary Search Tree. A node has two main data members, the key and the data. All nodes in a TST must have keys, but only some will have data. This can be seen in the way the data variable is of Optional type. */ class TSTNode { //Member properties of a particular node. /// The key that identifies this node. var key: Character /// The data stored in this node. May be `nil` var data: Element? /// Boolean flag to depict whether this node holds data or not. var hasData: Bool /// The children of this node var left: TSTNode?, right: TSTNode?, middle: TSTNode? /** Initializer for key and/or data - parameter key: The key to set for this node. - parameter data: The optional data to set in this node. */ init(key: Character, data: Element?) { self.key = key self.data = data self.hasData = (data != nil) } /** Make a node that only has a key - parameter key: The key to ascribe to this node. */ init(key: Character) { self.key = key self.data = nil self.hasData = false } } ================================================ FILE: Ternary Search Tree/TernarySearchTree.swift ================================================ // // TernarySearchTree.swift // // // Created by Siddharth Atre on 3/15/16. // // import Foundation /** The Ternary Search Tree (TST) Data structure. Data structure uses key-value mappings. Keys are strings used to map to any data element. See README for more information. */ public class TernarySearchTree { /// A reference to the root node of this TST var root: TSTNode? /** Standard initializer */ public init() {} // MARK: - Insertion /** Public insertion method. - parameter data: The value to store in this TST. - parameter key: The key to associate with this value. - returns: Value indicating insertion success/failure. */ @discardableResult public func insert(data: Element, withKey key: String) -> Bool { return insert(node: &root, withData: data, andKey: key, atIndex: 0) } /** Helper method for insertion that does the actual legwork. Insertion is performed recursively. - parameter node: The current node to insert below. - parameter data: The data being inserted. - parameter key: The key being used to find an insertion location for the given data - parameter charIndex: The index of the character in the key string to use to for the next node. - returns: Value indicating insertion success/failure. */ private func insert(node: inout TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { //sanity check. guard key.characters.count > 0 else { return false } //create a new node if necessary. if node == nil { let index = key.index(key.startIndex, offsetBy: charIndex) node = TSTNode(key: key[index]) } //if current char is less than the current node's char, go left let index = key.index(key.startIndex, offsetBy: charIndex) if key[index] < node!.key { return insert(node: &node!.left, withData: data, andKey: key, atIndex: charIndex) } //if it's greater, go right. else if key[index] > node!.key { return insert(node: &node!.right, withData: data, andKey: key, atIndex: charIndex) } //current char is equal to the current nodes, go middle else { //continue down the middle. if charIndex + 1 < key.characters.count { return insert(node: &node!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } //otherwise, all done. else { node!.data = data node?.hasData = true return true } } } // MARK: - Finding /** Public find method. - parameter key: Search for an object associated with this key. - returns: The element, if found. Otherwise, nil. */ public func find(key: String) -> Element? { return find(node: root, withKey: key, atIndex: 0) } /** Helper method that performs actual legwork of find operation. Implemented recursively. - parameter node: The current node being evaluated. - parameter key: The key being used for the search. - parameter charIndex: The index of the current char in the search key - returns: The element, if found. Nil otherwise. */ private func find(node: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { //Given key does not exist in tree. guard let node = node else { return nil } let index = key.index(key.startIndex, offsetBy: charIndex) //go left if key[index] < node.key { return find(node: node.left, withKey: key, atIndex: charIndex) } //go right else if key[index] > node.key { return find(node: node.right, withKey: key, atIndex: charIndex) } //go middle else { if charIndex + 1 < key.characters.count { return find(node: node.middle, withKey: key, atIndex: charIndex + 1) } else { return node.data } } } } ================================================ FILE: Ternary Search Tree/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Ternary Search Tree/Tests/TernarySearchTreeTests.swift ================================================ // // Tests.swift // Tests // // Created by Peter Bødskov on 10/01/17. // Copyright © 2017 Swift Algorithm Club. All rights reserved. // import XCTest class TernarySearchTreeTests: XCTestCase { let testCount = 30 func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testCanFindStringInTree() { var testStrings: [(key: String, data: String)] = [] let treeOfStrings = TernarySearchTree() for _ in (1...testCount) { var randomLength = Int(arc4random_uniform(10)) var key = Utils.shared.randomAlphaNumericString(withLength: randomLength) while testStrings.contains(where: { $0.key == key}) { //That key is taken, so we generate a new one with another length randomLength = Int(arc4random_uniform(10)) key = Utils.shared.randomAlphaNumericString(withLength: randomLength) } let data = Utils.shared.randomAlphaNumericString(withLength: randomLength) // print("Key: \(key) Data: \(data)") if key != "" && data != "" { testStrings.append((key, data)) treeOfStrings.insert(data: data, withKey: key) } } for aTest in testStrings { let data = treeOfStrings.find(key: aTest.key) XCTAssertNotNil(data) XCTAssertEqual(data, aTest.data) } } func testCanFindNumberInTree() { var testNums: [(key: String, data: Int)] = [] let treeOfInts = TernarySearchTree() for _ in (1...testCount) { let randomNum = Int(arc4random_uniform(UInt32.max)) var randomLength = Int(arc4random_uniform(10)) var key = Utils.shared.randomAlphaNumericString(withLength: randomLength) while testNums.contains(where: { $0.key == key}) { //That key is taken, so we generate a new one with another length randomLength = Int(arc4random_uniform(10)) key = Utils.shared.randomAlphaNumericString(withLength: randomLength) } if key != "" { testNums.append((key, randomNum)) treeOfInts.insert(data: randomNum, withKey: key) } } for aTest in testNums { let data = treeOfInts.find(key: aTest.key) XCTAssertNotNil(data) XCTAssertEqual(data, aTest.data) } } } ================================================ FILE: Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ D06C22031E24D02800622925 /* TernarySearchTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06C22021E24D02800622925 /* TernarySearchTreeTests.swift */; }; D0957B8A1E24D92D00417988 /* TernarySearchTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0957B891E24D92D00417988 /* TernarySearchTree.swift */; }; D0957B8C1E24D9A300417988 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0957B8B1E24D9A300417988 /* Utils.swift */; }; D0957B8E1E24DA0100417988 /* TSTNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0957B8D1E24DA0100417988 /* TSTNode.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ D06C22021E24D02800622925 /* TernarySearchTreeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TernarySearchTreeTests.swift; sourceTree = ""; }; D06C22041E24D02800622925 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D06C22081E24D16800622925 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D0957B891E24D92D00417988 /* TernarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TernarySearchTree.swift; path = ../TernarySearchTree.swift; sourceTree = ""; }; D0957B8B1E24D9A300417988 /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Utils.swift; path = ../Utils.swift; sourceTree = ""; }; D0957B8D1E24DA0100417988 /* TSTNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TSTNode.swift; path = ../TSTNode.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ D06C21FD1E24D02800622925 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ D06C21B61E24CC9600622925 = { isa = PBXGroup; children = ( D0957B891E24D92D00417988 /* TernarySearchTree.swift */, D0957B8B1E24D9A300417988 /* Utils.swift */, D06C22021E24D02800622925 /* TernarySearchTreeTests.swift */, D0957B8D1E24DA0100417988 /* TSTNode.swift */, D06C22041E24D02800622925 /* Info.plist */, D06C22081E24D16800622925 /* Tests.xctest */, ); sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ D06C21FF1E24D02800622925 /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = D06C22051E24D02800622925 /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( D06C21FC1E24D02800622925 /* Sources */, D06C21FD1E24D02800622925 /* Frameworks */, D06C21FE1E24D02800622925 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = Tests; productReference = D06C22081E24D16800622925 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ D06C21B71E24CC9600622925 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0810; LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { D06C21FF1E24D02800622925 = { CreatedOnToolsVersion = 8.1; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = D06C21BA1E24CC9600622925 /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = D06C21B61E24CC9600622925; productRefGroup = D06C21B61E24CC9600622925; projectDirPath = ""; projectRoot = ""; targets = ( D06C21FF1E24D02800622925 /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ D06C21FE1E24D02800622925 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ D06C21FC1E24D02800622925 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( D06C22031E24D02800622925 /* TernarySearchTreeTests.swift in Sources */, D0957B8E1E24DA0100417988 /* TSTNode.swift in Sources */, D0957B8A1E24D92D00417988 /* TernarySearchTree.swift in Sources */, D0957B8C1E24D9A300417988 /* Utils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ D06C21C31E24CC9600622925 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; D06C21C41E24CC9600622925 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; }; name = Release; }; D06C22061E24D02800622925 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; }; name = Debug; }; D06C22071E24D02800622925 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ D06C21BA1E24CC9600622925 /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( D06C21C31E24CC9600622925 /* Debug */, D06C21C41E24CC9600622925 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; D06C22051E24D02800622925 /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( D06C22061E24D02800622925 /* Debug */, D06C22071E24D02800622925 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = D06C21B71E24CC9600622925 /* Project object */; } ================================================ FILE: Ternary Search Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Ternary Search Tree/Utils.swift ================================================ // // Utils.swift // // // Created by Peter Bødskov on 10/01/17. // // import Foundation public struct Utils { public static let shared = Utils() let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" //Random string generator from: //http://stackoverflow.com/questions/26845307/generate-random-alphanumeric-string-in-swift/26845710 public func randomAlphaNumericString(withLength length: Int) -> String { let allowedCharsCount = UInt32(allowedChars.characters.count) var randomString = "" for _ in (0.. For more information about in-order traversals [see here](../Binary%20Tree/). ## Predecessors and successors An in-order traversal of a tree yields a linear ordering of the nodes. Thus each node has both a **predecessor** and a **successor** (except for the first and last nodes, which only have a successor or a predecessor respectively). In a threaded binary tree, each left child that would normally be `nil` instead stores the node's predecessor (if it exists), and each right child that would normally be `nil` instead stores the node's successor (if it exists). This is what separates threaded binary trees from standard binary trees. There are two types of threaded binary trees: **single threaded** and **double threaded**: - A single threaded tree keeps track of **either** the in-order predecessor **or** successor (left **or** right). - A double threaded tree keeps track of **both** the in-order predecessor **and** successor (left **and** right). Using a single or double threaded tree depends on what we want to accomplish. If we only need to traverse the tree in one direction (either forward or backward), then we use a single threaded tree. If we want to traverse in both directions, then we use a double threaded tree. It is important to note that each node stores either its predecessor or its left child, and either its successor or its right child. The nodes do not need to keep track of both. For example, in a double threaded tree, if a node has a right child but no left child, it will track its predecessor in place of its left child. Here is an example valid "full" threaded binary tree: ![Full](Images/Full.png) While the following threaded binary tree is not "full," it is still valid. The structure of the tree does not matter as long as it follows the definition of a binary search tree: ![Partial](Images/Partial.png) The solid lines denote the links between parents and children, while the dotted lines denote the "threads." It is important to note how the children and thread edges interact with each other. Every node besides the root has one entering edge (from its parent), and two leaving edges: one to the left and one to the right. The left leaving edge goes to the node's left child if it exists, and to its in-order predecessor if it does not. The right leaving edge goes to the node's right child if it exists, and to its in-order successor if it does not. The exceptions are the left-most node and the right-most node, which do not have a predecessor or successor, respectively. ## Representation Before we go into detail about the methods of a threaded binary tree, we should first explain how the tree itself is represented. The core of this data structure is the `ThreadedBinaryTree` class. Each instance of this class represents a node with six member variables: `value`, `parent`, `left`, `right`, `leftThread`, and `rightThread`. Of all of these, only `value` is required. The other five are Swift *optionals* (they may be `nil`). - `value: T` is the value of this node (e.g. 1, 2, A, B, etc.) - `parent: ThreadedBinaryTree?` is the parent of this node - `left: ThreadedBinaryTree?` is the left child of this node - `right: ThreadedBinaryTree?` is the right child of this node - `leftThread: ThreadedBinaryTree?` is the in-order predecessor of this node - `rightThread: ThreadedBinaryTree?` is the in-order successor of this node As we are storing both `leftThread` and `rightThread`, this is a double threaded tree. Now we are ready to go over some of the member functions in our `ThreadedBinaryTree` class. ## Traversal algorithm Let's start with the main reason we're using a threaded binary tree. It is now very easy to find the in-order predecessor and the in-order successor of any node in the tree. If the node has no `left`/`right` child, we can simply return the node's `leftThread`/`rightThread`. Otherwise, it is trivial to move down the tree and find the correct node. ```swift func predecessor() -> ThreadedBinaryTree? { if let left = left { return left.maximum() } else { return leftThread } } func successor() -> ThreadedBinaryTree? { if let right = right { return right.minimum() } else { return rightThread } } ``` > Note: `maximum()` and `minimum()` are methods of `ThreadedBinaryTree` which return the largest/smallest node in a given sub-tree. See [the implementation](ThreadedBinaryTree.swift) for more detail. Because these are `ThreadedBinaryTree` methods, we can call `node.predecessor()` or `node.successor()` to obtain the predecessor or successor of any `node`, provided that `node` is a `ThreadedBinaryTree` object. Because predecessors and/or successors are tracked, an in-order traversal of a threaded binary tree is much more efficient than the recursive algorithm outlined above. We use these predecessor/successor attributes to great effect in this new algorithm for both forward and backward traversals: ```swift public func traverseInOrderForward(_ visit: (T) -> Void) { var n: ThreadedBinaryTree n = minimum() while true { visit(n.value) if let successor = n.successor() { n = successor } else { break } } } public func traverseInOrderBackward(_ visit: (T) -> Void) { var n: ThreadedBinaryTree n = maximum() while true { visit(n.value) if let predecessor = n.predecessor() { n = predecessor } else { break } } } ``` Again, this a method of `ThreadedBinaryTree`, so we'd call it via `node.traverseInorderForward(visitFunction)`. Note that we are able to specify a function that executes on each node as they are visited. This function can be anything you want, as long as it accepts `T` (the type of the values of the nodes of the tree) and has no return value. Let's walk through a forward traversal of a tree by hand to get a better idea of how a computer would do it. For example, take this simple threaded tree: ![Base](Images/Base.png) We start at the root of the tree, **9**. Note that we don't `visit(9)` yet. From there we want to go to the `minimum()` node in the tree, which is **2** in this case. We then `visit(2)` and see that it has a `rightThread`, and thus we immediately know what its `successor()` is. We follow the thread to **5**, which does not have any leaving threads. Therefore, after we `visit(5)`, we go to the `minimum()` node in its `right` subtree, which is **7**. We then `visit(7)` and see that it has a `rightThread`, which we follow to get back to **9**. *Now* we `visit(9)`, and after noticing that it has no `rightThread`, we go to the `minimum()` node in its `right` subtree, which is **12**. This node has a `rightThread` that leads to `nil`, which signals that we have completed the traversal! We visited the nodes in order **2, 5, 7, 9, 12**, which intuitively makes sense, as that is their natural increasing order. A backward traversal would be very similar, but you would replace `right`, `rightThread`, `minimum()`, and `successor()` with `left`, `leftThread`, `maximum()`, and `predecessor()`. ## Insertion and deletion The quick in-order traversal that a threaded binary trees gives us comes at a small cost. Inserting/deleting nodes becomes more complicated, as we have to continuously manage the `leftThread` and `rightThread` variables. Rather than walking through some boring code, it is best to explain this with an example (although you can read through [the implementation](ThreadedBinaryTree.swift) if you want to know the finer details). Please note that this requires knowledge of binary search trees, so make sure you have [read this first](../Binary%20Search%20Tree/). > Note: we do allow duplicate nodes in this implementation of a threaded binary > tree. We break ties by defaulting insertion to the right. Let's start with the same tree that we used for the above traversal example: ![Base](Images/Base.png) Suppose we insert **10** into this tree. The resulting graph would look like this, with the changes highlighted in red: ![Insert1](Images/Insert1.png) If you've done your homework and are familiar with binary search trees, the placement of this node should not surprise you. What's new is how we maintain the threads between nodes. So we know that we want to insert **10** as **12**'s `left` child. The first thing we do is set **12**'s `left` child to **10**, and set **10**'s `parent` to **12**. Because **10** is being inserted on the `left`, and **10** has no children of its own, we can safely set **10**'s `rightThread` to its `parent` **12**. What about **10**'s `leftThread`? Because we know that **10** < **12**, and **10** is the only `left` child of **12**, we can safely set **10**'s `leftThread` to **12**'s (now outdated) `leftThread`. Finally we set **12**'s `leftThread = nil`, as it now has a `left` child. Let's now insert another node, **4**, into the tree: ![Insert2](Images/Insert2.png) While we are inserting **4** as a `right` child, it follows the exact same process as above, but mirrored (swap `left` and `right`). For the sake of completeness, we'll insert one final node, **15**: ![Insert3](Images/Insert3.png) Now that we have a fairly crowded tree, let's try removing some nodes. Compared to insertion, deletion is a little more complicated. Let's start with something simple, like removing **7**, which has no children: ![Remove1](Images/Remove1.png) Before we can just throw **7** away, we have to perform some clean-up. In this case, because **7** is a `right` child and has no children itself, we can simply set the `rightThread` of **7**'s `parent`(**5**) to **7**'s (now outdated) `rightThread`. Then we can just set **7**'s `parent`, `left`, `right`, `leftThread`, and `rightThread` to `nil`, effectively removing it from the tree. We also set the parent's `rightChild` to `nil`, which completes the deletion of this right child. Let's try something a little harder. Say we remove **5** from the tree: ![Remove2](Images/Remove2.png) This is a little trickier, as **5** has some children that we have to deal with. The core idea is to replace **5** with its first child, **2**. To accomplish this, we of course set **2**'s `parent` to **9** and set **9**'s `left` child to **2**. Note that **4**'s `rightThread` used to be **5**, but we are removing **5**, so it needs to change. It is now important to understand two important properties of threaded binary trees: 1. For the rightmost node **m** in the `left` subtree of any node **n**, **m**'s `rightThread` is **n**. 2. For the leftmost node **m** in the `right` subtree of any node **n**, **m**'s `leftThread` is **n**. Note how these properties held true before the removal of **5**, as **4** was the rightmost node in **5**'s `left` subtree. In order to maintain this property, we must set **4**'s `rightThread` to **9**, as **4** is now the rightmost node in **9**'s `left` subtree. To completely remove **5**, all we now have to do is set **5**'s `parent`, `left`, `right`, `leftThread`, and `rightThread` to `nil`. How about we do something crazy? What would happen if we tried to remove **9**, the root node? This is the resulting tree: ![Remove3](Images/Remove3.png) Whenever we want to remove a node that has two children, we take a slightly different approach than the above examples. The basic idea is to replace the node that we want to remove with the leftmost node in its `right` subtree, which we call the replacement node. > Note: we could also replace the node with the rightmost node in its `left` > subtree. Choosing left or right is mostly an arbitrary decision. Once we find the replacement node, **10** in this case, we remove it from the tree using the algorithms outlined above. This ensures that the edges in the `right` subtree remain correct. From there it is easy to replace **9** with **10**, as we just have to update the edges leaving **10**. Now all we have to do is fiddle with the threads in order to maintain the two properties outlined above. In this case, **12**'s `leftThread` is now **10**. Node **9** is no longer needed, so we can finish the removal process by setting all of its variables to `nil`. In order to illustrate how to remove a node that has only a `right` child, we'll remove one final node, **12** from the tree: ![Remove4](Images/Remove4.png) The process to remove **12** is identical to the process we used to remove **5**, but mirrored. **5** had a `left` child, while **12** has a `right` child, but the core algorithm is the same. And that's it! This was just a quick overview of how insertion and deletion work in threaded binary trees, but if you understood these examples, you should be able to insert or remove any node from any tree you want. More detail can of course be found in [the implementation](ThreadedBinaryTree.swift). ## Miscellaneous methods There are many other smaller operations that a threaded binary tree can do, such as `searching()` for a node in the tree, finding the `depth()` or `height()` of a node, etc. You can check [the implementation](ThreadedBinaryTree.swift) for the full technical details. Many of these methods are inherent to binary search trees as well, so you can find [further documentation here](../Binary%20Search%20Tree/). ## See also [Threaded Binary Tree on Wikipedia](https://en.wikipedia.org/wiki/Threaded_binary_tree) *Written for the Swift Algorithm Club by [Jayson Tung](https://github.com/JFTung)* *Migrated to Swift 3 by Jaap Wijnen* *Images made using www.draw.io* ================================================ FILE: Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // Simple little debug function to make testing output pretty func check(_ tree: ThreadedBinaryTree?) { if let tree = tree { print("\(tree.count) Total Nodes:") print(tree) print("Debug Info:") print(tree.debugDescription) print("In-Order Traversal:") let myArray = tree.toArray() for node in myArray { print(node) } if tree.isBST(minValue: Int.min, maxValue: Int.max) { print("This is a VALID binary search tree.") } else { print("This is an INVALID binary search tree.") } if tree.isThreaded() { print("This is a VALID threaded binary tree.") } else { print("This is an INVALID threaded binary tree.") } } else { print("This tree is nil.") } } print("\nTree with Single Node") let emptyTree = ThreadedBinaryTree(value: 1) check(emptyTree) print("\nFull Balanced Binary Tree with 7 Nodes") let fullTree = ThreadedBinaryTree(value: 4) fullTree.insert(2) fullTree.insert(1) fullTree.insert(6) fullTree.insert(5) fullTree.insert(3) fullTree.insert(7) check(fullTree) print("\n\nBase Binary Tree with 5 Nodes") let tree = ThreadedBinaryTree(array: [9, 5, 12, 2, 7]) check(tree) print("\nInsert 10") tree.insert(10) check(tree) print("\nInsert 4") tree.insert(4) check(tree) print("\nInsert 15") tree.insert(15) check(tree) print("\nRemove 13 (Not in the Tree)") tree.remove(13) check(tree) print("\nRemove 7") tree.remove(7) check(tree) print("\nRemove 5") tree.remove(5) check(tree) print("\nRemove 9 (root)") let newRoot = tree.remove(9) check(newRoot) print("\nRemove 12") newRoot?.remove(12) check(newRoot) print("\n\nDone with Tests!\n") ================================================ FILE: Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift ================================================ /* A Threaded Binary Tree. Based on this club's Binary Search Tree implementation. Each node stores a value and two children. The left child contains a smaller value; the right a larger (or equal) value. Any nodes that lack either a left or right child instead keep track of their in-order predecessor and/or successor. This tree allows duplicate elements (we break ties by defaulting right). This tree does not automatically balance itself. To make sure it is balanced, you should insert new values in randomized order, not in sorted order. */ public class ThreadedBinaryTree { fileprivate(set) public var value: T fileprivate(set) public var parent: ThreadedBinaryTree? fileprivate(set) public var left: ThreadedBinaryTree? fileprivate(set) public var right: ThreadedBinaryTree? fileprivate(set) public var leftThread: ThreadedBinaryTree? fileprivate(set) public var rightThread: ThreadedBinaryTree? public init(value: T) { self.value = value } public convenience init(array: [T]) { precondition(array.count > 0) self.init(value: array.first!) for v in array.dropFirst() { insert(v, parent: self) } } public var isRoot: Bool { return parent == nil } public var isLeaf: Bool { return left == nil && right == nil } public var isLeftChild: Bool { return parent?.left === self } public var isRightChild: Bool { return parent?.right === self } public var hasLeftChild: Bool { return left != nil } public var hasRightChild: Bool { return right != nil } public var hasAnyChild: Bool { return hasLeftChild || hasRightChild } public var hasBothChildren: Bool { return hasLeftChild && hasRightChild } /* How many nodes are in this subtree. Performance: O(n). */ public var count: Int { return (left?.count ?? 0) + 1 + (right?.count ?? 0) } } // MARK: - Adding items extension ThreadedBinaryTree { /* Inserts a new element into the tree. You should only insert elements at the root, to make to sure this remains a valid binary tree! Performance: runs in O(h) time, where h is the height of the tree. */ public func insert(_ value: T) { insert(value, parent: self) } fileprivate func insert(_ value: T, parent: ThreadedBinaryTree) { if value < self.value { if let left = left { left.insert(value, parent: left) } else { left = ThreadedBinaryTree(value: value) left?.parent = parent left?.rightThread = parent left?.leftThread = leftThread leftThread = nil } } else { if let right = right { right.insert(value, parent: right) } else { right = ThreadedBinaryTree(value: value) right?.parent = parent right?.leftThread = parent right?.rightThread = rightThread rightThread = nil } } } } // MARK: - Deleting items extension ThreadedBinaryTree { /* Deletes the "highest" node with the specified value. Returns the node that has replaced this removed one (or nil if this was a leaf node). That is primarily useful for when you delete the root node, in which case the tree gets a new root. Performance: runs in O(h) time, where h is the height of the tree. */ @discardableResult public func remove(_ value: T) -> ThreadedBinaryTree? { return search(value)?.remove() } /* Deletes "this" node from the tree. */ public func remove() -> ThreadedBinaryTree? { let replacement: ThreadedBinaryTree? if let left = left { if let right = right { replacement = removeNodeWithTwoChildren(left, right) replacement?.leftThread = leftThread replacement?.rightThread = rightThread left.maximum().rightThread = replacement right.minimum().leftThread = replacement } else { // This node only has a left child. The left child replaces the node. replacement = left left.maximum().rightThread = rightThread } } else if let right = right { // This node only has a right child. The right child replaces the node. replacement = right right.minimum().leftThread = leftThread } else { // This node has no children. We just disconnect it from its parent. replacement = nil if isLeftChild { parent?.leftThread = leftThread } else { parent?.rightThread = rightThread } } reconnectParentToNode(replacement) // The current node is no longer part of the tree, so clean it up. parent = nil left = nil right = nil leftThread = nil rightThread = nil return replacement } private func removeNodeWithTwoChildren(_ left: ThreadedBinaryTree, _ right: ThreadedBinaryTree) -> ThreadedBinaryTree { // This node has two children. It must be replaced by the smallest // child that is larger than this node's value, which is the leftmost // descendent of the right child. let successor = right.minimum() // If this in-order successor has a right child of its own (it cannot // have a left child by definition), then that must take its place. _ = successor.remove() // Connect our left child with the new node. successor.left = left left.parent = successor // Connect our right child with the new node. If the right child does // not have any left children of its own, then the in-order successor // *is* the right child. if right !== successor { successor.right = right right.parent = successor } else { successor.right = nil } // And finally, connect the successor node to our parent. return successor } private func reconnectParentToNode(_ node: ThreadedBinaryTree?) { if let parent = parent { if isLeftChild { parent.left = node } else { parent.right = node } } node?.parent = parent } } // MARK: - Searching extension ThreadedBinaryTree { /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ public func search(_ value: T) -> ThreadedBinaryTree? { var node: ThreadedBinaryTree? = self while let n = node { if value < n.value { node = n.left } else if value > n.value { node = n.right } else { return node } } return nil } /* // Recursive version of search // Educational but undesirable due to the overhead cost of recursion public func search(value: T) -> ThreadedBinaryTree? { if value < self.value { return left?.search(value) } else if value > self.value { return right?.search(value) } else { return self } } */ public func contains(value: T) -> Bool { return search(value) != nil } /* Returns the leftmost descendent. O(h) time. */ public func minimum() -> ThreadedBinaryTree { var node = self while let next = node.left { node = next } return node } /* Returns the rightmost descendent. O(h) time. */ public func maximum() -> ThreadedBinaryTree { var node = self while let next = node.right { node = next } return node } /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. */ public func depth() -> Int { var node = self var edges = 0 while let parent = node.parent { node = parent edges += 1 } return edges } /* Calculates the height of this node, i.e. the distance to the lowest leaf. Since this looks at all children of this node, performance is O(n). */ public func height() -> Int { if isLeaf { return 0 } else { return 1 + max(left?.height() ?? 0, right?.height() ?? 0) } } /* Finds the node whose value precedes our value in sorted order. */ public func predecessor() -> ThreadedBinaryTree? { if let left = left { return left.maximum() } else { return leftThread } } /* Finds the node whose value succeeds our value in sorted order. */ public func successor() -> ThreadedBinaryTree? { if let right = right { return right.minimum() } else { return rightThread } } } // MARK: - Traversal extension ThreadedBinaryTree { public func traverseInOrderForward(_ visit: (T) -> Void) { var n: ThreadedBinaryTree n = minimum() while true { visit(n.value) if let successor = n.successor() { n = successor } else { break } } } public func traverseInOrderBackward(_ visit: (T) -> Void) { var n: ThreadedBinaryTree n = maximum() while true { visit(n.value) if let predecessor = n.predecessor() { n = predecessor } else { break } } } public func traversePreOrder(_ visit: (T) -> Void) { visit(value) left?.traversePreOrder(visit) right?.traversePreOrder(visit) } public func traversePostOrder(_ visit: (T) -> Void) { left?.traversePostOrder(visit) right?.traversePostOrder(visit) visit(value) } /* Performs an in-order traversal and collects the results in an array. */ public func map(formula: (T) -> T) -> [T] { var a = [T]() var n: ThreadedBinaryTree n = minimum() while true { a.append(formula(n.value)) if let successor = n.successor() { n = successor } else { break } } return a } } // MARK: - Verification extension ThreadedBinaryTree { /* Is this threaded binary tree a valid binary search tree? */ public func isBST(minValue: T, maxValue: T) -> Bool { if value < minValue || value > maxValue { return false } let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true return leftBST && rightBST } /* Is this binary tree properly threaded? Either left or leftThread (but not both) must be nil (likewise for right). The first and last nodes in the in-order traversal are exempt from this, as the first has leftThread = nil, and the last has rightThread = nil. */ public func isThreaded() -> Bool { if left == nil && leftThread == nil { if self !== minimum() { return false } } if left != nil && leftThread != nil { return false } if right == nil && rightThread == nil { if self !== maximum() { return false } } if right != nil && rightThread != nil { return false } let leftThreaded = left?.isThreaded() ?? true let rightThreaded = right?.isThreaded() ?? true return leftThreaded && rightThreaded } } // MARK: - Debugging extension ThreadedBinaryTree: CustomStringConvertible { public var description: String { var s = "" if let left = left { s += "(\(left.description)) <- " } s += "\(value)" if let right = right { s += " -> (\(right.description))" } return s } } extension ThreadedBinaryTree: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(value)" if let parent = parent { s += ", parent: \(parent.value)" } if let leftThread = leftThread { s += ", leftThread: \(leftThread.value)" } if let rightThread = rightThread { s += ", rightThread: \(rightThread.value)" } if let left = left { s += ", left = [" + left.debugDescription + "]" } if let right = right { s += ", right = [" + right.debugDescription + "]" } return s } public func toArray() -> [T] { return map { $0 } } } ================================================ FILE: Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground ================================================ ================================================ FILE: Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Topological Sort/Graph.swift ================================================ public class Graph: CustomStringConvertible { public typealias Node = String private(set) public var adjacencyLists: [Node : [Node]] public init() { adjacencyLists = [Node: [Node]]() } public func addNode(_ value: Node) -> Node { adjacencyLists[value] = [] return value } public func addEdge(fromNode from: Node, toNode to: Node) -> Bool { adjacencyLists[from]?.append(to) return adjacencyLists[from] != nil ? true : false } public var description: String { return adjacencyLists.description } public func adjacencyList(forNode node: Node) -> [Node]? { for (key, adjacencyList) in adjacencyLists { if key == node { return adjacencyList } } return nil } } extension Graph { typealias InDegree = Int func calculateInDegreeOfNodes() -> [Node : InDegree] { var inDegrees = [Node: InDegree]() for (node, _) in adjacencyLists { inDegrees[node] = 0 } for (_, adjacencyList) in adjacencyLists { for nodeInList in adjacencyList { inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 } } return inDegrees } } ================================================ FILE: Topological Sort/README.markdown ================================================ # Topological Sort Topological sort is an algorithm that orders a directed graph such that for each directed edge *u→v*, vertex *u* comes before vertex *v*. In other words, a topological sort places the vertices of a [directed acyclic graph](../Graph/) on a line so that all directed edges go from left to right. Consider the graph in the following example: ![Example](Images/Graph.png) This graph has two possible topological sorts: ![Example](Images/TopologicalSort.png) The topological orderings are **S, V, W, T, X** and **S, W, V, T, X**. Notice how the arrows all go from left to right. The following is not a valid topological sort for this graph, since **X** and **T** cannot happen before **V**: ![Example](Images/InvalidSort.png) ## Where is this used? Let's consider that you want to learn all the algorithms and data structures from the Swift Algorithm Club. This might seem daunting at first but we can use topological sort to get things organized. Since you're learning about topological sort, let's take this topic as an example. What else do you need to learn first before you can fully understand topological sort? Well, topological sort uses [depth-first search](../Depth-First%20Search/) as well as a [stack](../Stack/). But before you can learn about the depth-first search algorithm, you need to know what a [graph](../Graph/) is, and it helps to know what a [tree](../Tree/) is. In turn, graphs and trees use the idea of linking objects together, so you may need to read up on that first. And so on... If we were to represent these objectives in the form of a graph it would look as follows: ![Example](Images/Algorithms.png) If we consider each algorithm to be a vertex in the graph you can clearly see the dependencies between them. To learn something you might have to know something else first. This is exactly what topological sort is used for -- it will sort things out so that you know what to do first. ## How does it work? **Step 1: Find all vertices that have in-degree of 0** The *in-degree* of a vertex is the number of edges pointing at that vertex. Vertices with no incoming edges have an in-degree of 0. These vertices are the starting points for the topological sort. In the context of the previous example, these starting vertices represent algorithms and data structures that don't have any prerequisites; you don't need to learn anything else first, hence the sort starts with them. **Step 2: Traverse the graph with depth-first search** Depth-first search is an algorithm that starts traversing the graph from a certain vertex and explores as far as possible along each branch before backtracking. To find out more about depth-first search, please take a look at the [detailed explanation](../Depth-First%20Search/). We perform a depth-first search on each vertex with in-degree 0. This tells us which vertices are connected to each of these starting vertices. **Step 3: Remember all visited vertices** As we perform the depth-first search, we maintain a list of all the vertices that have been visited. This is to avoid visiting the same vertex twice. **Step 4: Put it all together** The last step of the sort is to combine the results of the different depth-first searches and put the vertices in a sorted list. ## Example Consider the following graph: ![Graph Example](Images/Example.png) **Step 1:** The vertices with 0 in-degree are: **3, 7, 5**. These are our starting vertices. **Step 2:** Perform depth-first search for each starting vertex, without remembering vertices that have already been visited: ``` Vertex 3: 3, 10, 8, 9 Vertex 7: 7, 11, 2, 8, 9 Vertex 5: 5, 11, 2, 9, 10 ``` **Step 3:** Filter out the vertices already visited in each previous search: ``` Vertex 3: 3, 10, 8, 9 Vertex 7: 7, 11, 2 Vertex 5: 5 ``` **Step 4:** Combine the results of these three depth-first searches. The final sorted order is **5, 7, 11, 2, 3, 10, 8, 9**. (Important: we need to add the results of each subsequent search to the *front* of the sorted list.) The result of the topological sort looks like this: ![Result of the sort](Images/GraphResult.png) > **Note:** This is not the only possible topological sort for this graph. For example, other valid solutions are **3, 7, 5, 10, 8, 11, 9, 2** and **3, 7, 5, 8, 11, 2, 9, 10**. Any order where all the arrows are going from left to right will do. ## The code Here is how you could implement topological sort in Swift (see also [TopologicalSort1.swift](TopologicalSort1.swift)): ```swift extension Graph { public func topologicalSort() -> [Node] { // 1 let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 }).map({ node, indegree in return node }) // 2 var visited = [Node : Bool]() for (node, _) in adjacencyLists { visited[node] = false } // 3 var result = [Node]() for startNode in startNodes { result = depthFirstSearch(startNode, visited: &visited) + result } // 4 return result } } ``` Some remarks: 1. Find the in-degree of each vertex and put all the vertices with in-degree 0 in the `startNodes` array. In this graph implementation, vertices are called "nodes". Both terms are used interchangeably by people who write graph code. 2. The `visited` array keeps track of whether we've already seen a vertex during the depth-first search. Initially, we set all elements to `false`. 3. For each of the vertices in the `startNodes` array, perform a depth-first search. This returns an array of sorted `Node` objects. We prepend that array to our own `result` array. 4. The `result` array contains all the vertices in topologically sorted order. > **Note:** For a slightly different implementation of topological sort using depth-first search, see [TopologicalSort3.swift](TopologicalSort3.swift). This uses a stack and does not require you to find all vertices with in-degree 0 first. ## Kahn's algorithm Even though depth-first search is the typical way to perform a topological sort, there is another algorithm that also does the job. 1. Find out what the in-degree is of every vertex. 2. Put all the vertices that have no predecessors in a new array called `leaders`. These vertices have in-degree 0 and therefore do not depend on any other vertices. 3. Go through this list of leaders and remove them one-by-one from the graph. We don't actually modify the graph, we just decrement the in-degree of the vertices they point to. That has the same effect. 4. Look at the (former) immediate neighbor vertices of each leader. If any of them now have an in-degree of 0, then they no longer have any predecessors themselves. We'll add those vertices to the `leaders` array too. 5. This repeats until there are no more vertices left to look at. At this point, the `leaders` array contains all the vertices in sorted order. This is an **O(n + m)** algorithm where **n** is the number of vertices and **m** is the number of edges. You can see the implementation in [TopologicalSort2.swift](TopologicalSort2.swift). Source: I first read about this alternative algorithm in the Algorithm Alley column in Dr. Dobb's Magazine from May 1993. *Written for Swift Algorithm Club by Ali Hafizji and Matthijs Hollemans* ================================================ FILE: Topological Sort/Tests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Topological Sort/Tests/Tests.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7B3471BB1C8F50CF008381CD /* TopologicalSortTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */; }; 7B3471BF1C8F50DD008381CD /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BC1C8F50DD008381CD /* Graph.swift */; }; 7B3471C11C8F50DD008381CD /* TopologicalSort1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */; }; 7B3471C31C8F5348008381CD /* TopologicalSort2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */; }; 7BE143491C9C6A93001BC747 /* TopologicalSort3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BE143481C9C6A93001BC747 /* TopologicalSort3.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7B2BBC801C779D720067B71D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 7B2BBC941C779E7B0067B71D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopologicalSortTests.swift; sourceTree = SOURCE_ROOT; }; 7B3471BC1C8F50DD008381CD /* Graph.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graph.swift; path = ../Graph.swift; sourceTree = SOURCE_ROOT; }; 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopologicalSort1.swift; path = ../TopologicalSort1.swift; sourceTree = SOURCE_ROOT; }; 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopologicalSort2.swift; path = ../TopologicalSort2.swift; sourceTree = SOURCE_ROOT; }; 7BE143481C9C6A93001BC747 /* TopologicalSort3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TopologicalSort3.swift; path = ../TopologicalSort3.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7B2BBC7D1C779D720067B71D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7B2BBC681C779D710067B71D = { isa = PBXGroup; children = ( 7B2BBC831C779D720067B71D /* Tests */, 7B2BBC721C779D710067B71D /* Products */, ); sourceTree = ""; }; 7B2BBC721C779D710067B71D /* Products */ = { isa = PBXGroup; children = ( 7B2BBC801C779D720067B71D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( 7B3471BC1C8F50DD008381CD /* Graph.swift */, 7B3471BE1C8F50DD008381CD /* TopologicalSort1.swift */, 7B3471C21C8F5348008381CD /* TopologicalSort2.swift */, 7BE143481C9C6A93001BC747 /* TopologicalSort3.swift */, 7B3471BA1C8F50CF008381CD /* TopologicalSortTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); name = Tests; path = TestsTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7B2BBC7F1C779D720067B71D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( 7B2BBC7C1C779D720067B71D /* Sources */, 7B2BBC7D1C779D720067B71D /* Frameworks */, 7B2BBC7E1C779D720067B71D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TestsTests; productReference = 7B2BBC801C779D720067B71D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7B2BBC691C779D710067B71D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7B2BBC681C779D710067B71D; productRefGroup = 7B2BBC721C779D710067B71D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7B2BBC7F1C779D720067B71D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 7B2BBC7E1C779D720067B71D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 7B2BBC7C1C779D720067B71D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7B3471C31C8F5348008381CD /* TopologicalSort2.swift in Sources */, 7B3471BF1C8F50DD008381CD /* Graph.swift in Sources */, 7B3471BB1C8F50CF008381CD /* TopologicalSortTests.swift in Sources */, 7B3471C11C8F50DD008381CD /* TopologicalSort1.swift in Sources */, 7BE143491C9C6A93001BC747 /* TopologicalSort3.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7B2BBC871C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 7B2BBC881C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; 7B2BBC8D1C779D720067B71D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Debug; }; 7B2BBC8E1C779D720067B71D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7B2BBC6C1C779D710067B71D /* Build configuration list for PBXProject "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC871C779D720067B71D /* Debug */, 7B2BBC881C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7B2BBC8C1C779D720067B71D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 7B2BBC8D1C779D720067B71D /* Debug */, 7B2BBC8E1C779D720067B71D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7B2BBC691C779D710067B71D /* Project object */; } ================================================ FILE: Topological Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Topological Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Topological Sort/Tests/TopologicalSortTests.swift ================================================ import Foundation import XCTest extension Graph { public func loadEdgeList(_ lines: [String]) { for line in lines { let items = line.components(separatedBy: " ").filter { s in !s.isEmpty } if adjacencyList(forNode: items[0]) == nil { addNode(items[0]) } if adjacencyList(forNode: items[1]) == nil { addNode(items[1]) } addEdge(fromNode: items[0], toNode: items[1]) } } } class TopologicalSort: XCTestCase { // The topological sort is valid if a node does not have any of its // predecessors in its adjacency list. func checkIsValidTopologicalSort(_ graph: Graph, _ a: [Graph.Node]) { for i in stride(from: (a.count - 1), to: 0, by: -1) { if let neighbors = graph.adjacencyList(forNode: a[i]) { for j in stride(from: (i - 1), through: 0, by: -1) { XCTAssertFalse(neighbors.contains(a[j]), "\(a) is not a valid topological sort") } } } } func testTopologicalSort() { let graph = Graph() let node5 = graph.addNode("5") let node7 = graph.addNode("7") let node3 = graph.addNode("3") let node11 = graph.addNode("11") let node8 = graph.addNode("8") let node2 = graph.addNode("2") let node9 = graph.addNode("9") let node10 = graph.addNode("10") graph.addEdge(fromNode: node5, toNode: node11) graph.addEdge(fromNode: node7, toNode: node11) graph.addEdge(fromNode: node7, toNode: node8) graph.addEdge(fromNode: node3, toNode: node8) graph.addEdge(fromNode: node3, toNode: node10) graph.addEdge(fromNode: node11, toNode: node2) graph.addEdge(fromNode: node11, toNode: node9) graph.addEdge(fromNode: node11, toNode: node10) graph.addEdge(fromNode: node8, toNode: node9) XCTAssertEqual(graph.topologicalSort(), ["5", "7", "11", "2", "3", "10", "8", "9"]) XCTAssertEqual(graph.topologicalSortKahn(), ["3", "7", "5", "8", "11", "2", "9", "10"]) XCTAssertEqual(graph.topologicalSortAlternative(), ["5", "7", "3", "8", "11", "10", "9", "2"]) } func testTopologicalSortEdgeLists() { let p1 = ["A B", "A C", "B C", "B D", "C E", "C F", "E D", "F E", "G A", "G F"] let p2 = ["B C", "C D", "C G", "B F", "D G", "G E", "F G", "F G"] let p3 = ["S V", "S W", "V T", "W T"] let p4 = ["5 11", "7 11", "7 8", "3 8", "3 10", "11 2", "11 9", "11 10", "8 9"] let data = [ p1, p2, p3, p4 ] for d in data { let graph = Graph() graph.loadEdgeList(d) let sorted1 = graph.topologicalSort() checkIsValidTopologicalSort(graph, sorted1) let sorted2 = graph.topologicalSortKahn() checkIsValidTopologicalSort(graph, sorted2) let sorted3 = graph.topologicalSortAlternative() checkIsValidTopologicalSort(graph, sorted3) } } } ================================================ FILE: Topological Sort/Topological Sort.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif import UIKit let graph = Graph() let node5 = graph.addNode("5") let node7 = graph.addNode("7") let node3 = graph.addNode("3") let node11 = graph.addNode("11") let node8 = graph.addNode("8") let node2 = graph.addNode("2") let node9 = graph.addNode("9") let node10 = graph.addNode("10") graph.addEdge(fromNode: node5, toNode: node11) graph.addEdge(fromNode: node7, toNode: node11) graph.addEdge(fromNode: node7, toNode: node8) graph.addEdge(fromNode: node3, toNode: node8) graph.addEdge(fromNode: node3, toNode: node10) graph.addEdge(fromNode: node11, toNode: node2) graph.addEdge(fromNode: node11, toNode: node9) graph.addEdge(fromNode: node11, toNode: node10) graph.addEdge(fromNode: node8, toNode: node9) // using depth-first search graph.topologicalSort() // also using depth-first search graph.topologicalSortAlternative() // Kahn's algorithm graph.topologicalSortKahn() ================================================ FILE: Topological Sort/Topological Sort.playground/Sources/Graph.swift ================================================ public class Graph: CustomStringConvertible { public typealias Node = String private(set) public var adjacencyLists: [Node : [Node]] public init() { adjacencyLists = [Node: [Node]]() } public func addNode(_ value: Node) -> Node { adjacencyLists[value] = [] return value } public func addEdge(fromNode from: Node, toNode to: Node) -> Bool { adjacencyLists[from]?.append(to) return adjacencyLists[from] != nil ? true : false } public var description: String { return adjacencyLists.description } public func adjacencyList(forNode node: Node) -> [Node]? { for (key, adjacencyList) in adjacencyLists { if key == node { return adjacencyList } } return nil } } extension Graph { typealias InDegree = Int func calculateInDegreeOfNodes() -> [Node : InDegree] { var inDegrees = [Node: InDegree]() for (node, _) in adjacencyLists { inDegrees[node] = 0 } for (_, adjacencyList) in adjacencyLists { for nodeInList in adjacencyList { inDegrees[nodeInList] = (inDegrees[nodeInList] ?? 0) + 1 } } return inDegrees } } ================================================ FILE: Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift ================================================ extension Graph { private func depthFirstSearch(_ source: Node, visited: inout [Node : Bool]) -> [Node] { var result = [Node]() if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { if let seen = visited[nodeInAdjacencyList], !seen { result = depthFirstSearch(nodeInAdjacencyList, visited: &visited) + result } } } visited[source] = true return [source] + result } /* Topological sort using depth-first search. */ public func topologicalSort() -> [Node] { let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 }).map({ node, _ in return node }) var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false } var result = [Node]() for startNode in startNodes { result = depthFirstSearch(startNode, visited: &visited) + result } return result } } ================================================ FILE: Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift ================================================ extension Graph { /* Topological sort using Kahn's algorithm. */ public func topologicalSortKahn() -> [Node] { var nodes = calculateInDegreeOfNodes() // Find vertices with no predecessors and puts them into a new list. // These are the "leaders". The leaders array eventually becomes the // topologically sorted list. var leaders = nodes.filter({ _, indegree in return indegree == 0 }).map({ node, _ in return node }) // "Remove" each of the leaders. We do this by decrementing the in-degree // of the nodes they point to. As soon as such a node has itself no more // predecessors, it is added to the leaders array. This repeats until there // are no more vertices left. var l = 0 while l < leaders.count { if let edges = adjacencyList(forNode: leaders[l]) { for neighbor in edges { if let count = nodes[neighbor] { nodes[neighbor] = count - 1 if count == 1 { // this leader was the last predecessor leaders.append(neighbor) // so neighbor is now a leader itself } } } } l += 1 } // Was there a cycle in the graph? if leaders.count != nodes.count { print("Error: graphs with cycles are not allowed") } return leaders } } ================================================ FILE: Topological Sort/Topological Sort.playground/Sources/TopologicalSort3.swift ================================================ /* An alternative implementation of topological sort using depth-first search. This does not start at vertices with in-degree 0 but simply at the first one it finds. It uses a stack to build up the sorted list, but in reverse order. */ extension Graph { public func topologicalSortAlternative() -> [Node] { var stack = [Node]() var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false } func depthFirstSearch(_ source: Node) { if let adjacencyList = adjacencyList(forNode: source) { for neighbor in adjacencyList { if let seen = visited[neighbor], !seen { depthFirstSearch(neighbor) } } } stack.append(source) visited[source] = true } for (node, _) in visited { if let seen = visited[node], !seen { depthFirstSearch(node) } } return stack.reversed() } } ================================================ FILE: Topological Sort/Topological Sort.playground/contents.xcplayground ================================================ ================================================ FILE: Topological Sort/Topological Sort.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Topological Sort/TopologicalSort1.swift ================================================ extension Graph { private func depthFirstSearch(_ source: Node, visited: inout [Node : Bool]) -> [Node] { var result = [Node]() visited[source] = true if let adjacencyList = adjacencyList(forNode: source) { for nodeInAdjacencyList in adjacencyList { if let seen = visited[nodeInAdjacencyList], !seen { result = depthFirstSearch(nodeInAdjacencyList, visited: &visited) + result } } } return [source] + result } /* Topological sort using depth-first search. */ public func topologicalSort() -> [Node] { let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 }).map({ node, _ in return node }) var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false } var result = [Node]() for startNode in startNodes { result = depthFirstSearch(startNode, visited: &visited) + result } return result } } ================================================ FILE: Topological Sort/TopologicalSort2.swift ================================================ extension Graph { /* Topological sort using Kahn's algorithm. */ public func topologicalSortKahn() -> [Node] { var nodes = calculateInDegreeOfNodes() // Find vertices with no predecessors and puts them into a new list. // These are the "leaders". The leaders array eventually becomes the // topologically sorted list. var leaders = nodes.filter({ _, indegree in return indegree == 0 }).map({ node, _ in return node }) // "Remove" each of the leaders. We do this by decrementing the in-degree // of the nodes they point to. As soon as such a node has itself no more // predecessors, it is added to the leaders array. This repeats until there // are no more vertices left. var l = 0 while l < leaders.count { if let edges = adjacencyList(forNode: leaders[l]) { for neighbor in edges { if let count = nodes[neighbor] { nodes[neighbor] = count - 1 if count == 1 { // this leader was the last predecessor leaders.append(neighbor) // so neighbor is now a leader itself } } } } l += 1 } // Was there a cycle in the graph? if leaders.count != nodes.count { print("Error: graphs with cycles are not allowed") } return leaders } } ================================================ FILE: Topological Sort/TopologicalSort3.swift ================================================ /* An alternative implementation of topological sort using depth-first search. This does not start at vertices with in-degree 0 but simply at the first one it finds. It uses a stack to build up the sorted list, but in reverse order. */ extension Graph { public func topologicalSortAlternative() -> [Node] { var stack = [Node]() var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false } func depthFirstSearch(_ source: Node) { if let adjacencyList = adjacencyList(forNode: source) { for neighbor in adjacencyList { if let seen = visited[neighbor], !seen { depthFirstSearch(neighbor) } } } stack.append(source) visited[source] = true } for (node, _) in visited { if let seen = visited[node], !seen { depthFirstSearch(node) } } return stack.reversed() } } ================================================ FILE: Treap/Treap/Treap/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright Copyright © 2016 WillowTree, Inc. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication ================================================ FILE: Treap/Treap/Treap.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 750439C01DA9924E0045C660 /* Treap.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE11C7670350023AF4D /* Treap.swift */; }; 750439C11DA992510045C660 /* TreapMergeSplit.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */; }; 750439C21DA992530045C660 /* TreapCollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */; }; E1E34DD71C7670250023AF4D /* TreapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E34DD61C7670250023AF4D /* TreapTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ E1E34DCD1C7670240023AF4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E1E34DD21C7670250023AF4D /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E1E34DD61C7670250023AF4D /* TreapTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreapTests.swift; sourceTree = ""; }; E1E34DD81C7670250023AF4D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E1E34DE11C7670350023AF4D /* Treap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Treap.swift; path = ../../Treap.swift; sourceTree = ""; }; E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TreapMergeSplit.swift; path = ../../TreapMergeSplit.swift; sourceTree = ""; }; E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TreapCollectionType.swift; path = ../../TreapCollectionType.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ E1E34DCF1C7670250023AF4D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ E1E34DBA1C7670240023AF4D = { isa = PBXGroup; children = ( E1E34DC51C7670240023AF4D /* Treap */, E1E34DD51C7670250023AF4D /* TreapTests */, E1E34DC41C7670240023AF4D /* Products */, ); sourceTree = ""; }; E1E34DC41C7670240023AF4D /* Products */ = { isa = PBXGroup; children = ( E1E34DD21C7670250023AF4D /* Tests.xctest */, ); name = Products; sourceTree = ""; }; E1E34DC51C7670240023AF4D /* Treap */ = { isa = PBXGroup; children = ( E1E34DE11C7670350023AF4D /* Treap.swift */, E1E34DE21C7670350023AF4D /* TreapMergeSplit.swift */, E1E34DE91C7671200023AF4D /* TreapCollectionType.swift */, E1E34DCD1C7670240023AF4D /* Info.plist */, ); path = Treap; sourceTree = ""; }; E1E34DD51C7670250023AF4D /* TreapTests */ = { isa = PBXGroup; children = ( E1E34DD61C7670250023AF4D /* TreapTests.swift */, E1E34DD81C7670250023AF4D /* Info.plist */, ); path = TreapTests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ E1E34DD11C7670250023AF4D /* Tests */ = { isa = PBXNativeTarget; buildConfigurationList = E1E34DDE1C7670250023AF4D /* Build configuration list for PBXNativeTarget "Tests" */; buildPhases = ( E1E34DCE1C7670250023AF4D /* Sources */, E1E34DCF1C7670250023AF4D /* Frameworks */, E1E34DD01C7670250023AF4D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Tests; productName = TreapTests; productReference = E1E34DD21C7670250023AF4D /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ E1E34DBB1C7670240023AF4D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 0800; ORGANIZATIONNAME = "WillowTree, Inc."; TargetAttributes = { E1E34DD11C7670250023AF4D = { CreatedOnToolsVersion = 7.2.1; LastSwiftMigration = 0800; }; }; }; buildConfigurationList = E1E34DBE1C7670240023AF4D /* Build configuration list for PBXProject "Treap" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = E1E34DBA1C7670240023AF4D; productRefGroup = E1E34DC41C7670240023AF4D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( E1E34DD11C7670250023AF4D /* Tests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ E1E34DD01C7670250023AF4D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ E1E34DCE1C7670250023AF4D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 750439C01DA9924E0045C660 /* Treap.swift in Sources */, E1E34DD71C7670250023AF4D /* TreapTests.swift in Sources */, 750439C21DA992530045C660 /* TreapCollectionType.swift in Sources */, 750439C11DA992510045C660 /* TreapMergeSplit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ E1E34DD91C7670250023AF4D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; E1E34DDA1C7670250023AF4D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; E1E34DDF1C7670250023AF4D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = TreapTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.TreapTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Debug; }; E1E34DE01C7670250023AF4D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = TreapTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.willowtree.TreapTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ E1E34DBE1C7670240023AF4D /* Build configuration list for PBXProject "Treap" */ = { isa = XCConfigurationList; buildConfigurations = ( E1E34DD91C7670250023AF4D /* Debug */, E1E34DDA1C7670250023AF4D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; E1E34DDE1C7670250023AF4D /* Build configuration list for PBXNativeTarget "Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( E1E34DDF1C7670250023AF4D /* Debug */, E1E34DE01C7670250023AF4D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = E1E34DBB1C7670240023AF4D /* Project object */; } ================================================ FILE: Treap/Treap/Treap.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Treap/Treap/Treap.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings ================================================ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded ================================================ FILE: Treap/Treap/Treap.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme ================================================ ================================================ FILE: Treap/Treap/TreapTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: Treap/Treap/TreapTests/TreapTests.swift ================================================ // // TreapTests.swift // TreapTests // // Created by Robert Thompson on 2/18/16. // Copyright © 2016 Robert Thompson /* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ // swiftlint:disable force_try import XCTest class TreapTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testSwift4() { // last checked with Xcode 9.0b4 #if swift(>=4.0) print("Hello, Swift 4!") #endif } func testSanity() { var treap = Treap.empty treap = treap.set(key: 5, val: "a").set(key: 7, val: "b") XCTAssert(treap.get(5) == "a") XCTAssert(treap.get(7) == "b") treap = treap.set(key: 2, val: "c") XCTAssert(treap.get(2) == "c") treap = treap.set(key: 2, val: "d") XCTAssert(treap.get(2) == "d") treap = try! treap.delete(key: 5) XCTAssert(!treap.contains(5)) XCTAssert(treap.contains(7)) } func testFairlyBalanced() { var treap = Treap.empty for i in 0..<1000 { treap = treap.set(key: i, val: nil) } let depth = treap.depth XCTAssert(depth < 30, "treap.depth was \(depth)") } func testFairlyBalancedCollection() { var treap = Treap() for i in 0..<1000 { treap[i] = Optional.none } let depth = treap.depth XCTAssert(depth > 0 && depth < 30) } } ================================================ FILE: Treap/Treap.swift ================================================ // // Treap.swift // TreapExample // // Created by Robert Thompson on 7/27/15. // Copyright © 2016 Robert Thompson /* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ import Foundation public indirect enum Treap { case empty case node(key: Key, val: Element, p: Int, left: Treap, right: Treap) public init() { self = .empty } internal func get(_ key: Key) -> Element? { switch self { case .empty: return nil case let .node(treeKey, val, _, _, _) where treeKey == key: return val case let .node(treeKey, _, _, left, _) where key < treeKey: return left.get(key) case let .node(treeKey, _, _, _, right) where key > treeKey: return right.get(key) default: return nil } } public func contains(_ key: Key) -> Bool { switch self { case .empty: return false case let .node(treeKey, _, _, _, _) where treeKey == key: return true case let .node(treeKey, _, _, left, _) where key < treeKey: return left.contains(key) case let .node(treeKey, _, _, _, right) where key > treeKey: return right.contains(key) default: return false } } public var depth: Int { switch self { case .empty: return 0 case let .node(_, _, _, left, .empty): return 1 + left.depth case let .node(_, _, _, .empty, right): return 1 + right.depth case let .node(_, _, _, left, right): let leftDepth = left.depth let rightDepth = right.depth return 1 + leftDepth > rightDepth ? leftDepth : rightDepth } } public var count: Int { return Treap.countHelper(self) } fileprivate static func countHelper(_ treap: Treap) -> Int { if case let .node(_, _, _, left, right) = treap { return countHelper(left) + 1 + countHelper(right) } return 0 } } internal func leftRotate(_ tree: Treap) -> Treap { if case let .node(key, val, p, .node(leftKey, leftVal, leftP, leftLeft, leftRight), right) = tree { return .node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: Treap.node(key: key, val: val, p: p, left: leftRight, right: right)) } else { return .empty } } internal func rightRotate(_ tree: Treap) -> Treap { if case let .node(key, val, p, left, .node(rightKey, rightVal, rightP, rightLeft, rightRight)) = tree { return .node(key: rightKey, val: rightVal, p: rightP, left: Treap.node(key: key, val: val, p: p, left: left, right: rightLeft), right: rightRight) } else { return .empty } } public extension Treap { internal func set(key: Key, val: Element, p: Int = Int(arc4random())) -> Treap { switch self { case .empty: return .node(key: key, val: val, p: p, left: .empty, right: .empty) case let .node(nodeKey, nodeVal, nodeP, left, right) where key != nodeKey: return insertAndBalance(nodeKey, nodeVal, nodeP, left, right, key, val, p) case let .node(nodeKey, _, nodeP, left, right) where key == nodeKey: return .node(key: key, val: val, p: nodeP, left: left, right: right) default: // should never happen return .empty } } fileprivate func insertAndBalance(_ nodeKey: Key, _ nodeVal: Element, _ nodeP: Int, _ left: Treap, _ right: Treap, _ key: Key, _ val: Element, _ p: Int) -> Treap { let newChild: Treap let newNode: Treap let rotate: (Treap) -> Treap if key < nodeKey { newChild = left.set(key: key, val: val, p: p) newNode = .node(key: nodeKey, val: nodeVal, p: nodeP, left: newChild, right: right) rotate = leftRotate } else if key > nodeKey { newChild = right.set(key: key, val: val, p: p) newNode = .node(key: nodeKey, val: nodeVal, p: nodeP, left: left, right: newChild) rotate = rightRotate } else { // It should be impossible to reach here newChild = .empty newNode = .empty return newNode } if case let .node(_, _, newChildP, _, _) = newChild, newChildP < nodeP { return rotate(newNode) } else { return newNode } } internal func delete(key: Key) throws -> Treap { switch self { case .empty: throw NSError(domain: "com.wta.treap.errorDomain", code: -1, userInfo: nil) case let .node(nodeKey, val, p, left, right) where key < nodeKey: return try Treap.node(key: nodeKey, val: val, p: p, left: left.delete(key: key), right: right) case let .node(nodeKey, val, p, left, right) where key > nodeKey: return try Treap.node(key: nodeKey, val: val, p: p, left: left, right: right.delete(key: key)) case let .node(_, _, _, left, right): return merge(left, right: right) } } } ================================================ FILE: Treap/TreapCollectionType.swift ================================================ // // TreapCollectionType.swift // Treap // // Created by Robert Thompson on 2/18/16. // Copyright © 2016 Robert Thompson /* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ import Foundation extension Treap: MutableCollection { public typealias Index = TreapIndex public subscript(index: TreapIndex) -> Element { get { guard let result = self.get(index.keys[index.keyIndex]) else { fatalError("Invalid index!") } return result } mutating set { let key = index.keys[index.keyIndex] self = self.set(key: key, val: newValue) } } public subscript(key: Key) -> Element? { get { return self.get(key) } mutating set { guard let value = newValue else { _ = try? self.delete(key: key) return } self = self.set(key: key, val: value) } } public var startIndex: TreapIndex { return TreapIndex(keys: keys, keyIndex: 0) } public var endIndex: TreapIndex { let keys = self.keys return TreapIndex(keys: keys, keyIndex: keys.count) } public func index(after i: TreapIndex) -> TreapIndex { return i.successor() } fileprivate var keys: [Key] { var results: [Key] = [] if case let .node(key, _, _, left, right) = self { results.append(contentsOf: left.keys) results.append(key) results.append(contentsOf: right.keys) } return results } } public struct TreapIndex: Comparable { public static func < (lhs: TreapIndex, rhs: TreapIndex) -> Bool { return lhs.keyIndex < rhs.keyIndex } fileprivate let keys: [Key] fileprivate let keyIndex: Int public func successor() -> TreapIndex { return TreapIndex(keys: keys, keyIndex: keyIndex + 1) } public func predecessor() -> TreapIndex { return TreapIndex(keys: keys, keyIndex: keyIndex - 1) } fileprivate init(keys: [Key] = [], keyIndex: Int = 0) { self.keys = keys self.keyIndex = keyIndex } } public func ==(lhs: TreapIndex, rhs: TreapIndex) -> Bool { return lhs.keys == rhs.keys && lhs.keyIndex == rhs.keyIndex } ================================================ FILE: Treap/TreapMergeSplit.swift ================================================ // // TreapMergeSplit.swift // TreapExample // // Created by Robert Thompson on 7/27/15. // Copyright © 2016 Robert Thompson /* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ import Foundation public extension Treap { internal func split(_ key: Key) -> (left: Treap, right: Treap) { var current = self let val: Element if let newVal = self.get(key) { // swiftlint:disable force_try current = try! current.delete(key: key) // swiftlint:enable force_try val = newVal } else if case let .node(_, newVal, _, _, _) = self { val = newVal } else { fatalError("No values in treap") } switch self { case .node: if case let .node(_, _, _, left, right) = current.set(key: key, val: val, p: -1) { return (left: left, right: right) } else { return (left: .empty, right: .empty) } default: return (left: .empty, right: .empty) } } internal var leastKey: Key? { switch self { case .empty: return nil case let .node(key, _, _, .empty, _): return key case let .node(_, _, _, left, _): return left.leastKey } } internal var mostKey: Key? { switch self { case .empty: return nil case let .node(key, _, _, _, .empty): return key case let .node(_, _, _, _, right): return right.mostKey } } } internal func merge(_ left: Treap, right: Treap) -> Treap { switch (left, right) { case (.empty, _): return right case (_, .empty): return left case let (.node(leftKey, leftVal, leftP, leftLeft, leftRight), .node(rightKey, rightVal, rightP, rightLeft, rightRight)): if leftP < rightP { return .node(key: leftKey, val: leftVal, p: leftP, left: leftLeft, right: merge(leftRight, right: right)) } else { return .node(key: rightKey, val: rightVal, p: rightP, left: merge(rightLeft, right: left), right: rightRight) } default: break } return .empty } extension Treap: CustomStringConvertible { public var description: String { return Treap.descHelper(self, indent: 0) } fileprivate static func descHelper(_ treap: Treap, indent: Int) -> String { if case let .node(key, value, priority, left, right) = treap { var result = "" let tabs = String(repeating: "\t", count: indent) result += descHelper(left, indent: indent + 1) result += "\n" + tabs + "\(key), \(value), \(priority)\n" result += descHelper(right, indent: indent + 1) return result } else { return "" } } } ================================================ FILE: Tree/README.markdown ================================================ # Trees > This topic has been tutorialized [here](https://www.raywenderlich.com/138190/swift-algorithm-club-swift-tree-data-structure) A tree represents hierarchical relationships between objects. This is a tree: ![A tree](Images/Tree.png) A tree consists of nodes, and these nodes are linked to one another. Nodes have links to their children and usually to their parent as well. The children are the nodes below a given node; the parent is the node above. A node always has just one parent but can have multiple children. ![A tree](Images/ParentChildren.png) A node without a parent is the *root* node. A node without children is a *leaf* node. The pointers in a tree do not form cycles. This is not a tree: ![Not a tree](Images/Cycles.png) Such a structure is called a [graph](../Graph/). A tree is really a very simple form of a graph. (In a similar vein, a [linked list](../Linked%20List/) is a simple version of a tree. Think about it!) This article talks about a general-purpose tree. That's a tree without any kind of restrictions on how many children each node may have, or on the order of the nodes in the tree. Here's a basic implementation in Swift: ```swift public class TreeNode { public var value: T public weak var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { self.value = value } public func addChild(_ node: TreeNode) { children.append(node) node.parent = self } } ``` This describes a single node from the tree. It has a value of generic type `T`, a reference to a `parent` node, and an array of child nodes. It will be useful to add a `description` method so you can print the tree: ```swift extension TreeNode: CustomStringConvertible { public var description: String { var s = "\(value)" if !children.isEmpty { s += " {" + children.map { $0.description }.joined(separator: ", ") + "}" } return s } } ``` To see this in action in a playground: ```swift let tree = TreeNode(value: "beverages") let hotNode = TreeNode(value: "hot") let coldNode = TreeNode(value: "cold") let teaNode = TreeNode(value: "tea") let coffeeNode = TreeNode(value: "coffee") let chocolateNode = TreeNode(value: "cocoa") let blackTeaNode = TreeNode(value: "black") let greenTeaNode = TreeNode(value: "green") let chaiTeaNode = TreeNode(value: "chai") let sodaNode = TreeNode(value: "soda") let milkNode = TreeNode(value: "milk") let gingerAleNode = TreeNode(value: "ginger ale") let bitterLemonNode = TreeNode(value: "bitter lemon") tree.addChild(hotNode) tree.addChild(coldNode) hotNode.addChild(teaNode) hotNode.addChild(coffeeNode) hotNode.addChild(chocolateNode) coldNode.addChild(sodaNode) coldNode.addChild(milkNode) teaNode.addChild(blackTeaNode) teaNode.addChild(greenTeaNode) teaNode.addChild(chaiTeaNode) sodaNode.addChild(gingerAleNode) sodaNode.addChild(bitterLemonNode) ``` If you print out the value of `tree`, you'll get: beverages {hot {tea {black, green, chai}, coffee, cocoa}, cold {soda {ginger ale, bitter lemon}, milk}} That corresponds to the following structure: ![Example tree](Images/Example.png) The `beverages` node is the root because it has no parent. The leaves are `black`, `green`, `chai`, `coffee`, `cocoa`, `ginger ale`, `bitter lemon`, `milk` because they don't have any child nodes. For any node you can look at the `parent` property and work your way back up to the root: ```swift teaNode.parent // this is the "hot" node teaNode.parent!.parent // this is the root ``` We often use the following definitions when talking about trees: - **Height of the tree.** This is the number of links between the root node and the lowest leaf. In our example the height of the tree is 3 because it takes three jumps to go from the root to the bottom. - **Depth of a node.** The number of links between this node and the root node. For example, the depth of `tea` is 2 because it takes two jumps to reach the root. (The root itself has depth 0.) There are many different ways to construct trees. For example, sometimes you don't need to have a `parent` property at all. Or maybe you only need to give each node a maximum of two children -- such a tree is called a [binary tree](../Binary%20Tree/). A very common type of tree is the [binary search tree](../Binary%20Search%20Tree/) (or BST), a stricter version of a binary tree where the nodes are ordered in a particular way to speed up searches. The general purpose tree I've shown here is great for describing hierarchical data, but it really depends on your application what kind of extra functionality it needs to have. Here's an example of how you could use the `TreeNode` class to determine if the tree contains a particular value. You first look at the node's own `value` property. If there's no match, then you look at all your children in turn. Of course, those children are also `TreeNodes` so they will repeat the same process recursively: first look at their own value and then at their children. And their children will also do the same thing again, and so on... Recursion and trees go hand-in-hand. Here's the code: ```swift extension TreeNode where T: Equatable { func search(_ value: T) -> TreeNode? { if value == self.value { return self } for child in children { if let found = child.search(value) { return found } } return nil } } ``` And an example of how to use this: ```swift tree.search("cocoa") // returns the "cocoa" node tree.search("chai") // returns the "chai" node tree.search("bubbly") // nil ``` It's also possible to describe a tree using nothing more than an array. The indices in the array then create the links between the different nodes. For example, if we have: 0 = beverage 5 = cocoa 9 = green 1 = hot 6 = soda 10 = chai 2 = cold 7 = milk 11 = ginger ale 3 = tea 8 = black 12 = bitter lemon 4 = coffee Then we can describe the tree with the following array: [ -1, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 6, 6 ] Each entry in the array is a pointer to its parent node. The item at index 3, `tea`, has the value 1 because its parent is `hot`. The root node points to `-1` because it has no parent. You can only traverse such trees from a node back to the root but not the other way around. By the way, sometimes you see algorithms using the term *forest*. Unsurprisingly, that is the name given to a collection of separate tree objects. For an example of this, see [union-find](../Union-Find/). *Written for Swift Algorithm Club by Matthijs Hollemans* ================================================ FILE: Tree/Tree.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play let tree = TreeNode(value: "beverages") let hotNode = TreeNode(value: "hot") let coldNode = TreeNode(value: "cold") let teaNode = TreeNode(value: "tea") let coffeeNode = TreeNode(value: "coffee") let chocolateNode = TreeNode(value: "cocoa") let blackTeaNode = TreeNode(value: "black") let greenTeaNode = TreeNode(value: "green") let chaiTeaNode = TreeNode(value: "chai") let sodaNode = TreeNode(value: "soda") let milkNode = TreeNode(value: "milk") let gingerAleNode = TreeNode(value: "ginger ale") let bitterLemonNode = TreeNode(value: "bitter lemon") tree.addChild(hotNode) tree.addChild(coldNode) hotNode.addChild(teaNode) hotNode.addChild(coffeeNode) hotNode.addChild(chocolateNode) coldNode.addChild(sodaNode) coldNode.addChild(milkNode) teaNode.addChild(blackTeaNode) teaNode.addChild(greenTeaNode) teaNode.addChild(chaiTeaNode) sodaNode.addChild(gingerAleNode) sodaNode.addChild(bitterLemonNode) tree teaNode.parent teaNode.parent!.parent extension TreeNode where T: Equatable { func search(_ value: T) -> TreeNode? { if value == self.value { return self } for child in children { if let found = child.search(value) { return found } } return nil } } tree.search("cocoa") tree.search("chai") tree.search("bubbly") ================================================ FILE: Tree/Tree.playground/Sources/Tree.swift ================================================ public class TreeNode { public var value: T public weak var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { self.value = value } public func addChild(_ node: TreeNode) { children.append(node) node.parent = self } } extension TreeNode: CustomStringConvertible { public var description: String { var s = "\(value)" if !children.isEmpty { s += " {" + children.map { $0.description }.joined(separator: ", ") + "}" } return s } } extension TreeNode where T: Equatable { public func search(_ value: T) -> TreeNode? { if value == self.value { return self } for child in children { if let found = child.search(value) { return found } } return nil } } ================================================ FILE: Tree/Tree.playground/contents.xcplayground ================================================ ================================================ FILE: Tree/Tree.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Tree/Tree.swift ================================================ public class TreeNode { public var value: T public weak var parent: TreeNode? public var children = [TreeNode]() public init(value: T) { self.value = value } public func addChild(_ node: TreeNode) { children.append(node) node.parent = self } } extension TreeNode: CustomStringConvertible { public var description: String { var s = "\(value)" if !children.isEmpty { s += " {" + children.map { $0.description }.joined(separator: ", ") + "}" } return s } } extension TreeNode where T: Equatable { public func search(_ value: T) -> TreeNode? { if value == self.value { return self } for child in children { if let found = child.search(value) { return found } } return nil } } ================================================ FILE: Trie/ReadMe.md ================================================ # Trie > This topic has been tutorialized [here](https://www.raywenderlich.com/139410/swift-algorithm-club-swift-trie-data-structure) ## What is a Trie? A `Trie`, (also known as a prefix tree, or radix tree in some other implementations) is a special type of tree used to store associative data structures. A `Trie` for a dictionary might look like this: ![A Trie](images/trie.png) Storing the English language is a primary use case for a `Trie`. Each node in the `Trie` would represent a single character of a word. A series of nodes then make up a word. ## Why a Trie? Tries are very useful for certain situations. Here are some of the advantages: * Looking up values typically have a better worst-case time complexity. * Unlike a hash map, a `Trie` does not need to worry about key collisions. * Doesn't utilize hashing to guarantee a unique path to elements. * `Trie` structures can be alphabetically ordered by default. ## Common Algorithms ### Contains (or any general lookup method) `Trie` structures are great for lookup operations. For `Trie` structures that model the English language, finding a particular word is a matter of a few pointer traversals: ```swift func contains(word: String) -> Bool { guard !word.isEmpty else { return false } // 1 var currentNode = root // 2 var characters = Array(word.lowercased()) var currentIndex = 0 // 3 while currentIndex < characters.count, let child = currentNode.children[characters[currentIndex]] { currentNode = child currentIndex += 1 } // 4 if currentIndex == characters.count && currentNode.isTerminating { return true } else { return false } } ``` The `contains` method is fairly straightforward: 1. Create a reference to the `root`. This reference will allow you to walk down a chain of nodes. 2. Keep track of the characters of the word you're trying to match. 3. Walk the pointer down the nodes. 4. `isTerminating` is a boolean flag for whether or not this node is the end of a word. If this `if` condition is satisfied, it means you are able to find the word in the `trie`. ### Insertion Insertion into a `Trie` requires you to walk over the nodes until you either halt on a node that must be marked as `terminating`, or reach a point where you need to add extra nodes. ```swift func insert(word: String) { guard !word.isEmpty else { return } // 1 var currentNode = root // 2 for character in word.lowercased() { // 3 if let childNode = currentNode.children[character] { currentNode = childNode } else { currentNode.add(value: character) currentNode = currentNode.children[character]! } } // Word already present? guard !currentNode.isTerminating else { return } // 4 wordCount += 1 currentNode.isTerminating = true } ``` 1. Once again, you create a reference to the root node. You'll move this reference down a chain of nodes. 2. Begin walking through your word letter by letter 3. Sometimes, the required node to insert already exists. That is the case for two words inside the `Trie` that shares letters (i.e "Apple", "App"). If a letter already exists, you'll reuse it, and simply traverse deeper down the chain. Otherwise, you'll create a new node representing the letter. 4. Once you get to the end, you mark `isTerminating` to true to mark that specific node as the end of a word. ### Removal Removing keys from the trie is a little tricky, as there are a few more cases you'll need to take into account. Nodes in a `Trie` may be shared between different words. Consider the two words "Apple" and "App". Inside a `Trie`, the chain of nodes representing "App" is shared with "Apple". If you'd like to remove "Apple", you'll need to take care to leave the "App" chain in tact. ```swift func remove(word: String) { guard !word.isEmpty else { return } // 1 guard let terminalNode = findTerminalNodeOf(word: word) else { return } // 2 if terminalNode.isLeaf { deleteNodesForWordEndingWith(terminalNode: terminalNode) } else { terminalNode.isTerminating = false } wordCount -= 1 } ``` 1. `findTerminalNodeOf` traverses through the Trie to find the last node that represents the `word`. If it is unable to traverse through the chain of characters, it returns `nil`. 2. `deleteNodesForWordEndingWith` traverse backwords, deleting the nodes represented by the `word`. ### Time Complexity Let n be the length of some value in the `Trie`. * `contains` - Worst case O(n) * `insert` - O(n) * `remove` - O(n) ### Other Notable Operations * `count`: Returns the number of keys in the `Trie` - O(1) * `words`: Returns a list containing all the keys in the `Trie` - O(1) * `isEmpty`: Returns `true` if the `Trie` is empty, `false` otherwise - O(1) See also [Wikipedia entry for Trie](https://en.wikipedia.org/wiki/Trie). *Written for the Swift Algorithm Club by Christian Encarnacion. Refactored by Kelvin Lau* # Changes by Rick Zaccone * Added comments to all methods * Refactored the `remove` method * Renamed some variables. I have mixed feelings about the way Swift infers types. It's not always apparent what type a variable will have. To address this, I made changes such as renaming `parent` to `parentNode` to emphasize that it is a node and not the value contained within the node. * Added a `words` property that recursively traverses the trie and constructs an array containing all of the words in the trie. * Added a `isLeaf` property to `TrieNode` for readability. * Implemented `count` and `isEmpty` properties for the trie. * I tried stress testing the trie by adding 162,825 words. The playground was very slow while adding the words and eventually crashed. To fix this problem, I moved everything into a project and wrote `XCTest` tests that test the trie. There are also several performance tests. Everything passes. ================================================ FILE: Trie/Trie/Trie/AppDelegate.swift ================================================ // // AppDelegate.swift // Trie // // Created by Rick Zaccone on 2016-12-12. // Copyright © 2016 Rick Zaccone. All rights reserved. // import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { // Insert code here to initialize your application } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } } ================================================ FILE: Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "mac", "size" : "16x16", "scale" : "1x" }, { "idiom" : "mac", "size" : "16x16", "scale" : "2x" }, { "idiom" : "mac", "size" : "32x32", "scale" : "1x" }, { "idiom" : "mac", "size" : "32x32", "scale" : "2x" }, { "idiom" : "mac", "size" : "128x128", "scale" : "1x" }, { "idiom" : "mac", "size" : "128x128", "scale" : "2x" }, { "idiom" : "mac", "size" : "256x256", "scale" : "1x" }, { "idiom" : "mac", "size" : "256x256", "scale" : "2x" }, { "idiom" : "mac", "size" : "512x512", "scale" : "1x" }, { "idiom" : "mac", "size" : "512x512", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Trie/Trie/Trie/Base.lproj/Main.storyboard ================================================ Default Left to Right Right to Left Default Left to Right Right to Left ================================================ FILE: Trie/Trie/Trie/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleVersion 1 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright Copyright © 2016 Rick Zaccone. All rights reserved. NSMainStoryboardFile Main NSPrincipalClass NSApplication ================================================ FILE: Trie/Trie/Trie/ReadMe.md ================================================ # Changes - Corrected a spelling error in a comment. - Got rid of the `get` syntax for a read only property as the coding guidelines suggest. - Changed several tests so that they are more Swift-like. That is, they now feel like they are using the features of the language better. - Fixed a problem in the test method `testRemovePerformance`. The `measure` method runs the block of code 10 times. Previously, all words would get removed after the first run and the next 9 runs were very fast because there was nothing to do! That is corrected now. - Made the `Trie` class a subclass of `NSObject` and had it conform to `NSCoding`. Added a test to verify that this works. --- I wasn't able to figure out how to recursively archive the trie. Instead, I tried Kelvin's suggestion to use the `words` property to create an array of words in the trie, then archiving the array. There are a couple of nice aspects to this approach. - The `TrieNode` class can remain generic since it doesn't need to conform to `NSCoding`. - It doesn't require much new code. There are several downsides though. - The size of the archived words is three times the size of the original file of words! Did I do this right? The tests pass, so it seems correct. I question whether archiving is worth the effort if the resulting archive is so much larger than the original file. - I would expect that archiving the trie would result in a file that was smaller than the original since a trie doesn't repeat leading character sequences when they are the same. - This requires that the trie get reconstructed when it is unarchived. - My gut tells me that it would be faster to archive and unarchive the trie itself, but I don't have any hard data to support this. I would like to see code that recursively archives the trie so we can compare the performance. ================================================ FILE: Trie/Trie/Trie/Trie.swift ================================================ // // Trie.swift // Trie // // Created by Rick Zaccone on 2016-12-12. // Copyright © 2016 Rick Zaccone. All rights reserved. // import Foundation /// A node in the trie class TrieNode { var value: T? weak var parentNode: TrieNode? var children: [T: TrieNode] = [:] var isTerminating = false var isLeaf: Bool { return children.count == 0 } /// Initializes a node. /// /// - Parameters: /// - value: The value that goes into the node /// - parentNode: A reference to this node's parent init(value: T? = nil, parentNode: TrieNode? = nil) { self.value = value self.parentNode = parentNode } /// Adds a child node to self. If the child is already present, /// do nothing. /// /// - Parameter value: The item to be added to this node. func add(value: T) { guard children[value] == nil else { return } children[value] = TrieNode(value: value, parentNode: self) } } /// A trie data structure containing words. Each node is a single /// character of a word. class Trie: NSObject, NSCoding { typealias Node = TrieNode /// The number of words in the trie public var count: Int { return wordCount } /// Is the trie empty? public var isEmpty: Bool { return wordCount == 0 } /// All words currently in the trie public var words: [String] { return wordsInSubtrie(rootNode: root, partialWord: "") } fileprivate let root: Node fileprivate var wordCount: Int /// Creates an empty trie. override init() { root = Node() wordCount = 0 super.init() } // MARK: NSCoding /// Initializes the trie with words from an archive /// /// - Parameter decoder: Decodes the archive required convenience init?(coder decoder: NSCoder) { self.init() let words = decoder.decodeObject(forKey: "words") as? [String] for word in words! { self.insert(word: word) } } /// Encodes the words in the trie by putting them in an array then encoding /// the array. /// /// - Parameter coder: The object that will encode the array func encode(with coder: NSCoder) { coder.encode(self.words, forKey: "words") } } // MARK: - Adds methods: insert, remove, contains extension Trie { /// Inserts a word into the trie. If the word is already present, /// there is no change. /// /// - Parameter word: the word to be inserted. func insert(word: String) { guard !word.isEmpty else { return } var currentNode = root for character in word.lowercased() { if let childNode = currentNode.children[character] { currentNode = childNode } else { currentNode.add(value: character) currentNode = currentNode.children[character]! } } // Word already present? guard !currentNode.isTerminating else { return } wordCount += 1 currentNode.isTerminating = true } /// Determines whether a word is in the trie. /// /// - Parameters: /// - word: the word to check for /// - matchPrefix: whether the search word should match /// if it is only a prefix of other nodes in the trie /// - Returns: true if the word is present, false otherwise. func contains(word: String, matchPrefix: Bool = false) -> Bool { guard !word.isEmpty else { return false } var currentNode = root for character in word.lowercased() { guard let childNode = currentNode.children[character] else { return false } currentNode = childNode } return matchPrefix || currentNode.isTerminating } /// Attempts to walk to the last node of a word. The /// search will fail if the word is not present. Doesn't /// check if the node is terminating /// /// - Parameter word: the word in question /// - Returns: the node where the search ended, nil if the /// search failed. private func findLastNodeOf(word: String) -> Node? { var currentNode = root for character in word.lowercased() { guard let childNode = currentNode.children[character] else { return nil } currentNode = childNode } return currentNode } /// Attempts to walk to the terminating node of a word. The /// search will fail if the word is not present. /// /// - Parameter word: the word in question /// - Returns: the node where the search ended, nil if the /// search failed. private func findTerminalNodeOf(word: String) -> Node? { if let lastNode = findLastNodeOf(word: word) { return lastNode.isTerminating ? lastNode : nil } return nil } /// Deletes a word from the trie by starting with the last letter /// and moving back, deleting nodes until either a non-leaf or a /// terminating node is found. /// /// - Parameter terminalNode: the node representing the last node /// of a word private func deleteNodesForWordEndingWith(terminalNode: Node) { var lastNode = terminalNode var character = lastNode.value while lastNode.isLeaf, let parentNode = lastNode.parentNode { lastNode = parentNode lastNode.children[character!] = nil character = lastNode.value if lastNode.isTerminating { break } } } /// Removes a word from the trie. If the word is not present or /// it is empty, just ignore it. If the last node is a leaf, /// delete that node and higher nodes that are leaves until a /// terminating node or non-leaf is found. If the last node of /// the word has more children, the word is part of other words. /// Mark the last node as non-terminating. /// /// - Parameter word: the word to be removed func remove(word: String) { guard !word.isEmpty else { return } guard let terminalNode = findTerminalNodeOf(word: word) else { return } if terminalNode.isLeaf { deleteNodesForWordEndingWith(terminalNode: terminalNode) } else { terminalNode.isTerminating = false } wordCount -= 1 } /// Returns an array of words in a subtrie of the trie /// /// - Parameters: /// - rootNode: the root node of the subtrie /// - partialWord: the letters collected by traversing to this node /// - Returns: the words in the subtrie fileprivate func wordsInSubtrie(rootNode: Node, partialWord: String) -> [String] { var subtrieWords = [String]() var previousLetters = partialWord if let value = rootNode.value { previousLetters.append(value) } if rootNode.isTerminating { subtrieWords.append(previousLetters) } for childNode in rootNode.children.values { let childWords = wordsInSubtrie(rootNode: childNode, partialWord: previousLetters) subtrieWords += childWords } return subtrieWords } /// Returns an array of words in a subtrie of the trie that start /// with given prefix /// /// - Parameters: /// - prefix: the letters for word prefix /// - Returns: the words in the subtrie that start with prefix func findWordsWithPrefix(prefix: String) -> [String] { var words = [String]() let prefixLowerCased = prefix.lowercased() if let lastNode = findLastNodeOf(word: prefixLowerCased) { if lastNode.isTerminating { words.append(prefixLowerCased) } for childNode in lastNode.children.values { let childWords = wordsInSubtrie(rootNode: childNode, partialWord: prefixLowerCased) words += childWords } } return words } } ================================================ FILE: Trie/Trie/Trie/ViewController.swift ================================================ // // ViewController.swift // Trie // // Created by Rick Zaccone on 2016-12-12. // Copyright © 2016 Rick Zaccone. All rights reserved. // import Cocoa class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } override var representedObject: Any? { didSet { // Update the view, if already loaded. } } } ================================================ FILE: Trie/Trie/Trie/dictionary.txt ================================================ 10s 10th 11th 12th 13th 14th 15th 16th 17th 1800s 1890s 18th 1900s 1910s 1920s 1930s 1940s 1950s 1960s 1970s 1980s 1990s 19th 1st 20s 20th 21st 22nd 23rd 24th 25th 26th 27th 28th 29th 2nd 30s 30th 31st 3rd 40s 4th 50s 5th 60s 6th 70s 7th 80s 8th 90s 9th a aachen aah aahed aahing aahs aardvark aardvarks aardwolf aardwolves aaron ab aba ababa abaca abaci aback abacterial abacus abacuses abadan abaft abalone abalones abampere abamperes abandon abandoned abandonee abandonees abandoner abandoners abandoning abandonment abandonments abandons abapical abase abased abasement abasements abases abash abashed abashes abashing abashment abashments abasia abasing abatable abate abated abatement abatements abater abaters abates abating abatis abatises abattoir abattoirs abaxial abbacies abbacy abbatial abbess abbesses abbeville abbevillian abbey abbeys abbot abbots abbreviate abbreviated abbreviates abbreviating abbreviation abbreviations abbreviator abbreviators abbé abbés abc abcoulomb abdicable abdicate abdicated abdicates abdicating abdication abdications abdicator abdicators abdomen abdomens abdominal abdominally abdominous abducens abducent abducentes abduct abducted abducting abduction abductions abductor abductors abducts abeam abecedarian abecedarians abed abednego abel abelard abelia abelian abelmosk abelmosks aberdare aberdeen aberdonian aberdonians aberrance aberrancies aberrancy aberrant aberrantly aberrants aberrated aberration aberrational aberrations abet abetment abetments abets abetted abetter abetters abetting abettor abettors abeyance abeyant abfarad abfarads abhenries abhenry abhor abhorred abhorrence abhorrences abhorrent abhorrently abhorrer abhorrers abhorring abhors abidance abidances abide abided abider abiders abides abiding abidingly abidingness abigail abigails abilities ability abiogeneses abiogenesis abiogenetic abiogenetical abiogenic abiogenically abiogenist abiological abiologically abiosis abiotic abiotically abject abjection abjections abjectly abjectness abjuration abjurations abjure abjured abjurer abjurers abjures abjuring ablate ablated ablates ablating ablation ablations ablative ablatively ablatives ablaut ablaze able abler ablest abloom abluted ablution ablutionary ablutions ably abnegate abnegated abnegates abnegating abnegation abnegations abnegator abnegators abnormal abnormalities abnormality abnormally abnormals aboard abode abodes abohm aboil abolish abolishable abolished abolisher abolishers abolishes abolishing abolishment abolishments abolition abolitionary abolitionism abolitionist abolitionists abomasa abomasal abomasum abominable abominably abominate abominated abominates abominating abomination abominations abominator abominators aboral aborally aboriginal aboriginally aborigine aborigines aborning abort aborted aborter aborters abortifacient aborting abortion abortionist abortionists abortions abortive abortively abortiveness aborts abos abound abounded abounding abounds about above aboveboard aboveground abracadabra abrachia abradable abradant abradants abrade abraded abrader abraders abrades abrading abraham abranchiate abrash abrasion abrasions abrasive abrasively abrasiveness abrasives abreact abreacted abreacting abreaction abreactions abreacts abreast abridge abridged abridgement abridgements abridger abridgers abridges abridging abridgment abridgments abrin abroach abroad abrogate abrogated abrogates abrogating abrogation abrogations abrupt abruption abruptly abruptness abruzzi abruzzo absalom abscess abscessed abscesses abscessing abscise abscised abscises abscisin abscising abscisins abscissa abscissae abscissas abscission abscissions abscond absconded absconder absconders absconding absconds absence absences absent absented absentee absenteeism absentees absentia absenting absently absentminded absentmindedly absentmindedness absents absinth absinthe absinthes absinths absolute absolutely absoluteness absolutes absolution absolutions absolutism absolutisms absolutist absolutistic absolutists absolutize absolutized absolutizes absolutizing absolvable absolve absolved absolver absolvers absolves absolving absorb absorbability absorbable absorbance absorbancy absorbant absorbants absorbed absorbedly absorbedness absorbefacient absorbencies absorbency absorbent absorbents absorber absorbers absorbing absorbingly absorbs absorptance absorption absorptions absorptive absorptivity absquatulate absquatulated absquatulates absquatulating abstain abstained abstainer abstainers abstaining abstains abstemious abstemiously abstemiousness abstention abstentions abstentious abstinence abstinent abstinently abstract abstractable abstracted abstractedly abstractedness abstracter abstracters abstracting abstraction abstractional abstractionism abstractionist abstractionists abstractions abstractive abstractly abstractness abstractor abstractors abstracts abstruse abstrusely abstruseness abstrusities abstrusity absurd absurdism absurdist absurdities absurdity absurdly absurdness absurdum abu abubble abuilding abulia abulias abulic abundance abundances abundant abundantly abusable abuse abused abuser abusers abuses abusing abusive abusively abusiveness abut abutilon abutilons abutment abutments abuts abutted abutter abutters abutting abuzz abvolt abvolts aby abydos abye abyes abying abys abysm abysmal abysmally abysms abyss abyssal abysses abyssinia abyssinian abyssinians acacia acacias academe academes academia academic academical academically academician academicians academicism academics academies academism academy acantha acanthae acanthi acanthocephalan acanthoid acanthopterygian acanthus acanthuses acapnia acapulco acari acariasis acarid acaridae acarids acarologist acarology acarophobia acarpous acarus acatalectic acaudate acaulescent accede acceded accedence acceder acceders accedes acceding accelerando accelerant accelerate accelerated accelerates accelerating acceleratingly acceleration accelerations accelerative accelerator accelerators accelerograph accelerometer accelerometers accent accented accenting accentless accents accentual accentually accentuate accentuated accentuates accentuating accentuation accept acceptability acceptable acceptableness acceptably acceptance acceptances acceptant acceptation accepted acceptedly accepter accepters accepting acceptingly acceptingness acceptive acceptor acceptors accepts access accessaries accessary accessed accesses accessibility accessible accessibleness accessibly accessing accession accessional accessioned accessioning accessions accessorial accessories accessorily accessoriness accessorize accessorized accessorizes accessorizing accessory acciaccatura accidence accident accidental accidentally accidentalness accidentals accidently accidents accidie accidies accipiter accipitrine acclaim acclaimed acclaimer acclaimers acclaiming acclaims acclamation acclamations acclamatory acclimate acclimated acclimates acclimating acclimation acclimatization acclimatize acclimatized acclimatizer acclimatizers acclimatizes acclimatizing acclivities acclivitous acclivity accolade accoladed accolades accolading accommodate accommodated accommodates accommodating accommodatingly accommodation accommodational accommodationist accommodations accommodative accommodativeness accommodator accommodators accompanied accompanies accompaniment accompaniments accompanist accompanists accompany accompanying accompli accomplice accomplices accomplis accomplish accomplishable accomplished accomplisher accomplishers accomplishes accomplishing accomplishment accomplishments accord accordance accordances accordant accordantly accorded according accordingly accordion accordionist accordionists accordions accords accost accosted accosting accosts accouchement accouchements account accountabilities accountability accountable accountableness accountably accountancies accountancy accountant accountants accountantship accounted accounting accountings accounts accouter accoutered accoutering accouterment accouterments accouters accoutre accoutred accoutrement accoutrements accoutres accoutring accra accredit accreditable accreditation accreditations accredited accrediting accredits accrescent accrete accreted accretes accreting accretion accretionary accretions accretive accruable accrual accruals accrue accrued accruement accruements accrues accruing acculturate acculturated acculturates acculturating acculturation acculturational acculturative accumbent accumulable accumulate accumulated accumulates accumulating accumulation accumulations accumulative accumulatively accumulativeness accumulator accumulators accuracies accuracy accurate accurately accurateness accurse accursed accursedly accursedness accurst accusable accusal accusals accusation accusations accusative accusatively accusatives accusatorial accusatorially accusatory accuse accused accuser accusers accuses accusing accusingly accustom accustomation accustomed accustomedness accustoming accustoms ace aced acedia acedias aceldama acellular acentric acephalous acequia acequias acerate acerated acerb acerbate acerbated acerbates acerbating acerbic acerbically acerbities acerbity acerola acerolas acerose acervuli acervulus aces acetabula acetabular acetabulum acetal acetaldehyde acetals acetamide acetaminophen acetanilide acetate acetates acetic acetification acetified acetifier acetifies acetify acetifying acetoaceticacetonic acetone acetones acetonic acetophenetidin acetous acetum acetyl acetylate acetylated acetylates acetylating acetylation acetylative acetylcholine acetylcholinesterase acetylene acetylenic acetylic acetyls acetylsalicylic achaea achaean achaeans achaemenid achaemenids achalasia achates ache ached achene achenes achenial acheron aches acheulean acheuleans acheulian acheulians achier achiest achievable achieve achieved achievement achievements achiever achievers achieves achieving achillea achilles achiness aching achingly achira achlamydeous achlorhydria achlorhydric achlorophyllous acholia achondrite achondritic achondroplasia achondroplastic achromat achromatic achromatically achromaticity achromatin achromatinic achromatism achromatize achromatized achromatizes achromatizing achromats achromic achy acicula aciculae acicular aciculas aciculate aciculated acid acidanthera acidemia acidhead acidheads acidic acidifiable acidification acidified acidifier acidifiers acidifies acidify acidifying acidimeter acidimeters acidimetric acidimetry acidities acidity acidly acidness acidophil acidophilic acidophilus acidosis acidotic acids acidulate acidulated acidulates acidulating acidulation acidulent acidulous aciduria acidy acinar acing acini acinic acinous acinus ackee ackees ackerman acknowledge acknowledgeable acknowledged acknowledgedly acknowledgement acknowledgements acknowledges acknowledging acknowledgment acknowledgments acme acmes acne acned acock acoelomate acoelous acold acolyte acolytes aconite aconites acorn acorns acoustic acoustical acoustically acoustician acoustics acoustoelectric acoustoelectrically acoustooptical acoustooptically acoustooptics acquaint acquaintance acquaintances acquaintanceship acquaintanceships acquainted acquainting acquaints acquiesce acquiesced acquiescence acquiescent acquiescently acquiesces acquiescing acquirable acquire acquired acquirement acquirements acquirer acquirers acquires acquiring acquisition acquisitional acquisitions acquisitive acquisitively acquisitiveness acquisitor acquit acquits acquittal acquittals acquittance acquitted acquitter acquitters acquitting acre acreage acreages acres acrid acridine acridines acridities acridity acridly acridness acriflavine acrimonious acrimoniously acrimoniousness acrimony acrobat acrobatic acrobatically acrobatics acrobats acrocentric acrocephalic acrocephaly acrodont acrodonts acrolect acrolein acroleins acromegalic acromegalies acromegaly acromelic acromion acronym acronymic acronymically acronymous acronyms acropetal acropetally acrophobia acropolis acropolises acrosomal acrosome across acrostic acrostical acrostically acrostics acrylate acrylates acrylic acrylics acrylonitrile act acta actability actable actaeon acte acted actes actin actinal actinally acting actinia actiniae actinian actinians actinic actinically actinide actinides actinism actinium actinoid actinolite actinomere actinometer actinometers actinometric actinometrical actinometry actinomorphic actinomorphous actinomorphy actinomyces actinomycetal actinomycete actinomycetous actinomycin actinomycosis actinomycotic actinon actinons actinouranium action actionable actionably actionless actions actium activate activated activates activating activation activations activator activators active actively activeness actives activism activist activistic activists activities activity actomyosin actor actorish actors actress actresses acts actual actualities actuality actualization actualizations actualize actualized actualizes actualizing actually actuarial actuarially actuaries actuary actuate actuated actuates actuating actuation actuations actuator actuators acuity aculeate acumen acuminate acuminated acuminates acuminating acumination acupressure acupuncture acupunctured acupunctures acupuncturing acupuncturist acupuncturists acute acutely acuteness acuter acutest acyclic acyclovir acyl acylate acylated acylates acylating acylation acylations acyls ad ada adage adages adagio adagios adam adamance adamances adamancies adamancy adamant adamantine adamantly adamants adapt adaptability adaptable adaptableness adaptation adaptational adaptationally adaptations adapted adaptedness adapter adapters adapting adaption adaptions adaptive adaptively adaptiveness adaptivity adaptor adaptors adapts adaxial add addable addax addaxes added addend addenda addends addendum adder adders addible addict addicted addicting addiction addictions addictive addicts adding addis addison addition additional additionally additions additive additively additives additivity addle addlebrained addled addlepated addles addling address addressability addressable addressed addressee addressees addresser addressers addresses addressing adds adduce adduceable adduced adducer adducers adduces adducing adduct adducted adducting adduction adductive adductor adductors adducts adelaide ademption aden adenectomy adenine adenines adenitis adenitises adenocarcinoma adenocarcinomatous adenohypophyseal adenohypophyses adenohypophysial adenohypophysis adenoid adenoidal adenoids adenoma adenomas adenomatoid adenomatous adenosine adenosis adenosyl adenoviral adenovirus adenoviruses adenyl adept adeptly adeptness adepts adequacies adequacy adequate adequately adequateness adhere adhered adherence adherent adherently adherents adheres adhering adhesion adhesional adhesions adhesiotomies adhesiotomy adhesive adhesively adhesiveness adhesives adiabatic adiabatically adieu adieus adieux adige adios adipic adipocere adipocyte adipose adiposeness adiposity adirondack adirondacks adit adits adjacencies adjacency adjacent adjacently adjectival adjectivally adjective adjectively adjectives adjoin adjoined adjoining adjoins adjoint adjoints adjourn adjourned adjourning adjournment adjournments adjourns adjudge adjudged adjudges adjudging adjudicate adjudicated adjudicates adjudicating adjudication adjudications adjudicative adjudicator adjudicators adjudicatory adjunct adjunction adjunctive adjunctly adjuncts adjuration adjurations adjuratory adjure adjured adjurer adjurers adjures adjuring adjust adjustability adjustable adjustably adjusted adjuster adjusters adjusting adjustive adjustment adjustmental adjustments adjustor adjustors adjusts adjutancy adjutant adjutants adjuvant adjuvants adlerian adlib adlibbed adlibs adman admass admeasure admeasured admeasurement admeasurements admeasurer admeasures admeasuring admen admin administer administered administering administers administrable administrant administrants administrate administrated administrates administrating administration administrational administrations administrative administratively administrator administrators administratra administratrices administratrix admirability admirable admirableness admirably admiral admirals admiralties admiralty admiration admirations admire admired admirer admirers admires admiring admiringly admissibility admissible admissibleness admissibly admission admissions admissive admit admits admittance admittances admitted admittedly admitting admix admixed admixes admixing admixture admixtures admonish admonished admonisher admonishes admonishing admonishingly admonishment admonishments admonition admonitions admonitorily admonitory adnate adnation adnations adnexa adnexal adnominal adnoun adnouns ado adobe adobes adolescence adolescent adolescently adolescents adonais adonis adopt adoptability adoptable adopted adoptee adoptees adopter adopters adoptianism adoptianist adoptianists adopting adoption adoptionism adoptionist adoptionists adoptions adoptive adoptively adopts adorability adorable adorableness adorably adoral adoration adore adored adorer adorers adores adoring adoringly adorn adorned adorner adorners adorning adornment adornments adorns adrenal adrenalectomy adrenalin adrenaline adrenalize adrenalized adrenalizes adrenalizing adrenally adrenals adrenergic adrenergically adrenochrome adrenocortical adrenocorticosteroid adrenocorticotrophic adrenocorticotrophin adrenocorticotropic adrenocorticotropin adrenolytic adriatic adrift adroit adroitly adroitness ads adscititious adsorb adsorbable adsorbate adsorbates adsorbed adsorbent adsorbents adsorbing adsorbs adsorption adsorptive adularia adularias adulate adulated adulates adulating adulation adulations adulator adulators adulatory adult adulterant adulterants adulterate adulterated adulterates adulterating adulteration adulterations adulterator adulterators adulterer adulterers adulteress adulteresses adulteries adulterine adulterous adulterously adultery adulthood adultlike adultly adultness adults adumbrate adumbrated adumbrates adumbrating adumbration adumbrations adumbrative adumbratively adust advance advanced advancement advancements advancer advancers advances advancing advantage advantaged advantageous advantageously advantageousness advantages advantaging advect advected advecting advection advections advective advects advent adventism adventist adventists adventitia adventitial adventitious adventitiously adventitiousness adventive adventively advents adventure adventured adventurer adventurers adventures adventuresome adventuresomely adventuresomeness adventuress adventuresses adventuring adventurism adventurist adventuristic adventurists adventurous adventurously adventurousness adverb adverbial adverbially adverbs adversarial adversaries adversary adversative adversatively adverse adversely adverseness adversities adversity advert adverted advertence advertences advertencies advertency advertent advertently adverting advertise advertised advertisement advertisements advertiser advertisers advertises advertising adverts advice advices advisability advisable advisableness advisably advise advised advisedly advisee advisees advisement advisements adviser advisers advises advising advisor advisories advisors advisory advocacy advocate advocated advocates advocating advocation advocative advocator advocators advocatory advowson advowsons adynamia adynamias adynamic adyta adytum adz adze adzes aechmea aecia aecial aeciospore aecium aedes aedilberct aedile aediles aedine aegean aegeus aegis aeneas aeneid aeneous aeolian aeolians aeolic aeolus aeon aeonian aeonic aeons aepyornis aequorin aerate aerated aerates aerating aeration aerations aerator aerators aerenchyma aerial aerialist aerialists aerially aerials aerie aerier aeries aeriest aerily aero aeroallergen aeroballistic aeroballistics aerobat aerobatic aerobatics aerobe aerobes aerobic aerobically aerobicize aerobicized aerobicizes aerobicizing aerobics aerobiological aerobiologically aerobiology aerobiosis aerobiotic aerobium aeroculture aerodrome aerodromes aerodynamic aerodynamical aerodynamically aerodynamicist aerodynamicists aerodynamics aerodyne aerodynes aeroembolism aerofoil aerofoils aerogram aerograms aerographer aerolite aerolites aerolith aeroliths aerolitic aerologic aerological aerologist aerologists aerology aeromagnetic aeromagnetically aeromagnetics aeromechanical aeromechanically aeromechanics aeromedical aeromedicine aerometeorograph aerometer aerometers aeronaut aeronautic aeronautical aeronautically aeronautics aeronauts aeroneurosis aeronomer aeronomic aeronomical aeronomist aeronomy aeropause aerophagia aerophobia aerophore aerophyte aeroplane aeroplanes aeroponics aerosol aerosolization aerosolize aerosolized aerosolizes aerosolizing aerosols aerospace aerosphere aerostat aerostatic aerostatical aerostatics aerostats aerotactic aerotaxis aerothermodynamics aery aeschylus aesculapian aesculapius aesop aesopian aesopic aesthesia aesthete aesthetes aesthetic aesthetically aesthetician aestheticians aestheticism aestheticize aestheticized aestheticizes aestheticizing aesthetics aestival aestivate aestivated aestivates aestivating aestivation aethelberht aethelred aether aetheric aethers afar afeard afeared afebrile affability affable affably affair affaire affaires affairs affect affectability affectable affectation affectations affected affectedly affectedness affecter affecters affecting affectingly affection affectional affectionally affectionate affectionately affectionateness affectioned affectionless affections affective affectively affectivity affectless affectlessness affects affenpinscher afferent afferently affiance affianced affiances affiancing affiant affiants afficionado affidavit affidavits affiliate affiliated affiliates affiliating affiliation affiliations affine affined affinely affinities affinity affirm affirmable affirmably affirmance affirmant affirmation affirmations affirmative affirmatively affirmatives affirmed affirmer affirmers affirming affirms affix affixable affixal affixation affixations affixed affixer affixers affixes affixial affixing affixment afflatus afflatuses afflict afflicted afflicter afflicting affliction afflictions afflictive afflictively afflicts affluence affluency affluent affluently affluents afflux affluxes afford affordability affordable affordably afforded affording affords afforest afforestation afforested afforesting afforests affray affrayed affraying affrays affricate affricates affricative affright affrighted affrighting affrightment affrights affront affronted affronting affronts affusion affusions afghan afghani afghanistan afghans aficionada aficionado aficionados afield afire aflame aflatoxicosis aflatoxin afloat aflutter afoot afore aforementioned aforesaid aforethought aforetime aforetimes afoul afraid afreet afreets afresh africa african africanism africanist africanization africanize africanized africanizes africanizing africans africanus afrikaans afrikaner afrikaners afrit afrits afro afros aft after afterbirth afterbirths afterburner afterburners aftercare afterclap afterdamp afterdeck afterdecks aftereffect aftereffects afterglow afterimage afterimages afterlife afterlives aftermarket aftermarkets aftermath aftermost afternoon afternoons afterpains afterpiece afters aftersensation aftershave aftershaves aftershock aftershocks aftertaste aftertastes afterthought afterthoughts aftertime aftertimes afterward afterwards afterword afterwork afterworld afterworlds aftmost agadir again against agalactia agama agamas agamemnon agamete agametes agamic agamically agammaglobulinemia agammaglobulinemic agamogenesis agamospermy agapanthus agape agar agaric agarics agars agassiz agate agates agave agaves agaze age aged agedly agedness ageing ageism ageist ageists ageless agelessly agelessness agelong agencies agency agenda agendaless agendas agendum agendums agenesis agent agential agentries agentry agents ager ageratum ageratums agers ages aggie aggies aggiornamento aggiornamentos agglomerate agglomerated agglomerates agglomerating agglomeration agglomerations agglomerative agglomerator agglutinability agglutinable agglutinant agglutinate agglutinated agglutinates agglutinating agglutination agglutinations agglutinative agglutinin agglutinins agglutinogen agglutinogenic aggradation aggradational aggrade aggraded aggrades aggrading aggrandize aggrandized aggrandizement aggrandizements aggrandizer aggrandizers aggrandizes aggrandizing aggravate aggravated aggravates aggravating aggravatingly aggravation aggravations aggravative aggravator aggravators aggregate aggregated aggregately aggregateness aggregates aggregating aggregation aggregational aggregations aggregative aggregatively aggregator aggregators aggress aggressed aggresses aggressing aggression aggressions aggressive aggressively aggressiveness aggressivity aggressor aggressors aggrieve aggrieved aggrievedly aggrieves aggrieving agha aghas aghast agile agilely agileness agility agin agincourt aging agism agist agists agita agitate agitated agitatedly agitates agitating agitation agitational agitative agitato agitator agitators agitprop agitprops aglaia aglare agleam aglet aglets agley aglitter aglow aglycon aglycone aglycones aglycons agnail agnails agnate agnates agnathan agnatic agnatically agnation agnations agnes agnize agnized agnizes agnizing agnomen agnomens agnomina agnosia agnostic agnostically agnosticism agnostics agnus ago agog agon agonal agone agones agonic agonies agonist agonistes agonistic agonistically agonists agonize agonized agonizes agonizing agonizingly agony agora agorae agoraphobia agoraphobiac agoraphobic agoras agorot agoroth agotis agouti agouties agoutis agra agrafe agrafes agraffe agraffes agranulocytosis agrapha agraphia agraphias agraphic agrarian agrarianism agrarianly agrarians agree agreeability agreeable agreeableness agreeably agreed agreeing agreement agreements agrees agribusiness agricide agricola agricultural agriculturalist agriculturalists agriculturally agriculture agricultures agriculturist agriculturists agrigento agrimation agrimonies agrimony agrippa agrippina agrobiologic agrobiological agrobiologically agrobiologist agrobiology agrochemical agroforester agroforesters agroforestry agroindustrial agrologic agrological agrologically agrologist agrology agronomic agronomical agronomically agronomist agronomists agronomy agrostologist agrostology aground aguacate ague aguecheek agues aguish aguishly aguishness ah aha ahab ahead ahem ahems ahimsa ahimsas ahistoric ahistorical ahmadabad ahmedabad ahold aholds ahoy ahs ai aiblins aid aidan aide aided aider aiders aides aiding aidman aidmen aids aigret aigrets aigrette aigrettes aiguille aiguilles aiguillette aikido aikidos ail ailanthus ailanthuses ailed aileron ailerons ailing ailment ailments ails ailurophile ailurophobe ailurophobia aim aimed aiming aimless aimlessly aimlessness aims ain ain't ainu ainus aioli air airbag airbags airbed airbeds airboat airboats airborne airbrake airbrakes airbrush airbrushed airbrushes airbrushing airburst airbursts airbus airbuses aircraft aircrew aircrews airdate airdrome airdromes airdrop airdropped airdropping airdrops aired airedale airedales airer airers aires airfare airfares airfield airfields airflow airfoil airfoils airforce airforces airframe airframes airfreight airglow airglows airhead airheads airier airiest airily airiness airing airings airless airlessness airlift airlifted airlifting airlifts airline airliner airliners airlines airlock airlocks airmail airmailed airmailing airmails airman airmanship airmen airmobile airpark airparks airplane airplanes airplay airport airports airpost airpower airs airscrew airscrews airship airships airsick airsickness airside airspace airspeed airspeeds airstream airstreams airstrip airstrips airt airted airtight airtightness airtime airting airts airwave airwaves airway airways airwoman airwomen airworthier airworthiest airworthiness airworthy airy aisle aisles ait aitch aitchbone aitches aits aix ajar ajax ajuga ajugas akaryocyte akbar akee akees akhenaten akhenaton akimbo akin akinesia akinetic akkad akrotiri al ala alabama alabaman alabamans alabamian alabamians alabaster alabastrine alack alacritous alacrity aladdin alae alai alameda alamedas alamein alamo alamode alamodes alamogordo alamos alanine alanines alanyl alanyls alar alaric alarm alarmed alarming alarmingly alarmism alarmist alarmists alarms alarum alarums alary alas alaska alaskan alaskans alassio alastor alastors alate alb albacore albacores alban albania albanian albanians albany albatross albatrosses albedo albedos albeit albert alberta albertus albescent albigenses albigensian albigensianism albinism albinistic albino albinos albinotic albion albite albites albitic albitical albs album albumen albumin albuminoid albuminous albuminuria albuminuric albumose albumoses albums albuquerque alcaic alcaics alcaide alcaides alcalde alcaldes alcatraz alcayde alcaydes alcazar alcazars alcestis alchemic alchemical alchemically alchemist alchemistic alchemistical alchemists alchemize alchemized alchemizes alchemizing alchemy alcibiades alcohol alcoholic alcoholically alcoholicity alcoholics alcoholism alcoholometer alcoholometers alcoholometry alcohols alcott alcove alcoves alcuin aldebaran aldehyde aldehydes alder alderman aldermancy aldermanic aldermen alders alderwoman alderwomen aldicarb aldis aldol aldolase aldolases aldols aldose aldoses aldosterone aldosteronism aldrin aldrins ale aleatoric aleatory alec alecithal aleck alecks alecky alecs alee alegar alegars alehouse alehouses alembic alembics alençon aleph alephs aleppo alert alerted alerting alertly alertness alerts ales aleuron aleurone aleurones aleuronic aleurons aleut aleutian aleutians aleuts alevin alevins alewife alewives alex alexander alexandra alexandria alexandrian alexandrine alexandrines alexandrite alexandrites alexia alexin alfa alfalfa alfas alfilaria alfonso alforja alforjas alfred alfredo alfresco alga algae algaecide algaecides algal algaroba algarobas algarroba algarrobas algarve algas algebra algebraic algebraically algebraist algebraists algebras algeciras alger algeria algerian algerians algicidal algicide algicides algid algidities algidity algiers algin alginate alginates algins algoid algol algolagnia algolagniac algolagnic algolagnist algological algologically algologist algologists algology algonquian algonquians algonquin algonquins algophobia algorism algorithm algorithmic algorithmically algorithms alhambra ali alia alias aliases alibi alibied alibiing alibis alible alicante alice alicyclic alidad alidade alidades alidads alien alienability alienable alienage alienages alienate alienated alienates alienating alienation alienator alienators aliened alienee alienees aliening alienism alienisms alienist alienists alienly alienness alienor alienors aliens aliesterase aliform alight alighted alighting alightment alights align aligned aligner aligners aligning alignment alignments aligns alike alikeness aliment alimental alimentally alimentary alimentation alimentative alimented alimenting aliments alimonies alimony aline alined alinement alinements alines alining aliphatic aliquot aliquots alit aliter alive aliveness aliyah aliyahs alizarin alizarine alizarines alizarins alkahest alkahestic alkahestical alkahests alkalescence alkalescent alkali alkalimeter alkalimeters alkalimetry alkaline alkalinity alkalinization alkalinize alkalinized alkalinizes alkalinizing alkalis alkalization alkalize alkalized alkalizes alkalizing alkaloid alkaloidal alkaloids alkaloses alkalosis alkalotic alkane alkanes alkanet alkanets alkene alkenes alkine alkines alkoxy alkyd alkyds alkyl alkylate alkylated alkylates alkylating alkylation alkyls alkyne alkynes all alla allah allahabad allamanda allan allantoic allantoid allantoides allantoin allantois allargando allay allayed allayer allayers allaying allayment allays allegation allegations allege allegeable alleged allegedly alleger allegers alleges alleghenies allegheny allegiance allegiances allegiant alleging allegoric allegorical allegorically allegoricalness allegories allegorist allegorists allegorization allegorize allegorized allegorizer allegorizes allegorizing allegory allegretto allegrettos allegro allegros allele alleles allelic allelism allelomorph allelomorphic allelomorphism allelomorphs allelopathic allelopathy alleluia alleluias allemande allemandes allen allenby aller allergen allergenic allergenicity allergens allergic allergies allergist allergists allergy allers allethrin alleviate alleviated alleviates alleviating alleviation alleviations alleviative alleviator alleviators alleviatory alley alleyn alleyne alleys alleyway alleyways alliaceous alliance alliances allied allies alligator alligatoring alligators allison alliterate alliterated alliterates alliterating alliteration alliterations alliterative alliteratively alliterativeness allium alliums alloantibody alloantigen allocable allocatable allocate allocated allocates allocating allocation allocations allocator allocators allochthonous allocution allocutions allogamies allogamous allogamy allogeneic allogenic allograft allograph allographic allomerism allomerous allometric allometry allomorph allomorphic allomorphism allomorphs allonge allonges allonym allonymous allonymously allonyms allopath allopathic allopathically allopathies allopathist allopathists allopaths allopathy allopatric allopatrically allopatry allophane allophone allophones allophonic allopolyploid allopolyploidy allopurinol allosteric allosterically allostery allot allotetraploid allotetraploidy allotment allotments allotransplant allotransplantation allotransplanted allotransplanting allotransplants allotrope allotropes allotropic allotropical allotropically allotropy allots allotted allottee allottees allotter allotters allotting allotype allotypes allotypic allotypically allotypy allover allovers allow allowable allowably allowance allowanced allowances allowancing allowed allowedly allowing allows alloxan alloxans alloy alloyed alloying alloys allseed allseeds allspice allude alluded alludes alluding allure allured allurement allurements allurer allurers allures alluring alluringly allusion allusions allusive allusively allusiveness alluvia alluvial alluvion alluvium alluviums ally allying allyl allylic allyls alma almagest almagests almanac almanacs almandine almandines almandite almandites almeria almightily almightiness almighty almond almonds almoner almoners almost alms almsgiver almsgivers almsgiving almshouse almshouses almsman almsmen alnico alocasia aloe aloes aloetic aloft alogical alogically alogicalness aloha aloin aloins alone aloneness along alongshore alongside aloof aloofly aloofness alopecia alopecias alopecic aloud alow alp alpaca alpacas alpenglow alpenhorn alpenhorns alpenstock alpenstocks alpestrine alpha alphabet alphabetic alphabetical alphabetically alphabetization alphabetizations alphabetize alphabetized alphabetizer alphabetizers alphabetizes alphabetizing alphabets alphameric alphanumeric alphanumerical alphanumerically alphanumerics alphas alpheus alphorn alphorns alpine alpinism alpinist alpinists alps already alright alsace alsatian alsatians alsike also alstroemeria alt altai altaic altair altamira altar altarpiece altarpieces altars altazimuth altazimuths alter alterability alterable alterableness alterably alteration alterations alterative altercate altercated altercates altercating altercation altercations altered alterer alterers altering alternaria alternate alternated alternately alternateness alternates alternating alternation alternations alternative alternatively alternativeness alternatives alternator alternators alters althea altho althorn althorns although altimeter altimeters altimetric altimetry altiplano altiplanos altitude altitudes altitudinal altitudinous altnaharra alto altocumuli altocumulus altogether altoona altos altostratus altricial altruism altruist altruistic altruistically altruists alts alula alulae alular alum alumina aluminas aluminate aluminiferous aluminium aluminize aluminized aluminizes aluminizing aluminosilicate aluminous aluminum aluminums alumna alumnae alumni alumnus alumroot alumroots alunite alunites alvarez alveolar alveolarly alveolars alveolate alveolation alveoli alveolus alway always alyssum alyssums alzheimer alzheimer's am ama amah amahs amain amalfi amalgam amalgamate amalgamated amalgamates amalgamating amalgamation amalgamations amalgamative amalgamator amalgamators amalgams amanda amandine amanita amanitas amantadine amanuenses amanuensis amaranth amaranthine amaranths amarelle amarelles amaretto amarettos amarillo amarna amaryllis amaryllises amas amass amassable amassed amasser amassers amasses amassing amassment amassments amateur amateurish amateurishly amateurishness amateurism amateurs amative amatively amativeness amatol amatols amatory amaurosis amaurotic amaze amazed amazedly amazedness amazement amazes amazing amazingly amazon amazonia amazonian amazonite amazons ambage ambages ambagious ambarella ambassador ambassadorial ambassadors ambassadorship ambassadorships ambassadress ambassadresses ambeer ambeers amber ambergris amberjack ambiance ambiances ambidexterity ambidextrous ambidextrously ambience ambiences ambient ambiguities ambiguity ambiguous ambiguously ambiguousness ambipolar ambisexual ambisexuality ambit ambition ambitionless ambitions ambitious ambitiously ambitiousness ambits ambivalence ambivalent ambivalently ambiversion ambivert ambiverts amble ambled ambler amblers ambles ambling amblygonite amblyopia amblyopic ambo amboina amboinas ambos amboyna amboynas ambries ambrose ambrosia ambrosial ambrosially ambrosian ambrosias ambrotype ambry ambsace ambsaces ambulacra ambulacral ambulacrum ambulance ambulances ambulant ambulate ambulated ambulates ambulating ambulation ambulations ambulatories ambulatorily ambulatory ambuscade ambuscaded ambuscader ambuscades ambuscading ambush ambushed ambusher ambushers ambushes ambushing ambushment ameba amebas amebiasis amebic ameboid ameer ameers ameliorate ameliorated ameliorates ameliorating amelioration ameliorations ameliorative ameliorator ameliorators amelioratory amen amenability amenable amenableness amenably amend amendable amendatory amended amender amenders amending amendment amendments amends amenhotep amenities amenity amenophis amenorrhea amenorrheic amensalism ament amentaceous amentia amentias amentiferous aments amerasian amerasians amerce amerceable amerced amercement amercements amerces amerciable amercing america american americana americanism americanisms americanist americanists americanization americanize americanized americanizes americanizing americanness americans americas americium amerind amerindian amerindians amerinds ames ameslan amethopterin amethyst amethystine amethysts ametropia ametropic amharic amherst ami amiability amiable amiableness amiably amianthus amicability amicable amicableness amicably amice amices amici amicus amid amidase amidases amide amides amidic amido amidol amidols amidships amidst amiens amigo amigos amine amines amino aminoacidemia aminoaciduria aminobenzoic aminobutyric aminopeptidase aminopeptidases aminophenol aminophylline aminopterin aminopyrine aminopyrines aminosalicylic aminotransferase amir amirs amish amiss amities amitoses amitosis amitotic amitotically amitriptyline amitrole amitroles amity ammeter ammeters ammine ammines ammino ammo ammonia ammoniac ammoniacal ammoniate ammoniated ammoniates ammoniating ammoniation ammonification ammonified ammonifier ammonifies ammonify ammonifying ammonite ammonites ammonitic ammonium ammonoid ammonoids ammunition ammunitions amnesia amnesiac amnesiacs amnesic amnesics amnestic amnestied amnesties amnesty amnestying amnia amniocenteses amniocentesis amniographies amniography amnion amnions amnioscope amnioscopies amnioscopy amniote amniotes amniotic amobarbital amoeba amoebae amoebaean amoebas amoebiasis amoebic amoebocyte amoeboid amok amoks amole amoles among amongst amontillado amontillados amor amoral amoralism amorality amorally amore amoretti amoretto amorettos amorist amoristic amorists amorous amorously amorousness amorphism amorphous amorphously amorphousness amort amortizable amortization amortizations amortize amortized amortizes amortizing amos amosite amosites amount amounted amounting amounts amour amours amoxicillin amp amperage amperages ampere amperes ampersand ampersands amphetamine amphetamines amphiarthroses amphiarthrosis amphibia amphibian amphibians amphibiotic amphibious amphibiously amphibiousness amphibole amphiboles amphibolic amphibolite amphibolitic amphibologies amphibology amphibolous amphibrach amphictyonic amphictyonies amphictyony amphidiploid amphidiploidy amphimacer amphimictic amphimixes amphimixis amphion amphioxus amphipathic amphiploid amphiploids amphiploidy amphipod amphipods amphiprostyle amphisbaena amphisbaenic amphistylar amphitheater amphitheaters amphitheatric amphitheatrical amphitheatrically amphithecia amphithecium amphitrite amphitropous amphitryon amphora amphorae amphoral amphoras amphoteric ampicillin ample ampleness ampler amplest amplexicaul amplexus amplidyne amplidynes amplification amplifications amplified amplifier amplifiers amplifies amplify amplifying amplitude amplitudes amply ampoule ampoules amps ampul ampule ampules ampulla ampullae ampullar ampuls amputate amputated amputates amputating amputation amputations amputator amputators amputee amputees ampère amreeta amreetas amrita amritas amritsar amsterdam amtrac amtrack amtracks amtracs amtrak amuck amulet amulets amun amundsen amusable amuse amused amusedly amusement amusements amuser amusers amuses amusing amusingly amusingness amusive amygdala amygdalae amygdale amygdales amygdalin amygdaline amygdaloid amygdaloidal amygdule amygdules amyl amylaceous amylase amylases amyloid amyloidosis amyloids amylolysis amylolytic amylopsin amylose amyloses amyls amylum amylums amyotonia an ana anabaena anabaenas anabaptism anabaptist anabaptists anabas anabases anabasis anabatic anabiosis anabiotic anabolic anabolism anachronic anachronism anachronisms anachronistic anachronistically anachronous anachronously anaclisis anaclitic anacolutha anacoluthic anacoluthically anacoluthon anacoluthons anaconda anacondas anacreon anacreontic anacruses anacrusis anadem anadems anadiploses anadiplosis anadromous anaemia anaemias anaerobe anaerobes anaerobic anaerobically anaerobiosis anaerobiotic anaesthesia anaesthesiology anaesthetic anaesthetics anaesthetist anaesthetists anaesthetization anaesthetizations anaesthetize anaesthetized anaesthetizes anaesthetizing anagenesis anaglyph anaglyphic anaglyphs anagoge anagoges anagogic anagogically anagogies anagogy anagram anagrammatic anagrammatical anagrammatically anagrammatization anagrammatize anagrammatized anagrammatizes anagrammatizing anagrams anaheim anal analcime analcimes analcimic analcite analcites analecta analectic analects analemma analemmas analeptic analgesia analgesic analgesics analgetic analities anality anally analog analogic analogical analogically analogies analogist analogize analogized analogizes analogizing analogous analogously analogousness analogs analogue analogues analogy analphabet analphabetic analphabetics analphabetism analphabets analysand analysands analyses analysis analyst analysts analytic analytical analytically analyticities analyticity analytics analyzability analyzable analyzation analyze analyzed analyzer analyzers analyzes analyzing anamneses anamnesis anamnestic anamnestically anamorphic anamorphoses anamorphosis anapaest anapaests anapest anapestic anapests anaphase anaphases anaphasic anaphor anaphora anaphoras anaphoric anaphorically anaphors anaphrodisia anaphrodisiac anaphylactic anaphylactically anaphylactoid anaphylaxes anaphylaxis anaplasia anaplasmoses anaplasmosis anaplastic anapsid anapsids anarch anarchic anarchical anarchically anarchies anarchism anarchist anarchistic anarchists anarcho anarchs anarchy anarthria anarthric anarthrous anas anasarca anasarcas anasarcous anasazi anastasia anastigmat anastigmatic anastomose anastomosed anastomoses anastomosing anastomosis anastomotic anastrophe anatase anatases anathema anathemas anathematization anathematize anathematized anathematizes anathematizing anatolia anatolian anatolians anatomic anatomical anatomically anatomies anatomist anatomists anatomization anatomize anatomized anatomizes anatomizing anatomy anatropous anatto anattos anaxagoras anaximander ancestor ancestors ancestral ancestrally ancestress ancestresses ancestries ancestry anchor anchorage anchorages anchored anchoress anchoresses anchoret anchorets anchoring anchorite anchorites anchoritic anchoritically anchorless anchorman anchormen anchorperson anchorpersons anchors anchorwoman anchorwomen anchovies anchovy ancien anciens ancient anciently ancientness ancientry ancients ancilla ancillae ancillaries ancillary ancon ancona ancones ancress ancresses ancylostomiasis and andalucía andalusia andalusian andalusians andalusite andaman andamanese andamans andante andantes andantino andantinos andean andes andesite andesites andesitic andhra andiron andirons andorra andorran andorrans andouille andradite andrew andrews androcles androecia androecial androecium androgen androgenic androgenization androgenize androgenized androgenizes androgenizing androgens androgyne androgynous androgynously androgyny android androids andromache andromeda andronicus androsterone andré ands anecdota anecdotage anecdotal anecdotalist anecdotalists anecdotally anecdote anecdotes anecdotic anecdotical anecdotically anecdotist anecdotists anechoic anemia anemias anemic anemically anemics anemochory anemograph anemography anemometer anemometers anemometrical anemometry anemone anemones anemophilous anencephalic anencephalies anencephaly anent aneroid anesthesia anesthesias anesthesiologist anesthesiologists anesthesiology anesthetic anesthetically anesthetics anesthetist anesthetists anesthetization anesthetize anesthetized anesthetizes anesthetizing anestrus anestruses aneuploid aneuploidy aneurism aneurisms aneurysm aneurysmal aneurysms anew anfractuosities anfractuosity anfractuous anga angaria angarias angaries angary angel angela angeleno angelenos angeles angelfish angelfishes angelic angelica angelical angelically angelicas angelico angelina angelologist angelologists angelology angels angelus angeluses anger angered angering angerless angers angevin angevins angina anginal anginose angiocardiographic angiocardiography angiogenesis angiogram angiograms angiographic angiography angiology angioma angiomas angiomata angiomatous angiopathies angiopathy angioplasties angioplasty angiosarcoma angiosperm angiosperms angiotensin angkor angle angled angler anglerfish anglerfishes anglers angles anglesite angleworm angleworms anglia anglian anglians anglican anglicanism anglicans anglicanus anglice anglicism anglicisms anglicist anglicization anglicizations anglicize anglicized anglicizes anglicizing angling anglings anglo anglophil anglophile anglophiles anglophilia anglophiliac anglophilic anglophobe anglophobes anglophobia anglophobic anglophone anglophonic anglos angola angolan angolans angora angoras angostura angoulême angrier angriest angrily angriness angry angst angstrom angstroms anguilla anguillan anguillans anguish anguished anguishes anguishing angular angularities angularity angularly angularness angulate angulated angulately angulates angulating angulation angus anguses anhinga anhingas anhydride anhydrides anhydrite anhydrous anhydrously ani anil anile anilin aniline anilines anilingus anilins anility anils anima animadversion animadversions animadvert animadverted animadverting animadverts animal animalcula animalcule animalcules animalculum animalism animalist animalistic animality animalization animalize animalized animalizes animalizing animallike animally animals animas animate animated animatedly animately animateness animates animatic animating animation animations animato animator animators animis animism animist animistic animists animo animosities animosity animus animé anion anionic anionically anions aniracetam anis anise aniseed aniseeds aniseikonia aniseikonic anises anisette anisettes anisogamete anisogamic anisogamy anisometric anisometropia anisometropic anisotropic anisotropically anisotropism anisotropy anjou ankara ankerite ankerites ankh ankhs ankle anklebone anklebones ankles anklet anklets ankylose ankylosed ankyloses ankylosing ankylosis ankylotic anlace anlaces anlage anlagen anlages ann anna annalist annalistic annalists annals annan annapolis annapurna annates annatto annattos anne anneal annealed annealing anneals annelid annelidan annelidans annelids annex annexation annexational annexationism annexationist annexationists annexations annexed annexes annexing annie annihilability annihilable annihilate annihilated annihilates annihilating annihilation annihilations annihilative annihilator annihilators annihilatory anniversaries anniversary anno annotate annotated annotates annotating annotation annotations annotative annotator annotators announce announced announcement announcements announcer announcers announces announcing annoy annoyance annoyances annoyed annoyer annoyers annoying annoyingly annoys annual annualize annualized annualizes annualizing annually annuals annuitant annuitants annuities annuity annul annular annulate annulated annulation annulet annulets annuli annulled annulling annulment annulments annuls annulus annuluses annum annunciate annunciated annunciates annunciating annunciation annunciations annunciator annunciators annunciatory annus anoa anoas anodal anodally anode anodes anodic anodically anodization anodize anodized anodizes anodizing anodyne anodynes anoint anointed anointer anointers anointing anointment anointments anoints anole anoles anomalies anomalistic anomalistical anomalistically anomalous anomalously anomalousness anomaly anomic anomie anomy anon anonym anonymities anonymity anonymous anonymously anonymousness anonyms anopheles anopheline anorak anoraks anorectic anorectics anoretic anorexia anorexic anorexics anorexigenic anorthic anorthite anorthitic anorthosite anosmia anosmias anosmic anosognosia anosognosic anosognosics another anouilh anovulant anovulation anovulatory anoxemia anoxemias anoxemic anoxia anoxic ansate anschluss anselm anserine anson answer answerability answerable answerableness answerably answerback answered answerer answerers answering answers ant anta antacid antacids antae antaean antagonism antagonisms antagonist antagonistic antagonistically antagonists antagonize antagonized antagonizes antagonizing antarctic antarctica antares antas ante anteater anteaters antebellum antecede anteceded antecedence antecedent antecedently antecedents antecedes anteceding antecessor antecessors antechamber antechambers antechoir antechoirs anted antedate antedated antedates antedating antediluvian antediluvians anteed antefix antefixa antefixal antefixes anteing antelope antelopes antemeridian antemortem antenatal antenatally antenna antennae antennal antennas antennule antependia antependium antepenult antepenultima antepenultimate antepenultimates antepenults anterior anteriorly anteroom anterooms antes anthelia anthelion anthelmintic anthelmintics anthem anthemia anthemion anthems anther antheridia antheridium antherozoid anthers anthesis anthill anthills anthocyanin anthological anthologies anthologist anthologists anthologize anthologized anthologizer anthologizers anthologizes anthologizing anthology anthony anthozoan anthozoic anthracene anthraces anthracis anthracite anthracites anthracitic anthracnose anthracosis anthrax anthropic anthropical anthropocentric anthropocentrically anthropocentricity anthropocentrism anthropogenesis anthropogenic anthropoid anthropoidal anthropoids anthropologic anthropological anthropologically anthropologist anthropologists anthropology anthropometric anthropometrical anthropometrically anthropometrist anthropometry anthropomorph anthropomorphic anthropomorphically anthropomorphism anthropomorphist anthropomorphists anthropomorphization anthropomorphize anthropomorphized anthropomorphizes anthropomorphizing anthropomorphous anthropomorphs anthropopathism anthropophagi anthropophagic anthropophagous anthropophagus anthropophagy anthroposophical anthroposophist anthroposophy anthurium anti antiabortion antiabortionist antiabortionists antiacademic antiadministration antiaggression antiaging antiaircraft antialcohol antialcoholism antialien antiallergenic antiallergic antianemia antianxiety antiapartheid antiaphrodisiac antiaristocratic antiarrhythmic antiarthritic antiarthritis antiassimilation antiasthma antiatom antiatoms antiauthoritarian antiauthoritarianism antiauthority antibacklash antibacterial antibaryon antibes antibias antibillboard antibioses antibiosis antibiotic antibiotically antibiotics antiblack antiblackism antibodies antibody antiboss antibourgeois antiboycott antibug antibureaucratic antiburglar antiburglary antibusiness antibusing antic anticaking antically anticancer anticancerous anticapitalism anticapitalist anticapitalists anticarcinogen anticarcinogenic anticaries anticatalyst anticathode anticellulite anticensorship antichlor antichloristic anticholesterol anticholinergic anticholinesterase antichrist antichrists antichurch anticigarette anticipant anticipants anticipatable anticipate anticipated anticipates anticipating anticipation anticipations anticipative anticipatively anticipator anticipators anticipatory anticity anticlassical anticlerical anticlericalism anticlimactic anticlimactical anticlimactically anticlimax anticlimaxes anticlinal anticline anticlines anticling anticlockwise anticlotting anticoagulant anticoagulants anticoagulation anticodon anticold anticollision anticolonial anticolonialism anticolonialist anticolonialists anticommercial anticommercialism anticommunism anticommunist anticommunists anticompetitive anticonglomerate anticonservation anticonservationist anticonservationists anticonsumer anticonventional anticonvulsant anticonvulsive anticorporate anticorrosion anticorrosive anticorrosives anticorruption anticounterfeiting anticrack anticreative anticrime anticruelty antics anticult anticultural anticyclone anticyclones anticyclonic antidandruff antidefamation antidemocratic antidepressant antidepressants antidepression antidepressive antiderivative antiderivatives antidesegregation antidesertification antidesiccant antideuteron antidevelopment antidiabetic antidiarrheal antidilution antidiscrimination antidisestablishmentarian antidisestablishmentarianism antidogmatic antidotal antidotally antidote antidotes antidraft antidumping antieconomic antieducational antiegalitarian antielectron antielectrons antielite antielitism antielitist antielitists antiemetic antientropic antienvironmental antienzymatic antienzyme antienzymic antiepilepsy antiepileptic antierotic antiestablishment antiestrogen antietam antievolution antievolutionary antievolutionism antievolutionist antievolutionists antifamily antifascism antifascist antifascists antifashion antifashionable antifatigue antifebrile antifederalism antifederalist antifemale antifeminine antifeminism antifeminist antifeminists antifertility antifilibuster antiflu antifluoridationist antifoam antifoaming antifogging antiforeclosure antiforeign antiforeigner antiformalist antiformalists antifouling antifraud antifreeze antifreezes antifriction antifundamentalist antifundamentalists antifungal antifur antigalaxy antigambling antigay antigen antigene antigenes antigenic antigenically antigenicity antigens antiglare antiglobulin antigone antigovernment antigravity antigreenmail antigrowth antigua antiguan antiguans antiguerrilla antigun antihelium antihemophilic antihero antiheroes antiheroic antiheroine antiheroism antiherpes antihierarchical antihijack antihistamine antihistamines antihistaminic antihistorical antihomosexual antihuman antihumanism antihumanistic antihumanitarian antihunter antihunting antihydrogen antihypertensive antihypertensives antihysteric antijam antijamming antikickback antiknock antiknocks antilabor antileak antileprosy antilepton antileukemic antiliberal antiliberalism antilibertarian antiliquor antiliterate antilitter antilittering antilles antilock antilog antilogarithm antilogarithmic antilogarithms antilogical antilogies antilogs antilogy antilynching antimacassar antimacassars antimacho antimagnetic antimalaria antimalarial antimalarials antimale antiman antimanagement antimarijuana antimarket antimaterialism antimaterialist antimaterialists antimatter antimechanist antimechanists antimere antimeres antimerger antimeric antimetabolic antimetabolite antimetaphysical antimicrobial antimilitarism antimilitarist antimilitarists antimilitary antimiscegenation antimissile antimitotic antimodern antimodernist antimodernists antimonarchical antimonarchist antimonarchists antimonial antimonopolist antimonopolists antimonopoly antimony antimosquito antimusical antinarrative antinational antinationalist antinationalists antinatural antinature antinausea antineoplastic antinepotism antineutrino antineutrinos antineutron antineutrons anting antings antinodal antinode antinodes antinoise antinome antinomian antinomianism antinomians antinomic antinomies antinomy antinovel antinovelist antinuclear antinucleon antinucleons antiobesity antiobscenity antioch antiochus antiorganization antioxidant antioxidants antipapal antiparasitic antiparticle antiparticles antiparty antipasti antipasto antipastos antipathetic antipathetical antipathetically antipathies antipathy antiperiodic antipersonnel antiperspirant antiperspirants antipesticide antiphlogistic antiphon antiphonal antiphonally antiphonaries antiphonary antiphonies antiphons antiphony antiphrases antiphrasis antipiracy antiplague antiplaque antipleasure antipneumococcal antipoaching antipodal antipode antipodean antipodeans antipodes antipoetic antipolice antipolitical antipolitics antipollution antipollutionist antipope antipopes antipopular antiporn antipornographic antipornography antipot antipoverty antipredator antipress antiprofiteering antiprogressive antiprostitution antiproton antiprotons antipruritic antipsychotic antipsychotics antipyresis antipyretic antipyretics antipyrine antiquarian antiquarianism antiquarians antiquaries antiquark antiquary antiquate antiquated antiquatedness antiquates antiquating antiquation antique antiqued antiquely antiqueness antiquer antiquers antiques antiquing antiquities antiquity antirabies antirachitic antiracism antiracist antiracists antiracketeering antiradar antiradical antiradicalism antirape antirational antirationalism antirationalist antirationalists antirationality antirealism antirealist antirealists antirecession antirecessionary antired antireductionism antireductionist antireductionists antireflection antireflective antireform antiregulatory antireligion antireligious antirevolutionary antirheumatic antirheumatics antiriot antiritualism antirock antiroll antiromantic antiromanticism antiroyalist antiroyalists antirrhinum antirrhinums antirust antis antisatellite antischizophrenia antischizophrenic antiscience antiscientific antiscorbutic antisecrecy antisecretory antisegregation antiseizure antisentimental antiseparatist antiseparatists antisepses antisepsis antiseptic antiseptically antiseptics antisera antiserum antiserums antisex antisexist antisexists antisexual antisexuality antishark antiship antishock antishoplifting antiskid antislavery antisleep antislip antismog antismoke antismoker antismoking antismuggling antismut antisnob antisocial antisocialist antisocialists antisocially antispasmodic antispasmodics antispeculation antispeculative antispending antistate antistatic antisthenes antistick antistory antistress antistrike antistrophe antistrophes antistrophic antistrophically antistudent antisubmarine antisubsidy antisubversion antisubversive antisuicide antisymmetric antisyphilitic antitakeover antitank antitarnish antitax antitechnological antitechnology antiterrorism antiterrorist antiterrorists antitheft antitheoretical antitheses antithesis antithetic antithetical antithetically antithyroid antitobacco antitotalitarian antitoxic antitoxin antitoxins antitrade antitrades antitraditional antitrust antitruster antitrusters antitubercular antituberculosis antituberculous antitumor antitumoral antitussive antitype antitypes antityphoid antitypical antiulcer antiunemployment antiunion antiuniversity antiurban antivenin antivenins antiviolence antiviral antivirus antivitamin antivivisection antivivisectionist antivivisectionists antiwar antiwear antiwelfare antiwhaling antiwoman antiwrinkle antler antlered antlers antoinette antonine antonines antoninus antonio antonomasia antony antonym antonymic antonymous antonyms antonymy antra antral antre antres antrim antrorse antrorsely antrum ants antsier antsiest antsy antwerp anubis anuran anurans anuresis anuretic anuria anurias anuric anurous anus anuses anvil anvils anxieties anxiety anxious anxiously anxiousness any anybody anybody's anyhow anymore anyone anyone's anyplace anything anytime anyway anyways anywhere anywise anzio aorist aoristic aoristically aorists aorta aortae aortal aortas aortic aortographic aortography aosta aoudad aoudads apace apache apachean apaches apanage apanages aparejo aparejos apart apartheid apartment apartmental apartments apartness apatetic apathetic apathetical apathetically apathy apatite apatites ape apeak aped apelike apennine apennines aper aperient aperients aperiodic aperiodically aperiodicity aperitif aperitifs apertural aperture apertures aperçu aperçus apes apetalous apetaly apex apexes aphaereses aphaeresis aphaeretic aphagia aphagias aphanite aphanites aphanitic aphasia aphasiac aphasiacs aphasias aphasic aphasics aphelia aphelion apheresis apheses aphesis aphetic aphetically aphid aphides aphidian aphidians aphids aphis aphonia aphonias aphonic aphorism aphorisms aphorist aphoristic aphoristically aphorists aphorize aphorized aphorizes aphorizing aphotic aphrodisiac aphrodisiacal aphrodisiacs aphrodite aphyllies aphyllous aphylly apian apiarian apiaries apiarist apiarists apiary apical apically apices apiculate apicultural apiculture apiculturist apiece aping apio apios apis apish apishly apishness apivorous aplacental aplanatic aplasia aplasias aplastic aplenty aplite aplites aplitic aplomb apnea apneas apneic apnoea apnoeas apocalypse apocalypses apocalyptic apocalyptical apocalyptically apocalypticism apocalyptism apocalyptist apocalyptists apocarpies apocarpous apocarpy apochromatic apocope apocopes apocrine apocrypha apocryphal apocryphally apocryphalness apodal apodeictic apodictic apodictically apodoses apodosis apodous apoenzyme apogamic apogamies apogamous apogamy apogean apogee apogees apolitical apolitically apollinaris apollo apollonian apollos apollyon apologetic apologetically apologetics apologia apologias apologies apologist apologists apologize apologized apologizer apologizers apologizes apologizing apologue apologues apology apolune apolunes apomict apomictic apomictically apomicts apomixis apomixises apomorphine aponeuroses aponeurosis aponeurotic apophasis apophthegm apophthegms apophyge apophyges apophyllite apophysate apophyseal apophyses apophysis apoplectic apoplectically apoplexy aport aposematic aposematically aposiopeses aposiopesis aposiopetic aposporous apospory apostasies apostasy apostate apostates apostatize apostatized apostatizes apostatizing apostle apostlehood apostles apostleship apostleships apostolate apostolic apostolicity apostrophe apostrophes apostrophic apostrophize apostrophized apostrophizes apostrophizing apothecaries apothecary apothecia apothecial apothecium apothegm apothegmatic apothegmatical apothegmatically apothegms apothem apothems apotheoses apotheosis apotheosize apotheosized apotheosizes apotheosizing apotropaic apotropaically appal appalachia appalachian appalachians appall appalled appalling appallingly appalls appaloosa appaloosas appals appanage appanages apparat apparatchik apparatchiki apparatchiks apparats apparatus apparatuses apparel appareled appareling apparelled apparelling apparels apparent apparently apparentness apparition apparitional apparitions apparitor apparitors appeal appealability appealable appealed appealer appealers appealing appealingly appeals appear appearance appearances appeared appearing appears appeasable appeasably appease appeased appeasement appeasements appeaser appeasers appeases appeasing appel appellant appellants appellate appellation appellations appellative appellatively appellee appellees appels append appendage appendages appendant appendectomies appendectomy appended appendices appendicitis appendicular appending appendix appendixes appends apperceive apperceived apperceives apperceiving apperception apperceptive appertain appertained appertaining appertains appestat appestats appetence appetencies appetency appetent appetite appetites appetitive appetizer appetizers appetizing appetizingly appian applaud applaudable applaudably applauded applauder applauders applauding applauds applause applauses apple applejack applejacks apples applesauce appliance appliances applicability applicable applicably applicant applicants application applications applicative applicatively applicator applicators applicatory applied applier appliers applies appliqué appliquéd appliquéing appliqués apply applying appoggiatura appoint appointed appointee appointees appointing appointive appointment appointments appointor appoints appomattox apportion apportioned apportioning apportionment apportionments apportions appose apposed apposes apposing apposite appositely appositeness apposition appositional appositionally appositions appositive appositively appositives appraisable appraisal appraisals appraise appraised appraisement appraisements appraiser appraisers appraises appraising appraisingly appreciable appreciably appreciate appreciated appreciates appreciating appreciation appreciations appreciative appreciatively appreciativeness appreciator appreciators appreciatory apprehend apprehended apprehending apprehends apprehensible apprehensibly apprehension apprehensions apprehensive apprehensively apprehensiveness apprentice apprenticed apprentices apprenticeship apprenticeships apprenticing appressed apprise apprised apprises apprising apprize apprized apprizes apprizing approach approachability approachable approached approaches approaching approbate approbated approbates approbating approbation approbations approbative approbatory appropriable appropriate appropriated appropriately appropriateness appropriates appropriating appropriation appropriations appropriative appropriator appropriators approvable approvably approval approvals approve approved approver approvers approves approving approvingly approximate approximated approximately approximates approximating approximation approximations approximative approximatively appurtenance appurtenances appurtenant appétit apractic apraxia apraxias apraxic apricot apricots april aprils apriority apron aproned aproning aprons apropos après apse apses apsidal apsides apsis apt apteral apterous apteryx apteryxes aptitude aptitudes aptitudinal aptitudinally aptly aptness apulia apyrase apyrases apéritif apéritifs aqua aquacade aquacades aquacultural aquaculture aquaculturist aquae aquafortis aqualung aqualungs aquamarine aquamarines aquanaut aquanauts aquaplane aquaplaned aquaplaner aquaplaners aquaplanes aquaplaning aquarelle aquarellist aquaria aquarian aquarians aquarist aquarists aquarium aquariums aquarius aquas aquatic aquatically aquatics aquatint aquatinted aquatinter aquatinting aquatintist aquatints aquavit aqueduct aqueducts aqueous aquiculture aquifer aquiferous aquifers aquila aquilegia aquiline aquilinity aquinas aquitaine aquiver arab arabesque arabesques arabia arabian arabians arabic arabicize arabicized arabicizes arabicizing arability arabinose arabist arabists arabization arabize arabized arabizes arabizing arable arables arabs araby arachne arachnid arachnidan arachnidans arachnids arachnoid arachnoids arachnophobia aragon aragonese aragonite arak araks aralia aramaean aramaic arame aramean arapaho arapahoe arapahoes arapahos arapaima arapaimas ararat araucanian araucaria arawak arawakan arawakans arawaks arbalest arbalester arbalests arbalist arbalists arbiter arbiters arbitrable arbitrage arbitraged arbitrager arbitragers arbitrages arbitrageur arbitrageurs arbitraging arbitral arbitrament arbitraments arbitrarily arbitrariness arbitrary arbitrate arbitrated arbitrates arbitrating arbitration arbitrational arbitrations arbitrative arbitrator arbitrators arbor arboreal arboreally arboreous arbores arborescence arborescent arboreta arboretum arboretums arboricultural arboriculture arboricultures arborist arborists arborization arborize arborized arborizes arborizing arbors arborvitae arboviral arbovirology arbovirus arbutus arbutuses arc arcade arcaded arcades arcadia arcadian arcadians arcadias arcading arcady arcana arcane arcanum arcanums arccosine arced arch archaean archaeans archaeologic archaeological archaeologically archaeologist archaeologists archaeology archaeopteryx archaic archaically archaism archaisms archaist archaistic archaists archaize archaized archaizer archaizers archaizes archaizing archangel archangelic archangels archbishop archbishopric archbishoprics archbishops archconservative archconservatives archdeacon archdeaconate archdeaconries archdeaconry archdeacons archdeaconship archdiocesan archdiocese archdioceses archducal archduchess archduchesses archduchies archduchy archduke archdukes archean arched archegonia archegonial archegoniate archegonium archencephalon archenemies archenemy archenteric archenteron archeological archeologically archeologist archeologists archeology archeozoic archer archerfish archerfishes archeries archers archery arches archetypal archetypally archetype archetypes archetypical archetypically archfiend archfiends archidiaconal archidiaconate archidiaconates archiepiscopal archiepiscopality archiepiscopally archiepiscopate archiepiscopates archil archils archimandrite archimandrites archimedean archimedes archine archines arching archipelagic archipelago archipelagoes archipelagos architect architectonic architectonically architectonics architects architectural architecturally architecture architectures architrave architraves archival archive archived archives archiving archivist archivists archivolt archivolts archliberal archly archness archon archons archonship archonships archosaur archosaurs archpriest archrival archway archways arciform arcing arcked arcking arco arcs arcsine arctangent arctic arctically arctics arcturus arcuate arcuated arcuately arcuation ardeb ardebs ardencies ardency ardennes ardent ardently ardor ardors arduous arduously arduousness are area areal areally areas areaway areaways areca arecas aren aren't arena arenaceous arenas arenicolous areola areolae areolar areolas areolate areolation areole areoles areopagite areopagites areopagitic areopagus ares arete aretes arethusa arethusas argali argalis argent argentic argentiferous argentina argentine argentinean argentineans argentines argentinian argentinians argentite argentous argents argil argillaceous argillite argils arginase arginases arginine arginines argive argives argo argol argols argon argonaut argonauts argos argosies argosy argot argots arguable arguably argue argued arguer arguers argues argufied argufier argufiers argufies argufy argufying arguing argument argumenta argumentation argumentative argumentatively argumentativeness argumentive arguments argumentum argus arguses argyle argyles argyll argylls argyrol arhat arhats arhatship aria ariadne arian arianism arians arias ariboflavinosis arid aridity aridness ariel ariels aries arietta ariettas ariette ariettes aright arikara arikaras aril ariled arillate arils arimathaea arimathea arioso ariosos ariosto arise arisen arises arising arista aristae aristarchus aristas aristate aristides aristocracies aristocracy aristocrat aristocratic aristocratical aristocratically aristocrats aristophanes aristophanic aristotelean aristotelian aristotelianism aristotelians aristotle arithmetic arithmetical arithmetically arithmetician arithmeticians arithmetics arizona arizonan arizonans arizonian arizonians ark arkansan arkansans arkansas arks arkwright arles arm armada armadas armadillo armadillos armageddon armagh armament armamentaria armamentarium armamentariums armaments armature armatures armband armbands armchair armchairs armed armenia armenian armenians armentières armer armers armet armets armful armfuls armhole armholes armies armiger armigers arming arminian arminianism arminians arminius armistice armistices armless armlet armlets armlike armload armloads armoire armoires armor armored armorer armorers armorial armorially armorials armories armoring armorless armors armory armpit armpits armrest armrests arms armsful armstrong army armyworm armyworms arnatto arnattos arne arnheim arnhem arnica arnicas arno arnold aroid aroids aroint arointed arointing aroints aroma aromas aromatherapies aromatherapist aromatherapists aromatherapy aromatic aromatically aromaticity aromaticness aromatics aromatization aromatize aromatized aromatizes aromatizing arose around arousal arousals arouse aroused arouses arousing arpanet arpeggio arpeggios arpent arpents arquebus arquebuses arracacha arrack arracks arraign arraigned arraigner arraigning arraignment arraignments arraigns arrange arranged arrangement arrangements arranger arrangers arranges arranging arrant arrantly arras array arrayal arrayals arrayed arrayer arrayers arraying arrays arrear arrearage arrears arrest arrestant arrestants arrested arrestee arrestees arrester arresters arresting arrestingly arrestment arrestments arrestor arrestors arrests arrhythmia arrhythmias arrhythmic arrhythmically arriba arris arrises arrival arrivals arrive arrived arrivederci arriver arrivers arrives arriving arriviste arrière arroba arrobas arrogance arrogant arrogantly arrogate arrogated arrogates arrogating arrogation arrogations arrogative arrogator arrondissement arrondissements arrow arrowed arrowhead arrowheads arrowing arrowroot arrowroots arrows arrowwood arrowworm arrowworms arrowy arroyo arroyos arse arsenal arsenals arsenate arsenates arsenic arsenical arsenide arsenides arsenious arsenite arsenites arsenopyrite arses arshin arshins arsine arsines arsis arson arsonist arsonists arsonous arsons arsphenamine art artaxerxes arte artel artels artemis artemisia arterial arterialization arterialize arterialized arterializes arterializing arterially arterials arteries arteriogram arteriograms arteriographic arteriography arteriolar arteriole arterioles arterioloscleroses arteriolosclerosis arterioscleroses arteriosclerosis arteriosclerotic arteriovenous arteritis artery artesian artful artfully artfulness arthralgia arthralgic arthritic arthritically arthritics arthritides arthritis arthrodesis arthrogram arthrograms arthrography arthrogryposis arthromere arthromeric arthropathy arthropod arthropodal arthropodous arthropods arthroscope arthroscopic arthroscopically arthroscopies arthroscopy arthroses arthrosis arthrospore arthrotomy arthur arthurian artichoke artichokes article articled articles articling articulable articulacy articular articularly articulate articulated articulately articulateness articulates articulating articulation articulations articulative articulator articulators articulatory artier artiest artifact artifacts artifactual artifice artificer artificers artifices artificial artificialities artificiality artificially artificialness artilleries artillerist artillerists artillery artilleryman artillerymen artily artiness artiodactyl artiodactylous artisan artisans artisanship artist artiste artistes artistic artistically artistry artists artless artlessly artlessness artois arts artwork artworks arty aruba arugula arum arums arunachal aryan aryans aryl arytenoid arytenoidal arête arêtes as asafetida asafetidas asafoetida asafoetidas asbestic asbestine asbestos asbestoses asbestosis asbestotic asbestus asbestuses ascariasis ascarid ascarides ascarids ascaris ascend ascendable ascendance ascendancy ascendant ascendantly ascendants ascended ascendence ascendency ascendent ascendents ascender ascenders ascendible ascending ascendingly ascends ascension ascensional ascensions ascensive ascent ascents ascertain ascertainable ascertainableness ascertainably ascertained ascertaining ascertainment ascertainments ascertains asceses ascesis ascetic ascetical ascetically asceticism ascetics asci ascidia ascidian ascidians ascidiate ascidiform ascidium ascii ascites ascitic ascocarp ascocarps ascogonia ascogonium ascomycete ascomycetes ascomycetous ascorbate ascorbic ascospore ascosporic ascosporous ascot ascots ascribable ascribe ascribed ascribes ascribing ascription ascriptions ascriptive ascus asdic asdics asepalous asepses asepsis aseptic aseptically asepticism asexual asexuality asexualize asexualized asexualizes asexualizing asexually ash ashamed ashamedly ashanti ashcan ashcans ashed ashen asher ashes asheville ashier ashiest ashiness ashing ashlar ashlars ashless ashore ashram ashrams ashton ashtoreth ashtray ashtrays ashy asia asian asianization asians asiatic asiatics aside asides asinine asininely asininity asinorum ask askance askant asked asker askers askeses askesis askew askewness asking asks aslant asleep aslope aslosh asmodeus asocial asp asparaginase asparagine asparagus aspartame aspartate aspartic aspartokinase aspasia aspect aspects aspectual aspen aspens asperate asperated asperates asperating asperges aspergill aspergilla aspergilli aspergillosis aspergillum aspergillums aspergillus asperities asperity asperse aspersed asperses aspersing aspersion aspersions asphalt asphalted asphaltic asphalting asphaltite asphaltites asphalts asphaltum aspheric aspherical asphodel asphodels asphyxia asphyxiant asphyxiate asphyxiated asphyxiates asphyxiating asphyxiation asphyxiations asphyxiator asphyxiators aspic aspics aspidistra aspidistras aspirant aspirants aspirate aspirated aspirates aspirating aspiration aspirations aspirator aspirators aspiratory aspire aspired aspirer aspirers aspires aspirin aspiring aspiringly aspirins asps asquint ass assagai assagais assai assail assailable assailableness assailant assailants assailed assailer assailers assailing assailment assails assais assam assassin assassinate assassinated assassinates assassinating assassination assassinations assassinative assassinator assassins assault assaulted assaulter assaulters assaulting assaultive assaultively assaultiveness assaults assay assayable assayed assayer assayers assaying assays assegai assegais assemblage assemblages assemblagist assemble assembled assembler assemblers assembles assemblies assembling assembly assemblyman assemblymen assemblywoman assemblywomen assent assentation assented assenter assenters assenting assentingly assentive assentiveness assentor assentors assents assert assertable asserted assertedly asserter asserters assertible asserting assertion assertional assertions assertive assertively assertiveness assertor assertors asserts asses assess assessable assessed assesses assessing assessment assessments assessor assessorial assessors asset assets asseverate asseverated asseverates asseverating asseveration asseverations asseverative asshole assholes assibilate assibilated assibilates assibilating assibilation assiduities assiduity assiduous assiduously assiduousness assign assignability assignable assignably assignat assignation assignational assignations assignats assigned assignee assignees assigner assigners assigning assignment assignments assignor assignors assigns assimilability assimilable assimilate assimilated assimilates assimilating assimilation assimilationism assimilationist assimilationists assimilations assimilative assimilator assimilators assimilatory assiniboin assiniboins assisi assist assistance assistant assistants assistantship assistantships assisted assister assisters assisting assists assize assizes associability associable associableness associate associated associates associateship associateships associating association associational associationism associationist associationistic associations associative associatively associativity assoil assoiled assoiling assoilment assoils assonance assonances assonant assonantal assonants assort assortative assorted assorter assorters assorting assortment assortments assorts assuage assuaged assuagement assuagements assuages assuaging assuasive assumability assumable assumably assume assumed assumedly assumer assumers assumes assuming assumingly assumpsit assumption assumptions assumptive assumptively assurable assurance assurances assure assured assuredly assuredness assureds assurer assurers assures assurgency assurgent assuring assuror assurors assyria assyrian assyrians assyriological assyriologist assyriologists assyriology astarboard astarte astasia astasias astatic astatically astaticism astatine astatines aster asteria asterias asteriated asterisk asterisked asterisking asteriskless asterisks asterism asterismal asterisms astern asternal asteroid asteroidal asteroids asters asthenia asthenic asthenics asthenopia asthenopic asthenosphere asthenospheric asthma asthmatic asthmatically asthmatics astigmatic astigmatically astigmatism astigmatisms astilbe astir astomatal astomatous astomous astonied astonish astonished astonishes astonishing astonishingly astonishment astonishments astor astoria astound astounded astounding astoundingly astounds astrachan astrachans astraddle astragal astragalar astragali astragals astragalus astrakhan astrakhans astral astrally astraphobia astray astrictive astride astringency astringent astringently astringents astrionics astrobiological astrobiologist astrobiologists astrobiology astrochemist astrochemistry astrocyte astrocytic astrocytoma astrocytomas astrocytomata astrodome astrodomes astrodynamic astrodynamics astrogate astrogated astrogates astrogating astrogation astrogator astrogeologist astrogeology astrolabe astrolabes astrologer astrologers astrologic astrological astrologically astrology astrometric astrometrical astrometry astronaut astronautic astronautical astronautically astronautics astronauts astronavigation astronavigator astronomer astronomers astronomic astronomical astronomically astronomy astrophotographer astrophotographers astrophotographic astrophotography astrophysical astrophysicist astrophysicists astrophysics astrosphere asturian asturians asturias astute astutely astuteness astyanax astylar asuncion asunción asunder aswan aswarm aswirl aswoon asylum asylums asymmetric asymmetrical asymmetrically asymmetries asymmetry asymptomatic asymptomatically asymptote asymptotes asymptotic asymptotical asymptotically asynapsis asynchronism asynchronous asynchronously asynchrony asyndetic asyndetically asyndeton asyntactic at atalanta ataman atamans atamasco atapuerca ataractic ataraxia ataraxias ataraxic ataraxics ataturk atavism atavisms atavist atavistic atavistically atavists ataxia ataxias ataxic ataxics ataxies ataxy ate atelectasis atelier ateliers atemoya atemporal athabascan athabaskan athanasian athanasius atheism atheist atheistic atheistical atheistically atheists atheling athelings athelstan athena athenaeum athenaeums atheneum atheneums athenian athenians athens atheoretical atherogenesis atherogenic atherogenicity atheroma atheromas atheromata atheromatosis atheromatous atheroscleroses atherosclerosis atherosclerotic atherosclerotically athirst athlete athletes athletic athletically athleticism athletics athodyd athodyds athos athwart athwartship atilt atingle ation atlanta atlantan atlantes atlantic atlanticism atlanticist atlantis atlas atlases atlatl atlatls atman atmans atmometer atmometers atmometric atmometry atmosphere atmospheres atmospheric atmospherically atmospherics atmospherium atoll atolls atom atomic atomically atomicity atomies atomism atomisms atomist atomistic atomistical atomistically atomists atomization atomize atomized atomizer atomizers atomizes atomizing atoms atomy atonable atonal atonalism atonalist atonalistic atonalities atonality atonally atone atoneable atoned atonement atonements atoner atoners atones atonic atonicity atonics atonies atoning atony atop atopic atopies atopy atoxic atrabilious atrabiliousness atrazine atrazines atremble atresia atresias atresic atreus atria atrial atrioventricular atrip atrium atriums atrocious atrociously atrociousness atrocities atrocity atrophic atrophied atrophies atrophy atrophying atropine atropines atropins attaboy attach attachable attached attacher attachers attaches attaching attachment attachments attaché attachés attack attacked attacker attackers attacking attackman attackmen attacks attain attainability attainable attainableness attainably attainder attainders attained attaining attainment attainments attains attaint attainted attainting attaints attar attars attelet attempt attemptable attempted attempter attempters attempting attempts attend attendance attendances attendant attendantly attendants attended attendee attendees attender attenders attending attends attention attentional attentions attentive attentively attentiveness attenuate attenuated attenuates attenuating attenuation attenuations attenuator attenuators attest attestant attestation attestations attested attester attesters attesting attestor attestors attests attic attica atticism atticisms attics atticus attila attire attired attires attiring attitude attitudes attitudinal attitudinize attitudinized attitudinizes attitudinizing attoampere attoamperes attobecquerel attobecquerels attocandela attocandelas attocoulomb attocoulombs attofarad attofarads attogram attograms attohenries attohenry attohenrys attohertz attojoule attojoules attokelvin attokelvins attolumen attolumens attolux attometer attometers attomole attomoles attonewton attonewtons attoohm attoohms attopascal attopascals attoradian attoradians attorn attorned attorney attorneys attorneyship attorning attornment attorns attosecond attoseconds attosiemens attosievert attosieverts attosteradian attosteradians attotesla attoteslas attovolt attovolts attowatt attowatts attoweber attowebers attract attractable attractant attractants attracted attracter attracting attraction attractions attractive attractively attractiveness attractor attractors attracts attributable attribute attributed attributer attributers attributes attributing attribution attributional attributions attributive attributively attributiveness attributives attributor attrit attrite attrited attrites attriting attrition attritional attrits attritted attritting attune attuned attunement attunements attunes attuning atwitter atypical atypicality atypically au aubade aubades auberge auberges aubergine aubergines auburn auburns aubusson auckland auction auctioned auctioneer auctioneered auctioneering auctioneers auctioning auctions auctorial aucuba audacious audaciously audaciousness audacities audacity auden audi audial audibility audible audibleness audibles audibly audience audiences audile audiles auding audings audio audiocassette audiogenic audiogram audiograms audiological audiologist audiologists audiology audiometer audiometers audiometric audiometry audiophile audiophiles audios audiotape audiotaped audiotapes audiotaping audiotyping audiotypist audiotypists audiovisual audiovisuals audit auditable audited auditing audition auditioned auditioning auditions auditive auditor auditoria auditorium auditoriums auditors auditory audits audubon auf aufklarung aufklärung augean augend augends auger augers aught aughts augite augites augitic augment augmentable augmentation augmentations augmentative augmented augmenter augmenters augmenting augmentor augmentors augments augsburg augur augural augured auguries auguring augurs augury august augusta augustan augustans augustine augustinian augustinianism augustinians augustinism augustly augustness augusts augustus auk auklet auklets auks auld aunt aunthood aunthoods auntie aunties auntlike auntly aunts aura aurae aural aurally aurar auras aureate aureately aureateness aurei aurelian aurelius aureola aureolas aureole aureoles aureomycin aureus auric auricle auricled auricles auricula auriculae auricular auricularly auriculas auriculate auriculately auriferous auriform auriga aurochs aurora auroral aurorally auroras aurorean aurous aurum auschwitz auscultate auscultated auscultates auscultating auscultation auscultations auscultative auscultatory ausform ausformed ausforming ausforms auslander auspex auspicate auspicated auspicates auspicating auspice auspices auspicious auspiciously auspiciousness aussie aussies austen austenite austenitic austere austerely austereness austerer austerest austerities austerity austerlitz austin austral australasia australasian australes australia australian australians australis australoid australopithecine australopithecus austria austrian austrians austro autacoid autacoidal autacoids autarch autarchic autarchical autarchies autarchy autarkic autarkical autarkies autarky autecological autecology auteur auteurism auteurist auteurs authentic authentically authenticate authenticated authenticates authenticating authentication authentications authenticator authenticators authenticity author authored authoress authoresses authorial authoring authoritarian authoritarianism authoritarians authoritative authoritatively authoritativeness authorities authority authorization authorizations authorize authorized authorizer authorizers authorizes authorizing authors authorship autism autist autistic autistically auto autoantibody autobahn autobahns autobiographer autobiographers autobiographic autobiographical autobiographically autobiographies autobiography autobus autobuses autobusses autocatalyses autocatalysis autocatalytic autocatalytically autocephalous autochthon autochthones autochthonism autochthonous autochthonously autochthons autochthony autoclave autoclaved autoclaves autoclaving autocollimator autocollimators autocorrelation autocracies autocracy autocrat autocratic autocratical autocratically autocrats autocross autodidact autodidactic autodidacts autodyne autodynes autoecious autoeciously autoecism autoed autoerotic autoeroticism autoerotism autofocus autofocuses autogamic autogamies autogamous autogamy autogeneses autogenesis autogenetic autogenetically autogenic autogenies autogenous autogenously autogeny autogiro autogiros autograft autografted autografting autografts autograph autographed autographic autographical autographically autographing autographs autography autogyro autogyros autoharp autohypnosis autohypnotic autoimmune autoimmunities autoimmunity autoimmunization autoinfection autoinfections autoing autoinoculable autoinoculation autointoxication autoloader autoloaders autoloading autologous autolycus autolysate autolysin autolysis autolytic autolyze autolyzed autolyzes autolyzing automaker automakers automat automata automatable automate automated automates automatic automatically automaticity automatics automating automation automations automatism automatist automative automatization automatize automatized automatizes automatizing automaton automatons automatous automats automobile automobiles automobilist automobilists automorphism automorphisms automotive autonomic autonomically autonomies autonomist autonomists autonomous autonomously autonomy autopen autophagy autopiler autopilot autopilots autoplastic autoplastically autoplasty autopolyploid autopolyploidy autopsic autopsical autopsied autopsies autopsist autopsy autopsying autoradiogram autoradiograms autoradiograph autoradiographic autoradiography autorotate autorotated autorotates autorotating autorotation autoroute autos autosensor autosexing autosomal autosomally autosome autosomes autostrada autostradas autosuggest autosuggested autosuggestibility autosuggestible autosuggesting autosuggestion autosuggestive autosuggests autotelic autotetraploid autotetraploids autotetraploidy autotomic autotomies autotomize autotomized autotomizes autotomizing autotomous autotomy autotoxemia autotoxic autotoxin autotransformer autotroph autotrophic autotrophically autotrophy autoworker autre autumn autumnal autumnally autumns autunite autunites auvergne aux auxesis auxetic auxetically auxiliaries auxiliary auxin auxinic auxinically auxins auxotroph auxotrophic auxotrophy avail availability available availableness availably availed availing availingly avails avalanche avalanched avalanches avalanching avalon avant avarice avaricious avariciously avariciousness avascular avascularity avast avatar avatars avaunt ave avellan avellane avenge avenged avenger avengers avenges avenging avengingly avens aventail aventails aventine aventurine avenue avenues aver average averaged averagely averageness averages averaging averment averments avernus averrable averred averring avers averse aversely averseness aversion aversions aversive aversively aversiveness avert avertable averted avertible averting averts aves avesta avgas avgases avgasses avian aviaries aviarist aviarists aviary aviate aviated aviates aviating aviation aviator aviators aviatrices aviatrix aviatrixes aviculture aviculturist avid avidin avidins avidities avidity avidly avidness avifauna avifaunal avifaunas avignon avila avion avionic avionics avirulence avirulent avis avises avitaminoses avitaminosis avitaminotic aviv avo avocado avocadoes avocados avocation avocational avocationally avocations avocet avocets avogadro avoid avoidable avoidably avoidance avoidances avoided avoider avoiders avoiding avoids avoirdupois avon avos avouch avouched avouches avouching avouchment avouchments avow avowable avowably avowal avowals avowed avowedly avower avowers avowing avows avulse avulsed avulses avulsing avulsion avulsions avuncular aw await awaited awaiting awaits awake awaked awaken awakened awakener awakeners awakening awakenings awakens awakes awaking award awardable awarded awardee awardees awarder awarders awarding awards aware awareness awash away awayness awe aweary aweather awed aweigh aweless awes awesome awesomely awesomeness awestricken awestruck awful awfully awfulness awhile awhirl awing awkward awkwardly awkwardness awl awless awls awn awned awning awninged awnings awnless awns awoke awoken awry ax axe axed axel axels axenic axenically axes axial axiality axially axil axile axilla axillae axillar axillaries axillars axillary axils axing axiological axiologically axiologist axiology axiom axiomatic axiomatically axiomatization axiomatizations axiomatize axiomatized axiomatizes axiomatizing axioms axis axisymmetric axisymmetrical axisymmetrically axisymmetry axle axles axletree axletrees axman axmen axminster axolotl axolotls axon axonal axone axonemal axoneme axones axonometric axons axoplasm axoplasmic axoplasms ay ayah ayahs ayatollah ayatollahs aye ayers ayes ayin ayins azalea azaleas azathioprine azeotrope azeotropic azeotropy azerbaijan azerbaijani azerbaijanis azide azides azido azidothymidine azimuth azimuthal azimuthally azimuths azine azines azo azoic azole azoles azonal azonic azorean azores azorian azotemia azotemias azotemic azoth azoths azotobacter azoturia azoturias aztec aztecan aztecs azure azures azurite azurites azygos azygoses azygous aîné aînée añu b baa baaed baaing baal baalbek baalim baalism baals baas baba babar babas babassu babassus babbage babbitt babbittry babbitts babble babbled babblement babbler babblers babbles babbling babcock babe babel babels babes babesbabel babesia babesias babesiosis babied babier babies babiest babirusa babirusas babka babkas baboo baboon baboonery baboonish baboons baboos babu babul babuls babus babushka babushkas baby babyhood babying babyish babylon babylonia babylonian babylonians babysat babysitter babysitters babysitting baccalaureate baccalaureates baccarat baccate bacchanal bacchanalia bacchanalian bacchanalians bacchanalias bacchanals bacchant bacchante bacchantes bacchantic bacchants bacchic bacchus bach bached bachelor bachelor's bachelorhood bachelorhoods bachelors bachelorship baches baching bacillar bacillary bacilli bacillus bacitracin back backache backaches backbeat backbeats backbencher backbenchers backbend backbends backbit backbite backbiter backbiters backbites backbiting backbitten backboard backboards backbone backboned backbones backbreaker backbreakers backbreaking backcloth backcountry backcourt backcourtman backcourtmen backcross backcrossed backcrosses backcrossing backdate backdated backdates backdating backdoor backdoors backdrop backdrops backed backelordom backer backers backfield backfields backfill backfilled backfilling backfills backfire backfired backfires backfiring backgammon background backgrounder backgrounders backgrounds backhand backhanded backhandedly backhandedness backhander backhanders backhanding backhands backhoe backhoes backhouse backhouses backing backings backlash backlashed backlasher backlashers backlashes backlashing backless backlight backlighted backlighting backlights backlist backlisted backlisting backlists backlit backlog backlogged backlogging backlogs backorder backorders backpack backpacked backpacker backpackers backpacking backpacks backpedal backpedaled backpedaling backpedalled backpedalling backpedals backpressure backpressures backquote backquotes backrest backrests backroom backrooms backrush backrushes backs backsaw backsaws backscatter backscattered backscattering backscatters backseat backseats backset backsets backshore backshores backside backsides backslap backslapped backslapper backslappers backslapping backslaps backslash backslashes backslid backslidden backslide backslider backsliders backslides backsliding backspace backspaced backspaces backspacing backspin backspins backstab backstabbed backstabber backstabbers backstabbing backstabs backstage backstairs backstay backstays backstitch backstitched backstitches backstitching backstop backstopped backstopping backstops backstretch backstretches backstroke backstrokeer backstrokeers backstrokes backstroking backswept backswimmer backswimmers backswing backswings backsword backswords backtrace backtrack backtracked backtracking backtracks backup backups backward backwardly backwardness backwards backwash backwashes backwater backwaters backwoods backwoodsman backwoodsmen backyard backyards bacon baconian baconians bacons bacteremia bacteremic bacteremically bacteria bacterial bacterially bactericidal bactericidally bactericide bactericides bacterin bacterins bacteriocin bacteriocins bacteriogenic bacteriologic bacteriological bacteriologically bacteriologist bacteriologists bacteriology bacteriolyses bacteriolysis bacteriolytic bacteriophage bacteriophages bacteriophagic bacteriophagy bacteriorhodopsin bacteriorhodopsins bacterioscopy bacteriostases bacteriostasis bacteriostat bacteriostatic bacteriostats bacterium bacteriuria bacterization bacterizations bacterize bacterized bacterizes bacterizing bacteroid bactria bactrian baculiform bad badajoz badass badasses baddie baddies baddy bade baden badge badged badger badgered badgering badgers badges badging badinage badinages badland badlands badly badman badmen badminton badmouth badmouthed badmouthing badmouths badness baedeker baedekers bael baels baffin baffle baffled bafflegabs bafflement bafflements baffler bafflers baffles baffling bafflingly bag bagasse bagasses bagatelle bagatelles bagehot bagel bagels bagful bagfuls baggage bagged bagger baggers baggier baggiest baggily bagginess bagging baggings baggy baghdad baglike bagman bagmen bagnio bagnios bagpipe bagpiper bagpipers bagpipes bags bagsful baguette baguettes bagwig bagwigs bagworm bagworms bah bahama bahaman bahamas bahamian bahamians bahawalpur bahrain bahraini bahrainis baht bahts bail bailable bailed bailee bailees bailer bailers bailey baileys bailie bailies bailiff bailiffs bailiffship bailing bailiwick bailiwicks bailment bailments bailor bailors bailout bailouts bails bailsman bailsmen baird bairn bairns bait baited baiter baiters baiting baits baiza baizas baize baizes bake baked bakelite baker bakeries bakers bakersfield bakery bakes bakeshop bakeshops baking baklava baklavas baksheesh balaam balaclava balaclavas balalaika balalaikas balance balanced balancer balancers balances balancing balas balases balata balatas balboa balboas balbriggan balconies balcony bald baldachin baldachins balder balderdash baldest baldhead baldheaded baldheads balding baldish baldly baldness baldpate baldpates baldric baldrics baldwin baldwins bale balearic balearics baled baleen baleens balefire balefires baleful balefully balefulness baler balers bales balfour bali balinese baling balk balkan balkanization balkanize balkanized balkanizes balkanizing balkans balked balker balkers balkier balkiest balkiness balking balkline balklines balks balky ball ballad ballade balladeer balladeers ballades balladic balladist balladists balladry ballads ballantyne ballarat ballast ballasted ballasting ballasts ballcarrier ballcarriers balled ballerina ballerinas ballet balletic balletomane balletomanes balletomania ballets ballflower ballflowers ballgame ballgames balling ballista ballistae ballistic ballistically ballistician ballisticians ballistics ballistocardiogram ballistocardiograms ballistocardiograph ballistocardiographs ballistocardiography ballon ballonet ballonets ballons balloon ballooned ballooning balloonist balloonists balloons ballot balloted balloter balloters balloting ballots ballottement ballottements ballpark ballparks ballplayer ballplayers ballpoint ballpoints ballroom ballrooms balls ballsier ballsiest ballsy bally ballyhoo ballyhooed ballyhooing ballyhoos ballyrag ballyragged ballyragging ballyrags balm balmacaan balmacaans balmier balmiest balmily balminess balmoral balmorals balms balmy balneal balneology baloney baloneys balsa balsam balsamic balsamroot balsamroots balsams balsas balsasbalsa balt balthazar baltic baltimore baltimorean baltimoreans balts baluchi baluchis baluchistan baluchithere baluchitheres baluster balusters balustrade balustrades balzac bam bamako bambara bambini bambino bambinos bamboo bamboos bamboozle bamboozled bamboozlement bamboozler bamboozlers bamboozles bamboozling ban banach banal banalities banality banalize banalized banalizes banalizing banally banana bananas banausic banco bancos bancroft band banda bandage bandaged bandager bandagers bandages bandaging bandana bandanas bandanna bandannas bandbox bandboxes bandeau bandeaus bandeaux banded bander banderilla banderillas banderillero banderilleros banderol banderole banderoles banderols banders bandicoot bandicoots bandied bandies banding bandings bandit banditry bandits banditti bandjarmasin bandleader bandleaders bandmaster bandmasters bandog bandogs bandoleer bandoleers bandolier bandoliers bandoneon bandoneonist bandoneonists bandoneons bandora bandoras bandore bandores bands bandsman bandsmen bandstand bandstands bandwagon bandwagoning bandwagons bandwidth bandwidths bandy bandying bane baneberries baneberry baneful banefully banes bang bangalore banged banger bangers banging bangkok bangkoks bangladesh bangladeshi bangladeshis bangle bangles bangor bangs bangtail bangtails bangui bani baning banish banished banisher banishers banishes banishing banishment banishments banister banisters banjo banjoes banjoist banjoists banjos bank bankability bankable bankbook bankbooks bankcard bankcards banked banker bankerly bankers banking bankings banknote banknotes bankroll bankrolled bankroller bankrollers bankrolling bankrolls bankrupt bankruptcies bankruptcy bankrupted bankrupting bankruptive bankrupts banks banksia banksias bankside banksides banned banner bannered banneret bannerets bannerette bannerettes bannering bannerol bannerols banners banning bannister bannisters bannock bannocks banns banquet banqueted banqueter banqueters banqueting banquets banquette banquettes banquo bans banshee banshees banshie banshies bantam bantams bantamweight bantamweights banter bantered banterer banterers bantering banteringly banters bantling bantlings bantu bantus bantustan bantustans banyan banyans banzai banzais baobab baobabs baptisia baptisias baptism baptismal baptismally baptisms baptist baptisteries baptistery baptistries baptistry baptists baptize baptized baptizer baptizers baptizes baptizing bar barabbas barathea baratheas barb barbadian barbadians barbados barbara barbarian barbarianism barbarians barbaric barbarically barbarism barbarisms barbarities barbarity barbarization barbarize barbarized barbarizes barbarizing barbarossa barbarous barbarously barbarousness barbary barbasco barbascos barbate barbe barbecue barbecued barbecuer barbecuers barbecues barbecuing barbed barbedness barbel barbell barbellate barbells barbels barber barbered barbering barberries barberry barbers barbershop barbershops barbes barbet barbets barbette barbettes barbican barbicans barbicel barbicels barbing barbirolli barbital barbitals barbitone barbitones barbiturate barbiturates barbituric barbizon barbs barbuda barbudan barbudans barbule barbules barbwire barbwires barca barcarole barcaroles barcas barcelona barclay barcode barcodes bard bardacious barde barded bardes bardic barding bardolino bardolinos bards bare bareback barebacked bared barefaced barefacedly barefacedness barefoot barefooted barege bareges barehanded barehandedness bareheaded barelegged bareleggedness barely bareness barents barer bares barest barf barfed barfing barflies barfly barfs bargain bargained bargainer bargainers bargaining bargains barge bargeboard bargeboards barged bargee bargees bargello bargellos bargeman bargemen barges barghest barghests barging bargirl bargirls barhop barhoping barhopped barhops bari bariatric bariatrician bariatricians bariatrics baric barilla barillas baring barite barites baritonal baritone baritones barium bark barked barkeep barkeeper barkeepers barkeeps barkentine barkentines barker barkers barkier barkiest barking barkless barks barky barley barleycorn barleycorns barlow barlows barm barmaid barmaids barman barmecidal barmecide barmen barmier barmiest barms barmy barn barnabas barnacle barnacled barnacles barnardo barnburner barnburners barns barnstorm barnstormed barnstormer barnstormers barnstorming barnstorms barnum barny barnyard barnyards barogram barograms barograph barographic barographs barolo barolos barometer barometers barometric barometrical barometrically barometry baron baronage baronages baroness baronesses baronet baronetage baronetages baronetcies baronetcy baronetess baronets barong barongs baronial baronies barons barony baroque baroquely baroques baroreceptor baroreceptors barotseland barouche barouches barque barquentine barquentines barques barrack barracked barracker barrackers barracking barracks barracoon barracoons barracuda barracudas barrage barraged barrages barraging barramunda barramundas barramundi barramundis barranca barrancas barranco barrancos barrater barraters barrator barrators barratries barratrous barratrously barratry barre barred barrel barreled barrelful barrelfuls barrelhead barrelheads barrelhouse barrelhouses barreling barrelled barrelling barrels barren barrenly barrenness barrens barres barrette barrettes barricade barricaded barricader barricaders barricades barricading barrier barriers barring barrio barrios barrister barristers barroom barrooms barrow barrows barry barrymore bars barstool barstools bartend bartended bartender bartenders bartending bartends barter bartered barterer barterers bartering barters bartholomew bartizan bartizaned bartizans bartlett bartletts bartók bartókian baruch barware barycenter barycenters baryon baryonic baryons barysphere baryspheres baryta barytas baryte barytes barytone barytones bas basal basally basalt basaltic basalts bascule bascules base baseball baseballs baseboard baseboards baseborn baseburner baseburners based basel baseless baselessly baseline baselines basely baseman basemen basement basementless basements baseness basenji basenjis baser baserunning bases basest bash bashaw bashaws bashed basher bashers bashes bashful bashfully bashfulness bashing basic basically basichromatic basicities basicity basics basidia basidial basidiocarp basidiocarps basidiomycete basidiomycetes basidiomycetous basidiospore basidiospores basidiosporous basidium basification basified basifier basifiers basifies basifixed basify basifying basil basilar basilica basilican basilicas basilicata basilisk basilisks basils basin basinal basined basinet basinets basing basins basipetal basipetally basis bask basked baskerville basket basketball basketballs basketful basketfuls basketlike basketry baskets basketsful basketwork basking basks basle basophil basophile basophiles basophilia basophilias basophilic basophils basotho basque basques basra bass basses basset bassets bassett bassi bassinet bassinets bassist bassists basso bassoon bassoonist bassoonists bassoons bassos basswood basswoods bast bastard bastardies bastardization bastardizations bastardize bastardized bastardizes bastardizing bastardly bastards bastardy baste basted baster basters bastes bastille bastilles bastinado bastinadoed bastinadoes bastinadoing basting bastings bastion bastioned bastions bastnaesite bastnaesites basutoland bat batavia batavian batavians batboy batboys batch batched batcher batchers batches batching bate bateau bateaux bated bates batfish batfishes batfowl batfowled batfowling batfowls batgirl batgirls bath bathe bathed bather bathers bathes bathetic bathetically bathhouse bathhouses bathing bathmat bathmats batholith batholithic batholiths bathometer bathometers bathophobia bathophobias bathos bathoses bathrobe bathrobes bathroom bathrooms baths bathsheba bathtub bathtubs bathurst bathwater bathyal bathymetric bathymetrical bathymetrically bathymetry bathypelagic bathyscaph bathyscaphe bathyscaphes bathyscaphs bathysphere bathyspheres bathythermograph bathythermographs batik batiks bating batiste batman batmen baton batons batophobia batrachian batrachians batrachotoxin batrachotoxins bats batsman batsmen batswana batswanas batt battailous battalia battalias battalion battalions batteau batted battement batten battenbergs battened battening battens batter battered batterer batterers batterie batteries battering batters battery battier battiest battiness batting battings battle battled battledore battledores battlefield battlefields battlefront battlefronts battleground battlegrounds battlement battlemented battlements battler battlers battles battleship battleships battlewagon battlewagons battling batts battu battue battues batty batwing batwings bauble baubles baucis baud baudelaire bauds bauhaus bauhinia bauhinias baum baumé bauxite bauxites bauxitic bavaria bavarian bavarians bawbee bawbees bawcock bawcocks bawd bawdier bawdiest bawdily bawdiness bawdries bawdry bawds bawdy bawdyhouse bawdyhouses bawl bawled bawler bawlers bawling bawls bay bayadere bayaderes bayberries bayberry bayed bayesian bayeux baying bayonet bayoneted bayoneting bayonets bayonetted bayonetting bayonne bayou bayous bayreuth bays bayside bazaar bazaars bazooka bazookas bdellium bdelliums be beach beachboy beachboys beachcomb beachcombed beachcomber beachcombers beachcombing beachcombs beached beaches beachfront beachfronts beachhead beachheads beaching beachless beachscape beachscapes beachside beachwear beachy beacon beaconed beaconing beacons bead beaded beadier beadiest beadily beading beadings beadle beadles beadroll beadrolls beads beadsman beadsmen beadwork beady beagle beagles beak beaked beaker beakers beaks beaky beam beamed beamier beamiest beaming beamingly beamish beamishly beams beamy bean beanbag beanbags beanball beanballs beaned beaneries beanery beanie beanies beaning beano beanos beanpole beanpoles beans beanstalk beanstalks bear bearability bearable bearably bearbaiting bearbaitings bearberries bearberry bearcat bearcats beard bearded beardedness bearding beardless beardlessness beards beardtongue beardtongues bearer bearers bearing bearings bearish bearishly bearishness bearlike bears bearskin bearskins beast beastie beasties beastings beastlier beastliest beastliness beastly beasts beat beatable beaten beater beaters beatific beatifically beatification beatifications beatified beatifies beatify beatifying beating beatings beatitude beatitudes beatles beatless beatnik beatniks beatrice beats beau beaucoup beaucoups beaufort beaujolais beaumont beaune beaus beaut beauteous beauteously beauteousness beautician beauticians beauties beautification beautifications beautified beautifier beautifiers beautifies beautiful beautifully beautifulness beautify beautifying beauts beauty beautyberries beautyberry beautybush beautybushes beaux beaver beaverboard beaverbrook beavered beavering beavers beavertail beavertails bebop bebopper beboppers becalm becalmed becalming becalms became because beccafico beccaficos bechance bechanced bechances bechancing bechuana bechuanaland bechuanas beck becket beckets beckon beckoned beckoner beckoners beckoning beckoningly beckons becks becloud beclouded beclouding beclouds become becomes becoming becomingly becomingness becquerel becquerels bed bedabble bedabbled bedabbles bedabbling bedaub bedaubed bedaubing bedaubs bedazzle bedazzled bedazzlement bedazzles bedazzling bedbug bedbugs bedchamber bedchambers bedclothes bedcover bedcovering bedcovers bedded bedder bedders bedding bede bedeck bedecked bedecking bedecks bedevil bedeviled bedeviling bedevilled bedevilling bedevilment bedevils bedew bedewed bedewing bedews bedfast bedfellow bedfellows bedford bedfordshire bedight bedighted bedighting bedights bedim bedimmed bedimming bedims bedizen bedizened bedizening bedizenment bedizens bedlam bedlamite bedlamites bedmate bedmates bedouin bedouins bedpan bedpans bedplate bedplates bedpost bedposts bedraggle bedraggled bedraggles bedraggling bedrid bedridden bedrock bedroll bedrolls bedroom bedrooms beds bedside bedsides bedsonia bedsoniae bedsore bedsores bedspread bedspreads bedspring bedsprings bedstead bedsteads bedstraw bedstraws bedtime bedtimes beduin beduins bee beebee beebees beebread beech beecham beechdrops beechen beeches beechnut beechnuts beef beefalo beefaloes beefalos beefcake beefcakes beefeater beefeaters beefed beefier beefiest beefiness beefing beefs beefsteak beefsteaks beefwood beefwoods beefy beehive beehives beekeeper beekeepers beekeeping beelike beeline beelines beelzebub been beep beeped beeper beepers beeping beeps beer beerbohm beerhouse beerhouses beerier beeriest beers beersheba beery bees beestings beeswax beet beethoven beetle beetled beetles beetleweed beetleweeds beetling beetroot beetroots beets beeves befall befallen befalling befalls befell befit befits befitted befitting befittingly befog befogged befogging befogs befool befooled befooling befools before beforehand beforetime befoul befouled befouling befouls befriend befriended befriending befriends befuddle befuddled befuddlement befuddlements befuddles befuddling beg began beget begets begetter begetters begetting beggar beggared beggaries beggaring beggarliness beggarly beggars beggary begged begging begin beginner beginners beginning beginnings begins begird begirded begirding begirds begirt begone begonia begonias begorra begot begotten begrime begrimed begrimes begriming begrudge begrudged begrudger begrudgers begrudges begrudging begrudgingly begs beguile beguiled beguilement beguilements beguiler beguilers beguiles beguiling beguilingly beguine beguines begum begums begun behalf behalves behave behaved behaver behavers behaves behaving behavior behavioral behaviorally behaviorism behaviorist behavioristic behaviorists behaviors behead beheaded beheading beheadings beheads beheld behemoth behemoths behest behind behindhand behinds behold beholden beholder beholders beholding beholds behoof behoove behooved behooves behooving beige beiges beigy beijing being beings beirut bejesus bejewel bejeweled bejeweling bejewelled bejewels bel belabor belabored belaboring belabors belarus belated belatedly belatedness belaud belauded belauding belauds belay belayed belaying belays belch belched belches belching beldam beldame beldames beldams beleaguer beleaguered beleaguering beleaguerment beleaguers belemnite belemnites belfast belfried belfries belfry belgae belgian belgians belgic belgium belgrade belgravia belie belied belief beliefs belier beliers belies believability believable believably believe believed believer believers believes believing belike belittle belittled belittlement belittler belittlers belittles belittling belittlingly belive belize belizian belizians bell bella belladonna bellbird bellbirds bellboy bellboys belle belled belleek belleeks belles belletrism belletrist belletristic belletrists bellflower bellflowers bellhop bellhops belli bellicose bellicosely bellicoseness bellicosity bellied bellies belligerence belligerency belligerent belligerently belligerents belling bellini bellman bellmen belloc bellona bellow bellowed bellower bellowers bellowing bellows bellpull bellpulls bells bellum bellwether bellwethers bellwort bellworts belly bellyache bellyached bellyacher bellyachers bellyaches bellyaching bellyband bellybands bellybutton bellybuttons bellyful bellyfuls bellying belmont belmopan beloit belonephobia belonephobias belong belonged belonger belongers belonging belongingness belongings belongs belorussia belorussian belorussians beloved beloveds below belowground bels belsen belshazzar belt beltane belted belting beltings beltless belts beltway beltways beluga belukha belvedere belvederes belying bema bemata bemedaled bemedalled bemire bemired bemires bemiring bemoan bemoaned bemoaning bemoans bemock bemocked bemocking bemocks bemuse bemused bemusedly bemusement bemuses bemusing ben benares bench benched bencher benchers benches benching benchmark benchmarked benchmarking benchmarks benchwarmer benchwarmers bend bendable benday bendayed bendaying bendays bender benders bending bends bendy bene beneath benedict benedictine benedictines benediction benedictions benedictive benedictory benedicts benedictus benefaction benefactions benefactor benefactors benefactress benefactresses benefic benefice beneficed beneficence beneficences beneficent beneficently benefices beneficial beneficially beneficialness beneficiaries beneficiary beneficiate beneficiated beneficiating beneficiation beneficing benefit benefited benefiter benefiters benefiting benefits benefitted benefitting benelux benevento benevolence benevolent benevolently benevolentness bengal bengalese bengali bengaline bengalines bengalis benghazi benidorm benighted benightedly benightedness benign benignancies benignancy benignant benignantly benignities benignity benignly benin beninese benison benisons benjamin benne bennet bennets bennies bennington benny bens bent bentham benthamism benthamite benthamites benthic benthonic benthos benthoses bentonite bentonites bentonitic bents bentwood bentwoods benumb benumbed benumbing benumbment benumbs benz benzaldehyde benzaldehydes benzalkonium benzanthracene benzedrine benzene benzenes benzidine benzidines benzimidazole benzimidazoles benzin benzine benzines benzins benzoate benzoates benzocaine benzocaines benzocarbazole benzocarbazoles benzodiazepine benzodiazepines benzoic benzoin benzoins benzol benzols benzophenone benzophenones benzopyrene benzopyrenes benzoyl benzoyls benzyl benzylic benzyls beowulf bepaint bepainted bepainting bepaints bequeath bequeathal bequeathals bequeathed bequeather bequeathers bequeathing bequeathment bequeaths bequest bequests berate berated berates berating berber berberine berberines berbers berceuse berceuses berdache berdaches berdachism berea bereave bereaved bereavement bereavements bereaver bereavers bereaves bereaving bereft berenices beret berets berg bergamo bergamot bergamots bergen bergs bergsonian bergsonism beribboned beriberi bering berkeleian berkeleianism berkeley berkelium berkshire berkshires berlin berline berliner berliners berlioz berm berms bermuda bermudan bermudans bermudas bermudian bermudians bern bernadette bernadotte bernard bernardine berne bernese bernhardt bernini bernoulli bernstein berried berries berry berrying berrylike berseem berseems berserk berserker berserkers berserkly berserks berth bertha berthas berthed berthing berths beryl berylline beryllium beryls berzelius bes besançon beseech beseeched beseecher beseechers beseeches beseeching beseechingly beseem beseemed beseeming beseems beset besetment besets besetting beshrew beshrewed beshrewing beshrews beside besides besiege besieged besiegement besieger besiegers besieges besieging besmear besmeared besmearing besmears besmirch besmirched besmircher besmirchers besmirches besmirching besmirchment besom besoms besot besots besotted besotting besought bespangle bespangled bespangles bespangling bespatter bespattered bespattering bespatters bespeak bespeaking bespeaks bespectacled bespoke bespoken besprent besprinkle besprinkled besprinkles besprinkling bessarabia bessel bessemer bessie bessies best bestead besteaded besteading besteads bested bestial bestialities bestiality bestialize bestialized bestializes bestializing bestially bestiaries bestiary besting bestir bestirred bestirring bestirs bestow bestowable bestowal bestowals bestowed bestowing bestowment bestows bestraddle bestraddled bestraddles bestraddling bestrew bestrewed bestrewing bestrewn bestrews bestridden bestride bestrides bestriding bestrode bests bestseller bestsellerdom bestsellers bestselling bet beta betaine betaines betake betaken betakes betaking betamethasone betamethasones betas betatron betatrons betel betelgeuse betels beth bethanechol bethanechols bethany bethel bethels bethesda bethink bethinking bethinks bethlehem bethought betide betided betides betiding betimes betjeman betoken betokened betokening betokens betonies betony betook betray betrayal betrayals betrayed betrayer betrayers betraying betrays betroth betrothal betrothals betrothed betrothing betroths bets betta bettas betted better bettered bettering betterment betterments betters betterton betting bettor bettors betty between betweenbrain betweenness betweentimes betweenwhiles betwixt beulah bevel beveled beveling bevelled bevelling bevels beverage beverages beverly bevies bevy bewail bewailed bewailer bewailers bewailing bewailment bewails beware bewared bewares bewaring bewhiskered bewick bewigged bewilder bewildered bewilderedly bewilderedness bewildering bewilderingly bewilderment bewilders bewitch bewitched bewitcher bewitchers bewitchery bewitches bewitching bewitchingly bewitchment bewitchments bewray bewrayed bewraying bewrays bey beyond beys bezant bezants bezel bezels bezique bezoar bezoars bhakti bhaktis bhang bhangs bhutan bhutanese bi biafra biafran biafrans bialy bialys biannual biannually biarritz bias biased biases biasing biasness biassed biasses biassing biathlete biathletes biathlon biathlons biaxial biaxiality biaxially bib bibb bibbed bibber bibbers bibbery bibbing bibbs bibcock bibcocks bibelot bibelots bible bibles bibless biblical biblically biblicism biblicist biblicists bibliofilm bibliofilms bibliographer bibliographers bibliographic bibliographical bibliographically bibliographies bibliography bibliolater bibliolaters bibliolatrous bibliolatry bibliology bibliomancies bibliomancy bibliomania bibliomaniac bibliomaniacal bibliomaniacs bibliopegic bibliopegist bibliopegists bibliopegy bibliophile bibliophiles bibliophilic bibliophilism bibliophilistic bibliophily bibliopole bibliopoles bibliopolic bibliopolical bibliopolist bibliopolists bibliotheca bibliothecal bibliothecas bibliotherapies bibliotherapy bibliotic bibliotics bibliotist bibliotists bibs bibulous bibulously bibulousness bicameral bicameralism bicarb bicarbonate bicarbonates bicarbs bicaudal bicellular bicentenaries bicentenary bicentennial bicentennials bicentric bicentricity bicephalous biceps bicepses bichloride bichlorides bichromate bichromated bichromates bichrome bicipital bicker bickered bickerer bickerers bickering bickers bicoastal bicolor bicolored bicolors bicomponent biconcave biconcavity biconditional biconditionals biconvex biconvexity bicorne bicornes bicornuate bicultural biculturalism bicuspid bicuspidate bicuspids bicycle bicycled bicycler bicyclers bicycles bicyclic bicycling bicyclist bicyclists bid bidarka bidarkas biddability biddable biddably bidden bidder bidders biddies bidding biddings biddy bide bided bidentate bider biders bides bidet bidets bidialectal bidialectalism bidialectalist bidialectalists biding bidirectional bidirectionally bidonville bidonvilles bids biedermeier bien biennia biennial biennially biennials biennium bienniums bier biers bierstadt bifacial biff biffed biffies biffing biffs biffy bifid bifida bifidity bifidly bifilar bifilarly biflagellate bifocal bifocaled bifocalism bifocals bifoliolate biform bifunctional bifurcate bifurcated bifurcately bifurcates bifurcating bifurcation bifurcations big bigamies bigamist bigamists bigamous bigamously bigamy bigarade bigarades bigeminal bigeminies bigeminy bigeneric bigeye bigeyes bigfoot bigger biggest biggety biggie biggies biggin bigging biggings biggins biggish biggity bighead bigheaded bigheadedness bigheads bighearted bigheartedly bigheartedness bighorn bighorns bight bights bigly bigmouth bigmouthed bigmouths bigness bignonia bignonias bigos bigot bigoted bigotedly bigotedness bigotries bigotry bigots bigtime bigwig bigwigs bihar bijection bijections bijective bijou bijous bijouterie bijouteries bijoux bijugate bike biked biker bikers bikes bikeway bikeways bikie bikies biking bikini bikinied bikinis bilabial bilabially bilabials bilabiate bilander bilanders bilateral bilateralism bilaterally bilateralness bilayer bilayers bilbao bilberries bilberry bilbo bilboa bilboas bilboes bildungsroman bildungsromans bile biles bilge bilged bilges bilging bilgy bilharzia bilharzias bilharziasis biliary bilimbi bilimbis bilinear bilingual bilingualism bilingually bilinguals bilious biliously biliousness bilirubin bilirubins biliverdin biliverdins bilk bilked bilker bilkers bilking bilks bill billable billabong billabongs billboard billboarded billboarding billboards billbug billbugs billed biller billers billet billeted billeting billets billfish billfishes billfold billfolds billhead billheads billhook billhooks billiard billiards billies billing billings billingsgate billion billionaire billionaires billionfold billions billionth billionths billon billons billow billowed billowiness billowing billows billowy billposter billposters billposting bills billy billycock billycocks bilobate bilobed bilobular bilocation bilocations bilocular biltong biltongs bimanal bimanous bimanual bimanually bimaxillary bimbo bimbos bimestrial bimetal bimetallic bimetallism bimetallist bimetallistic bimetallists bimetals bimillenaries bimillenary bimillenial bimillenially bimillennia bimillennium bimillenniums biminis bimodal bimodality bimolecular bimolecularly bimonthlies bimonthly bimorphemic bin binal binaries binary binate binational binaural binaurally bind binder binderies binders bindery binding bindingly bindingness bindings bindle bindles bindlestiff bindlestiffs binds bindweed bindweeds bine bines binge binged bingeing binger bingers binges binging bingo bingoes bingos binnacle binnacles binned binning binocular binocularity binocularly binoculars binomial binomially binomials binominal bins bint bints binturong binturongs binuclear binucleate binucleated bio bioaccumulation bioaccumulations bioaccumulative bioacoustics bioactive bioactivities bioactivity bioagent bioagents bioassay bioassays bioastronautical bioastronautics bioavailability biocatalyst biocatalysts biocatalytic biocenology biocenose biocenoses biocenosis biochemical biochemically biochemist biochemistries biochemistry biochemists biochip biochips biocidal biocide biocides bioclimatic bioclimatology biocoenoses biocoenosis biocompatibility biocompatible bioconversion biodegradability biodegradable biodegradation biodegrade biodegraded biodegrades biodegrading biodiversity biodynamic biodynamics bioelectric bioelectrical bioelectricity bioelectronic bioelectronics bioenergetic bioenergetics bioengineer bioengineered bioengineering bioengineers bioenvironmental bioethical bioethicist bioethicists bioethics biofeedback bioflavonoid bioflavonoids biogas biogenesis biogenetic biogenetical biogenetically biogenetics biogenic biogenous biogeochemical biogeochemistry biogeographer biogeographers biogeographic biogeographical biogeography biogerontologist biogerontologists biogerontology biographee biographees biographer biographers biographic biographical biographically biographies biography biohazard biohazards bioinorganic bioinstrumentation bioinstrumentations biologic biological biologically biologicals biologics biologism biologist biologistic biologists biology bioluminescence bioluminescent biolysis biolytic biomarker biomarkers biomass biomasses biomaterial biomaterials biomathematical biomathematician biomathematicians biomathematics biome biomechanical biomechanically biomechanics biomedical biomedicine biomembrane biomembranes biomes biometeorology biometric biometrical biometrically biometrics biometry biomimesis biomineralogist biomineralogists biomolecular biomolecule biomolecules bionic bionics bionomic bionomical bionomically bionomics bioorganic biophysical biophysically biophysicist biophysicists biophysics biopic biopics biopolymer biopolymers bioprocess bioprocessed bioprocesses bioprocessing biopsic biopsied biopsies biopsy biopsychic biopsychology bioptic bioreactor bioreactors bioregion bioregional bioregionalism bioregionalist bioregionalists bioregions bioresearch biorhythm biorhythmic biorhythms bios biosatellite biosatellites bioscience biosciences bioscientific bioscientist bioscientists bioscope bioscopes bioscopies bioscopy biosensor biosensors biosocial biosocially biosphere biospheres biospheric biostatistician biostatisticians biostatistics biosyntheses biosynthesis biosynthesize biosynthesized biosynthesizes biosynthesizing biosynthetic biosynthetically biosystematic biosystematics biosystematist biosystematists biota biotas biotech biotechnical biotechnological biotechnologist biotechnologists biotechnology biotelemetric biotelemetry biotherapies biotherapy biotic biotin biotins biotite biotites biotitic biotope biotopes biotransformation biotransformations biotron biotrons biotype biotypes biotypic bioweapon bioweapons biparental biparentally biparous bipartisan bipartisanism bipartisanship bipartite bipartitely bipartition biped bipedal bipedalism bipedality bipeds biphenyl biphenyls bipinnate bipinnately biplane biplanes bipod bipods bipolar bipolarity bipolarization bipolarize bipolarized bipolarizes bipolarizing bipotentialities bipotentiality bipropellant bipropellants biquadratic biquadratics biquarterly biracial biracialism biradial biramous birch birched birchen bircher birchers birches birching birchism birchist birchists bird birdbath birdbaths birdbrain birdbrained birdbrains birdcage birdcages birdcall birdcalls birded birder birders birdhouse birdhouses birdie birdied birdieing birdies birding birdlike birdlime birdlimed birdlimes birdliming birdman birdmen birds birdseed birdseeds birdshot birdwatcher birdwatchers birdying birefringence birefringent bireme biremes biretta birettas birk birkbeck birkie birkies birks birl birled birler birlers birling birls birmingham biro biros birr birred birring birrs birth birthday birthdays birthed birthing birthings birthmark birthmarks birthplace birthplaces birthrate birthrates birthright birthrights birthroot birthroots births birthstone birthstones birthwort birthworts biryani biryanis bis biscay biscayne biscotti biscotto biscuit biscuits bise bisect bisected bisecting bisection bisectional bisectionally bisections bisector bisectors bisects biseriate biserrate bises bisexual bisexuality bisexually bisexuals bishop bishopric bishoprics bishops bislama bismarck bismarckian bismuth bismuthal bismuthic bison bisons bisque bisques bissau bissextile bissextiles bistate bister bistered bisters bistort bistorts bistouries bistoury bistre bistred bistres bistro bistroic bistros bisulcate bisulfate bisulfates bisulfide bisulfides bisulfite bisulfites bit bitable bitartrate bitartrates bitch bitched bitcheries bitchery bitches bitchier bitchiest bitchily bitchiness bitching bitchy bite biteable biteplate biteplates biter biters bites bitewing bitewings bithynia bithynian biting bitingly bitmap bitmapped bitmapping bitmaps bitok bitoks bits bitstock bitstocks bitsy bitt bitted bitten bitter bitterbrush bitterbrushes bittered bitterender bitterenders bitterer bitterest bittering bitterish bitterly bittern bitterness bitterns bitternut bitternuts bitterroot bitterroots bitters bittersweet bittersweetly bittersweetness bittersweets bitterweed bittier bittiest bittiness bitting bittock bittocks bitts bitty bitumen bitumens bituminization bituminize bituminized bituminizes bituminizing bituminoid bituminous bitwise bivalence bivalency bivalent bivalents bivalve bivalved bivalves bivariate bivouac bivouacked bivouacking bivouacks bivouacs biweeklies biweekly biyearly biz bizarre bizarrely bizarreness bizet bizonal bizone bizones blab blabbed blabber blabbered blabbering blabbermouth blabbermouths blabbers blabbing blabby blabs black blackamoor blackamoors blackball blackballed blackballer blackballers blackballing blackballs blackbeard blackberries blackberry blackbird blackbirder blackbirders blackbirds blackboard blackboards blackbodies blackbody blackbuck blackbucks blackcap blackcaps blackcock blackcocks blackcurrant blackcurrants blackdamp blacked blacken blackened blackener blackeners blackening blackens blacker blackest blackface blackfaces blackfeet blackfish blackfishes blackflies blackfly blackfoot blackguard blackguarded blackguarding blackguardism blackguardly blackguards blackhander blackhanders blackhead blackheads blackheart blacking blackings blackish blackjack blackjacked blackjacking blackjacks blackland blackleg blacklegs blacklight blacklist blacklisted blacklister blacklisters blacklisting blacklists blackly blackmail blackmailed blackmailer blackmailers blackmailing blackmails blackness blackout blackouts blackpoll blackpolls blacks blacksburg blacksmith blacksmithing blacksmiths blacksnake blacksnakes blackstone blackstrap blackstraps blacktail blacktails blackthorn blackthorns blacktop blacktopped blacktopping blacktops blackwash blackwashed blackwashes blackwashing blackwater bladder bladderlike bladdernose bladdernoses bladdernut bladdernuts bladders bladderwort bladderworts bladdery blade bladed blades blaff blaffs blagging blagoveshchensk blah blahs blain blains blamable blamableness blamably blame blamed blameful blamefully blamefulness blameless blamelessly blamelessness blamer blamers blames blameworthier blameworthiest blameworthiness blameworthy blaming blanc blanch blanche blanched blancher blanchers blanches blanching blancmange blancmanges bland blander blandest blandification blandified blandifies blandify blandifying blandish blandished blandisher blandishers blandishes blandishing blandishment blandishments blandly blandness blank blanked blanker blankest blanket blanketed blanketflower blanketflowers blanketing blanketlike blankets blanking blankly blankness blanks blare blared blares blaring blarney blarneyed blarneying blarneys blaspheme blasphemed blasphemer blasphemers blasphemes blasphemies blaspheming blasphemous blasphemously blasphemousness blasphemy blast blasted blastema blastemal blastemas blastemata blastematic blastemic blaster blasters blastie blasties blasting blastment blastocoel blastocoelic blastocoels blastocyst blastocystic blastocysts blastoderm blastodermatic blastodermic blastoderms blastodisk blastodisks blastoff blastoffs blastogenesis blastogenetic blastogenic blastoma blastomas blastomata blastomere blastomeres blastomeric blastomycete blastomycetes blastomycin blastomycins blastomycosis blastoporal blastopore blastopores blastoporic blastosphere blastospheres blastospore blastospores blasts blastula blastulae blastular blastulas blastulation blasé blat blatancies blatancy blatant blatantly blate blather blathered blatherer blatherers blathering blathers blatherskite blatherskites blats blatted blatter blattered blattering blatters blatting blaw blawed blawing blawn blaws blaxploitation blaze blazed blazer blazers blazes blazing blazingly blazon blazoned blazoner blazoners blazoning blazonment blazonries blazonry blazons bleach bleachable bleached bleacher bleachers bleaches bleaching bleak bleaker bleakest bleakish bleakly bleakness blear bleared blearier bleariest blearily bleariness blearing blears bleary bleat bleated bleater bleaters bleating bleats bleb blebby blebs bled bleed bleeder bleeders bleeding bleedings bleeds bleep bleeped bleeper bleepers bleeping bleeps blemish blemished blemisher blemishers blemishes blemishing blench blenched blencher blenchers blenches blenching blend blende blended blender blenders blendes blending blends blenheim blennies blenny blent bleomycin bleomycins blepharitis blepharoplast blepharoplasts blepharoplasty blepharospasm blepharospasms blesbok blesboks bless blessed blessedly blessedness blesser blessers blesses blessing blessings blest blether blethered blethering blethers blew bligh blight blighted blighter blighters blighting blights blimp blimpish blimpishly blimpishness blimps blin blind blinded blinder blinders blindest blindfish blindfishes blindfold blindfolded blindfolding blindfolds blinding blindingly blindly blindman blindman's blindness blinds blindworm blindworms blini blinis blink blinked blinker blinkered blinkering blinkers blinking blinks blintz blintze blintzes blip blipped blipping blips bliss blissful blissfully blissfulness blister blistered blistering blisteringly blisters blistery blithe blithely blitheness blither blithered blithering blithers blithesome blithesomely blithest blithsomeness blitz blitzed blitzes blitzing blitzkrieg blitzkriegs blivit blivits blizzard blizzards blizzardy bloat bloated bloater bloaters bloating bloats blob blobbed blobbing blobs bloc block blockade blockaded blockader blockaders blockades blockading blockage blockages blockbuster blockbusters blockbusting blocked blocker blockers blockhead blockheadedness blockheads blockhouse blockhouses blockier blockiest blocking blockish blockishly blockishness blocks blocky blocs bloemfontein blois bloke blokes blond blonde blonder blondes blondest blondish blondness blonds blood bloodbath bloodbaths bloodcurdling bloodcurdlingly blooded bloodedness bloodguilt bloodguiltiness bloodguilty bloodhound bloodhounds bloodied bloodier bloodies bloodiest bloodily bloodiness blooding bloodless bloodlessly bloodlessness bloodletter bloodletters bloodletting bloodlettings bloodline bloodlines bloodlust bloodmobile bloodmobiles bloodred bloodroot bloodroots bloods bloodshed bloodshot bloodstain bloodstained bloodstaining bloodstains bloodstock bloodstone bloodstones bloodstream bloodstreams bloodsucker bloodsuckers bloodsucking bloodthirstily bloodthirstiness bloodthirsty bloodworm bloodworms bloody bloodying bloom bloomed bloomer bloomers blooming blooms bloomy bloop blooped blooper bloopers blooping bloops blossom blossomed blossoming blossoms blossomy blot blotch blotched blotches blotchily blotchiness blotching blotchy blots blotted blotter blotters blotting blotto blouse bloused blouses blousing blouson blousons blousy blow blowback blowbacks blowby blowbys blower blowers blowfish blowfishes blowflies blowfly blowgun blowguns blowhard blowhards blowhole blowholes blowier blowiest blowing blowjob blowjobs blown blowoff blowoffs blowout blowouts blowpipe blowpipes blows blowsier blowsiest blowsy blowtorch blowtorches blowup blowups blowy blowzier blowziest blowzily blowziness blowzy blub blubbed blubber blubbered blubberer blubberers blubbering blubberingly blubbers blubbery blubbing blubs blucher bluchers bludgeon bludgeoned bludgeoneers bludgeoner bludgeoners bludgeoning bludgeons blue bluebeard bluebeards bluebell bluebells blueberries blueberry bluebill bluebills bluebird bluebirds bluebonnet bluebonnets bluebook bluebooks bluebottle bluebottles bluecoat bluecoated bluecoats bluecurls blued bluefin bluefish bluefishes bluegill bluegills bluegrass blueing blueings bluejacket bluejackets bluely blueness bluenose bluenosed bluenoses bluepoint bluepoints blueprint blueprinted blueprinting blueprints bluer blues blueshift bluesman bluesmen bluest bluestem bluestems bluestocking bluestockings bluestone bluestones bluesy bluet bluetongue bluetongues bluets blueweed blueweeds bluey blueys bluff bluffable bluffed bluffer bluffers bluffest bluffing bluffly bluffness bluffs bluing bluings bluish bluishness blunder blunderbuss blunderbusses blundered blunderer blunderers blundering blunderingly blunderings blunders blunt blunted blunter bluntest blunting bluntly bluntness blunts blur blurb blurbs blurred blurrier blurriest blurrily blurriness blurring blurringly blurry blurs blurt blurted blurter blurters blurting blurts blush blushed blusher blushers blushes blushful blushing blushingly bluster blustered blusterer blusterers blustering blusteringly blusterous blusters blustery blücher bo bo's'n bo's'ns bo'sun bo'suns boa boadicea boar board boarded boarder boarders boarding boardinghouse boardinghouses boardlike boardman boardmen boardroom boardrooms boards boardsailing boardwalk boardwalks boarfish boarfishes boarhound boarhounds boarish boars boart boarts boas boast boasted boaster boasters boastful boastfully boastfulness boasting boastings boasts boat boatbill boatbills boatbuilder boatbuilders boated boatel boatels boater boaters boathouse boathouses boating boatlift boatlifts boatload boatloads boatman boatmanship boatmen boats boatsman boatsmen boatswain boatswains boatwright boatwrights boatyard boatyards bob bobbed bobber bobberies bobbers bobbery bobbie bobbies bobbin bobbinet bobbinets bobbing bobbins bobble bobbled bobbles bobbling bobby bobbysoxer bobbysoxers bobcat bobcats bobeche bobeches boboli bobolink bobolinks bobs bobsled bobsledded bobsledder bobsledders bobsledding bobsleded bobsleding bobsleds bobstay bobstays bobtail bobtailed bobtails bobwhite bobwhites bocaccio bocaccios boccaccio bocce bocces bocci boccie boccies boccis bock bocks bodacious bodaciously bode boded bodega bodegas bodement bodements bodensee bodes bodhisattva bodhisattvas bodice bodices bodied bodies bodiless bodily boding bodings bodkin bodkins bodleian bodley body bodybuilder bodybuilders bodybuilding bodyguard bodyguards bodying bodysnatching bodysuit bodysuits bodysurf bodysurfed bodysurfer bodysurfers bodysurfing bodysurfs bodyweight bodywork boehmite boehmites boeing boeings boeotia boeotian boeotians boer boers boethius boff boffin boffins boffo boffola boffolas boffos boffs bofors bog bogey bogeyed bogeying bogeyman bogeymen bogeys bogged boggier boggiest bogginess bogging boggle boggled boggler bogglers boggles boggling boggy bogie bogies bogle bogles bogotá bogs bogsat bogtrotter bogtrotters bogus bogwood bogwoods bogy bogyman bogymen bohea boheas bohemia bohemian bohemianism bohemians bohemias bohr bohrium bohunk bohunks bohème boil boilable boiled boiler boilermaker boilermakers boilerplate boilerplates boilers boiling boiloff boiloffs boils bois boise boisterous boisterously boisterousness bokhara bokmål bola bolas bolases bold bolded bolder boldest boldface boldfaced boldfaces boldfacing bolding boldly boldness bole bolection bolections bolero boleros boles bolete boletes boleti boletus boletuses boleyn bolide bolides bolingbroke bolivar bolivars bolivia bolivian boliviano bolivianos bolivians boll bollard bollards bolled bolling bollinger bollix bollixed bollixes bollixing bolls bollworm bollworms bolo bologna bolognan bolognese bolometer bolometers bolometric bolometrically boloney bolos bolshevik bolsheviks bolshevism bolshevist bolshevists bolshevization bolshevize bolshevized bolshevizes bolshevizing bolshie bolshies bolshy bolster bolstered bolsterer bolsterers bolstering bolsters bolt bolted bolter bolters bolthole boltholes bolting boltonia boltonias boltrope boltropes bolts bolus boluses bolívar bomb bombard bombarded bombarder bombardier bombardiers bombarding bombardment bombardments bombardon bombardons bombards bombast bombaster bombasters bombastic bombastically bombasts bombay bombazine bombazines bombe bombed bomber bombers bombes bombinate bombinated bombinates bombinating bombination bombing bombings bomblet bomblets bombproof bombs bombshell bombshells bombsight bombsights bombycid bombycids bon bona bonanza bonanzas bonaparte bonapartism bonapartist bonapartists bonaventure bonbon bonbonnière bonbonnières bonbons bond bondable bondage bonded bonder bonders bondholder bondholders bondi bonding bondings bondmaid bondmaids bondman bondmen bonds bondservant bondservants bondsman bondsmen bondstone bondstones bondwoman bondwomen bone boneblack boned bonefish bonefishes bonehead boneheaded boneheadedness boneheads boneless boner boners bones boneset bonesets bonesetter bonesetters boney boneyard boneyards bonfire bonfires bong bonged bonging bongo bongoes bongoist bongoists bongos bongs bonhomie bonhomies bonier boniest boniface bonifaces boniness boning bonito bonitos bonjour bonkers bonn bonne bonnes bonnet bonneted bonneting bonnets bonneville bonnie bonnier bonniest bonnily bonniness bonny bonnyclabber bonnyclabbers bono bons bonsai bonsoir bonspiel bonspiels bontebok bonteboks bonum bonus bonuses bony bonze bonzes boo boob boobies booboisie booboisies booboo booboos boobs booby boodle boodles booed booger boogerman boogermen boogers boogeyman boogeymen boogie boogied boogies boogying boohoo boohooed boohooing boohoos booing book bookbinder bookbinderies bookbinders bookbindery bookbinding bookbindings bookcase bookcases booked bookend bookends booker bookers bookful bookie bookies booking bookings bookish bookishly bookishness bookkeeper bookkeepers bookkeeping booklet booklets booklists booklore booklores booklouse booklouses bookmaker bookmakers bookmaking bookman bookmark bookmarker bookmarkers bookmarks bookmen bookmobile bookmobiles bookplate bookplates bookrack bookracks bookroom bookrooms books bookseller booksellers bookselling bookshelf bookshelves bookshop bookshops bookstall bookstalls bookstand bookstands bookstore bookstores bookwork bookworm bookworms boolean boom boomed boomer boomerang boomeranged boomeranging boomerangs boomers boomier boomiest booming boomlet boomlets booms boomtown boomtowns boomy boon boondocks boondoggle boondoggled boondoggler boondogglers boondoggles boondoggling boonies boons boor boorish boorishly boorishness boors boos boost boosted booster boosterish boosterism boosters boosting boosts boot bootblack bootblacks booted bootee bootees bootes booth booths bootie booties booting bootjack bootjacks bootlace bootlaces bootle bootleg bootlegged bootlegger bootleggers bootlegging bootlegs bootless bootlessly bootlessness bootlick bootlicked bootlicker bootlickers bootlicking bootlicks boots bootstrap bootstrapped bootstrapping bootstraps booty booze boozed boozehound boozehounds boozer boozers boozes boozier booziest boozily boozing boozy bop bophuthatswana bopped bopper boppers bopping boppish bops bora boracic borage borages borane boranes boras borate borated borates borax boraxes borazon borborygmi borborygmus bordeaux bordello bordellos border bordereau bordereaux bordered borderer borderers bordering borderland borderlands borderline borderlines borders bordetella bordetellas bordure bordures bore boreal borealis boreas borecole borecoles bored boredom borehole boreholes borer borers bores borghese borgia boric boride borides boring boringly boringness borings born borne bornean borneo borneol borneols bornholm bornite bornites borodin boron boronic borons borosilicate borosilicates borough boroughs borrelia borrelias borrow borrowed borrower borrowers borrowing borrowings borrows borsch borsches borscht borschts borsht borshts borstal borstals bort borts borty borzoi borzois bos'n bosc boscage boscages bosch bosh bosk boskage boskages boskier boskiest boskiness bosks bosky bosnia bosnian bosnians bosom bosomed bosoms bosomy boson bosons bosphorus bosporus bosque bosques bosquet bosquets boss bossa bossdom bossdoms bossed bosses bossier bossies bossiest bossily bossiness bossing bossism bossisms bossy boston bostonian bostonians bosun bosuns boswell boswellian boswellize boswellized boswellizes boswellizing boswells bosworth bot botanic botanical botanically botanicals botanies botanist botanists botanize botanized botanizer botanizers botanizes botanizing botany botch botched botcher botchers botches botching botchy botfly both bother botheration botherations bothered bothering bothers bothersome bothnia botonee botonnee botryoidal botryoidally botrytis bots botswana botswanan bott botticelli bottle bottlebrush bottlebrushes bottlecap bottlecaps bottled bottleful bottleneck bottlenecked bottlenecking bottlenecks bottlenose bottlenoses bottler bottlers bottles bottling bottom bottomed bottomer bottomers bottoming bottomland bottomless bottomlessly bottomlessness bottommost bottoms botts botulin botulinal botulins botulinum botulinums botulinus botulism boucicault boucle bouclé boudicca boudin boudins boudoir boudoirs bouffant bouffe bouffes bougainvillaea bougainvillaeas bougainville bougainvillea bougainvilleas bough boughed boughs bought bougie bougies bouillabaisse bouillon boulder bouldered boulderer boulderers bouldering boulders bouldery boule boules boulevard boulevardier boulevardiers boulevards bouleversement bouleversements boulle boulles boulogne bounce bounced bouncer bouncers bounces bouncier bounciest bouncily bouncing bouncingly bouncy bound boundaries boundary bounded boundedness bounden bounder bounderish bounders bounding boundless boundlessly boundlessness bounds bounteous bounteously bounteousness bountied bounties bountiful bountifully bountifulness bounty bouquet bouquetier bouquetiers bouquets bourbon bourbonism bourbons bourdon bourdons bourg bourgeois bourgeoise bourgeoises bourgeoisie bourgeoisification bourgeoisified bourgeoisifies bourgeoisify bourgeoisifying bourgeon bourgeoned bourgeoning bourgeons bourget bourgogne bourgs bourguignon bourn bourne bournes bourns bourrée bourrées bourse bourses bouse boused bouses bousing boustrophedon boustrophedonic bout boutique boutiques bouton boutonniere boutonnieres boutonnière boutonnières boutons bouts bouvardia bouvardias bouvier bouzouki bouzoukis bovid bovids bovine bovinely bovines bovinity bovril bow bowdlerism bowdlerization bowdlerizations bowdlerize bowdlerized bowdlerizer bowdlerizers bowdlerizes bowdlerizing bowed bowel bowelless bowels bower bowerbird bowerbirds bowered bowering bowers bowery bowfin bowfins bowfront bowhead bowheads bowie bowing bowings bowknot bowknots bowl bowlder bowlders bowled bowleg bowlegged bowlegs bowler bowlers bowlful bowlfuls bowline bowlines bowling bowls bowman bowmen bows bowse bowsed bowses bowshot bowshots bowsing bowsprit bowsprits bowstring bowstrings bowwow bowwows bowyer bowyers box boxboard boxboards boxcar boxcars boxed boxer boxers boxes boxfish boxfishes boxful boxfuls boxhaul boxhauled boxhauling boxhauls boxier boxiest boxiness boxing boxings boxlike boxthorn boxthorns boxwood boxwoods boxy boy boyar boyard boyards boyars boycott boycotted boycotter boycotters boycotting boycotts boyfriend boyfriends boyhood boyish boyishly boyishness boyle boyo boyos boys boysenberries boysenberry bozcaada bozeman bozo bozos boîte boîtes boötes bra brabant brabble brabbled brabbler brabblers brabbles brabbling brace braced bracelet bracelets bracer bracero braceros bracers braces brachia brachial brachiate brachiated brachiates brachiating brachiation brachiator brachiators brachiocephalic brachiopod brachiopods brachiosaurus brachium brachycephalic brachycephalism brachycephaly brachydactylia brachydactylic brachydactyly brachylogies brachylogy brachypterism brachypterous brachyuran bracing bracingly bracings braciola bracken brackens bracket bracketed bracketing brackets brackish brackishness braconid braconids bract bracteal bracteate bracted bracteolate bracteole bracteoles bracts brad bradawl bradawls bradded bradding brads bradshaw bradycardia bradycardias bradycardic bradykinin bradykinins bradylogia bradylogias brae braes brag braganza bragg braggadocio braggadocios braggart braggarts bragged bragger braggers braggest bragging braggy brags brahe brahma brahman brahmanic brahmanical brahmanism brahmanist brahmanists brahmans brahmaputra brahmas brahmin brahminism brahmins brahms brahmsian braid braided braider braiders braiding braidings braids brail brailed brailing braille brailled brailler braillers brailles braillewriter braillewriters brailling brails brain braincase braincases brainchild brainchildren brained brainier brainiest brainily braininess braining brainish brainless brainlessly brainlessness brainpan brainpans brainpower brains brainsick brainsickly brainsickness brainstem brainstems brainstorm brainstormed brainstormer brainstormers brainstorming brainstorms brainteaser brainteasers brainwash brainwashed brainwasher brainwashers brainwashes brainwashing brainwave brainwaves brainwork brainworker brainworkers brainworks brainy braise braised braises braising brake braked brakeless brakeman brakemen brakes braking braky braless bralessness bramble brambleberries brambleberry brambles brambling bramblings brambly bran branch branched branches branchia branchiae branchial branching branchiopadous branchiopod branchiopodan branchiopods branchless branchlet branchlets branchy brand brandade brandades branded brandenburg brander branders brandied brandies branding brandish brandished brandisher brandishers brandishes brandishing brandling brandlings brands brandy brandying brandywine brank branks brannigan brannigans branny brant brants braque bras brash brasher brashes brashest brashly brashness brass brassard brassards brassbound brasserie brasseries brasses brassica brassicas brassie brassier brassiere brassieres brassies brassiest brassily brassiness brassware brasswares brassy brasília brat bratislava brats brattice bratticed brattices bratticing brattier brattiest brattiness brattish brattishness brattle brattleboro brattled brattles brattling bratty bratwurst bratwursts braunschweiger braunschweigers brava bravado bravadoes bravados bravas brave braved bravely braveness braver braveries bravers bravery braves bravest braving bravissimo bravo bravoed bravoes bravoing bravos bravura bravuras braw brawer brawest brawl brawled brawler brawlers brawlier brawliest brawling brawlingly brawls brawly brawn brawnier brawniest brawnily brawniness brawny bray brayed brayer brayers braying brays braze brazed brazen brazened brazenfaced brazening brazenly brazenness brazens brazer brazers brazes brazier braziers brazil brazilian brazilians brazils brazilwood brazilwoods brazing brazzaville breach breached breaches breaching bread breadbasket breadbaskets breadboard breadboarded breadboarding breadboards breadbox breadboxes breadcrumb breadcrumbs breaded breadfruit breadfruits breading breadline breadlines breadnut breadnuts breadroot breadroots breads breadstuff breadstuffs breadth breadths breadthways breadthwise breadwinner breadwinners breadwinning break breakable breakableness breakables breakage breakages breakaway breakaways breakdown breakdowns breaker breakers breakfast breakfasted breakfaster breakfasters breakfasting breakfasts breakfront breakfronts breaking breakings breakneck breakoff breakoffs breakout breakouts breakpoint breakpoints breaks breakthrough breakthroughs breakup breakups breakwater breakwaters bream breamed breaming breams breast breastbone breastbones breasted breastfed breastfeed breastfeeding breastfeeds breasting breastplate breastplates breasts breaststroke breaststroker breaststrokers breaststrokes breastwork breastworks breath breathability breathable breathalyzer breathalyzers breathe breathed breather breathers breathes breathier breathiest breathily breathiness breathing breathings breathless breathlessly breathlessness breaths breathtaking breathtakingly breathy breccia breccias brecciate brecciated brecciates brecciating brecciation brecht brechtian breckinridge bred breda brede bredes breech breechblock breechblocks breechcloth breechcloths breechclout breechclouts breeches breeching breechings breechloader breechloaders breechloading breed breeder breeders breeding breeds breeks breeze breezed breezeless breezes breezeway breezeways breezier breeziest breezily breeziness breezing breezy bregma bregmata bregmatic bremen bremsstrahlung bremsstrahlungs bren brenner brent bresaola bresaolas brest bretagne brethren breton bretons breughel breve breves brevet brevetcy breveted breveting brevets brevetted brevetting breviaries breviary brevity brew brewage brewages brewed brewer breweries brewers brewery brewing brewpub brewpubs brews briand briar briard briards briarroot briarroots briars briarwood briarwoods bribable bribe bribed bribee bribees briber briberies bribers bribery bribes bribing brick brickbat brickbats bricked bricking bricklayer bricklayers bricklaying brickle bricks brickwork bricky brickyard brickyards bricolage bricolages bridal bridals bride bridegroom bridegrooms brides brideshead bridesmaid bridesmaids bridewell bridewells bridge bridgeable bridgeboard bridgeboards bridged bridgehead bridgeheads bridgeless bridgeport bridges bridgetown bridgework bridging bridie bridle bridled bridler bridlers bridles bridling brie brief briefcase briefcases briefed briefer briefers briefest briefing briefings briefless briefly briefness briefs brier briers briery bries brig brigade brigaded brigades brigadier brigadiers brigading brigadoon brigand brigandage brigandine brigandines brigandism brigands brigantine brigantines bright brighten brightened brightener brighteners brightening brightens brighter brightest brightly brightness brightwork brightworks brigs brill brilliance brilliancy brilliant brilliantine brilliantly brilliantness brilliants brills brim brimful brimless brimmed brimmer brimmers brimming brims brimstone brimstones brinded brindisi brindle brindled brindles brine brined brinell briner briners brines bring bringdown bringdowns bringer bringers bringing brings brinier briniest brininess brining brink brinkmanship brinksmanship briny brio brioche brioches briolette briolettes briquet briquets briquette briquetted briquettes briquetting brisance brisances brisant brisbane brisk brisker briskest brisket briskets briskly briskness brisling brislings bristle bristlecone bristled bristlelike bristles bristletail bristletails bristlier bristliest bristling bristly bristol bristols brit britain britannia britannic britannica britches briticism briticisms british britisher britishers britishness briton britons brits britt brittany britten brittle brittlebush brittlebushes brittlely brittleness brittler brittlest brittonic britts brno bro broach broached broacher broachers broaches broaching broad broadax broadaxe broadaxes broadband broadcast broadcasted broadcaster broadcasters broadcasting broadcastings broadcasts broadcloth broaden broadened broadener broadeners broadening broadens broader broadest broadleaf broadloom broadlooms broadly broadminded broadmindedly broadmindedness broadness broads broadsheet broadsheets broadside broadsided broadsides broadsiding broadsword broadswords broadtail broadtails broadway brobdingnag brobdingnagian brobdingnagians brocade brocaded brocades brocatel brocatelle brocatelles brocatels broccoli brochette brochettes brochure brochures brock brockage brockages brocket brockets brocks brogan brogans brogue brogues broider broidered broidering broiders broidery broil broiled broiler broilers broiling broils broke broken brokenhearted brokenheartedly brokenly brokenness broker brokerage brokerages brokered brokering brokers brollies brolly bromate bromated bromates bromating brome bromegrass bromegrasses bromelain bromelains bromeliad bromeliads bromelin bromelins bromes bromic bromide bromides bromidic brominate brominated brominates brominating bromination bromine bromism bromo bromos bronc bronchi bronchia bronchial bronchially bronchiectasis bronchiolar bronchiole bronchioles bronchitic bronchitis bronchium broncho bronchodilator bronchodilators bronchopneumonia bronchos bronchoscope bronchoscopes bronchoscopic bronchoscopically bronchoscopist bronchoscopists bronchoscopy bronchus bronco broncobuster broncobusters broncos broncs brontosaur brontosaurs brontosaurus brontosauruses brontë brontës bronx bronze bronzed bronzer bronzers bronzes bronzing bronzy brooch brooches brood brooded brooder brooders broodier broodiest broodiness brooding broodingly broods broody brook brooked brookie brookies brooking brookite brookites brooklet brooklets brooklime brooklimes brooklyn brooklynese brooks broom broomball broomballer broomballers broomcorn broomcorns broomed brooming broomrape broomrapes brooms broomstick broomsticks broomtail broomtails broomy bros brose broses broth brothel brothels brother brotherhood brotherhoods brotherliness brotherly brothers broths brougham broughams brought brouhaha brouhahas brow browallia browallias browbeat browbeaten browbeater browbeaters browbeating browbeats brown browne browned browner brownest brownian brownie brownies browning brownings brownish brownness brownnose brownnosed brownnoser brownnosers brownnoses brownnosing brownout brownouts browns brownshirt brownshirts brownstone brownstones browny browridge brows browse browsed browser browsers browses browsing bruce brucella brucellae brucellas brucellosis brucine brucines bruckner brueghel bruges bruin bruins bruise bruised bruiser bruisers bruises bruising bruit bruited bruiting bruits brulee brulé brulés brumal brumbies brumby brume brumes brummagem brummell brumous brunch brunched brunches brunching brunei bruneian bruneians brunel brunelleschi brunet brunets brunette brunettes brunhild brunizem brunswick brunt brush brushability brushback brushed brusher brushers brushes brushfire brushfires brushier brushing brushings brushland brushoff brushstroke brushstrokes brushup brushups brushwood brushwork brushy brusk brusque brusquely brusqueness brusquer brusquerie brusqueries brusquest brussels brut brutal brutalism brutalist brutalists brutalities brutality brutalization brutalize brutalized brutalizes brutalizing brutally brute brutes brutish brutishly brutishness brutism brutum brutus bruxelles bruxism bruxisms brynhild bryological bryologist bryologists bryology bryonies bryony bryophyllum bryophyta bryophyte bryophytes bryophytic bryozoa bryozoan bryozoans brython brythonic brythons brzezinski brûlée brûlées bub bubbies bubble bubbled bubblegum bubblehead bubbleheaded bubbleheads bubbler bubblers bubbles bubblier bubblies bubbliest bubbling bubbly bubby bubo buboes bubonic bubonocele bubonoceles buccal buccally buccaneer buccaneering buccaneerish buccaneers buccinator bucco bucephalus bucer bucharest buchenwald buchu buchus buck buckaroo buckaroos buckbean buckbeans buckboard buckboards bucked bucker buckeroo buckers bucket bucketed bucketful bucketfuls bucketing buckets bucketsful buckeye buckeyes buckhorn buckhorns buckhound buckhounds bucking buckinghamshire buckjump buckjumped buckjumper buckjumpers buckjumping buckjumps buckle buckled buckler bucklered bucklering bucklers buckles buckley's buckling buckminsterfullerene buckminsterfullerenes bucko buckoes buckram buckramed buckraming buckrams bucks bucksaw bucksaws buckshee buckshees buckshot buckskin buckskinned buckskins bucktail bucktails buckteeth buckthorn buckthorns bucktooth bucktoothed buckwheat buckyball buckyballs buco bucolic bucolically bucolics bud budapest budded budder budders buddha buddhahood buddhas buddhism buddhist buddhistic buddhistical buddhists buddied buddies budding buddle buddleia buddleias buddles buddy buddying budge budged budgerigar budgerigars budges budget budgetary budgeted budgeteer budgeteers budgeter budgeters budgeting budgets budgie budgies budging buds budworm budworms buenos buff buffa buffalo buffaloberry buffaloed buffaloes buffaloing buffed buffer buffered buffering buffers buffet buffeted buffeter buffeters buffeting buffetings buffets buffi buffing bufflehead buffleheads buffo buffoon buffoonery buffoonish buffoons buffos buffs bug bugaboo bugaboos bugbane bugbanes bugbear bugbears bugeye bugeyes bugged bugger buggered buggering buggers buggery buggier buggies buggiest bugginess bugging buggy bughouse bughouses bugle bugled bugler buglers bugles bugleweed bugleweeds bugling bugloss buglosses bugs buhl buhls buhrstone buhrstones buick buicks build buildable builddown builddowns builded builder builderer builderers buildering builders building buildings builds buildup buildups built buirdly bujumbura bukhara bulawayo bulb bulbar bulbed bulbel bulbels bulbiferous bulbil bulbils bulblet bulblets bulbourethral bulbous bulbously bulbs bulbul bulbuls bulgar bulgaria bulgarian bulgarians bulgars bulge bulged bulges bulgier bulgiest bulginess bulging bulgur bulgy bulimarexia bulimarexias bulimia bulimic bulk bulked bulkhead bulkheads bulkier bulkiest bulkily bulkiness bulking bulks bulky bull bulla bullace bullaces bullae bullate bullbaiting bullbat bullbats bullboat bullboats bulldog bulldogged bulldogger bulldoggers bulldogging bulldogs bulldoze bulldozed bulldozer bulldozers bulldozes bulldozing bulled bullet bulleted bulletin bulletined bulleting bulletining bulletins bulletproof bulletproofed bulletproofing bulletproofs bullets bullfight bullfighter bullfighters bullfighting bullfights bullfinch bullfinches bullfrog bullfrogs bullhead bullheaded bullheadedly bullheadedness bullheads bullhorn bullhorns bullied bullies bulling bullion bullish bullishly bullishness bullism bullmastiff bullmastiffs bullnecked bullock bullocks bullocky bullous bullpen bullpens bullring bullrings bullroarer bullroarers bullrush bullrushes bulls bullshat bullshit bullshits bullshitted bullshitter bullshitters bullshitting bullshot bullterrier bullterriers bullwhacker bullwhackers bullwhip bullwhipped bullwhipping bullwhips bully bullyboy bullyboys bullying bullyrag bullyragged bullyragging bullyrags bulrush bulrushes bulwark bulwarked bulwarking bulwarks bulwer bum bumbershoot bumbershoots bumble bumblebee bumblebees bumbled bumbler bumblers bumbles bumbling bumblingly bumboat bumboats bumf bumkin bumkins bummalo bummalos bummed bummer bummers bumming bump bumped bumper bumpers bumph bumpier bumpiest bumpily bumpiness bumping bumpkin bumpkinish bumpkinly bumpkins bumps bumptious bumptiously bumptiousness bumpy bums bun buna bunas bunch bunchberries bunchberry bunched bunches bunchflower bunchflowers bunchgrass bunchgrasses bunchily bunchiness bunching bunchy bunco buncoed buncoing buncombe buncos bund bundist bundists bundle bundled bundler bundlers bundles bundling bunds bung bungalow bungalows bunged bungee bunghole bungholes bunging bungle bungled bungler bunglers bungles bunglesome bungling bunglingly bungs bunion bunions bunk bunked bunker bunkered bunkering bunkerings bunkers bunkhouse bunkhouses bunking bunkmate bunkmates bunko bunkos bunkroom bunkrooms bunks bunkum bunnies bunny bunraku buns bunsen bunt bunted bunter bunters bunting buntings buntline buntlines bunts bunyan bunyanesque bunyip bunyips buoy buoyance buoyances buoyancy buoyant buoyantly buoyed buoying buoys buppie buppies buprestid buprestids bur buran burans burbage burberry burble burbled burbler burblers burbles burbling burbly burbot burbots burbs burden burdened burdening burdens burdensome burdensomely burdensomeness burdock burdocks bureau bureaucracies bureaucracy bureaucrat bureaucratese bureaucrateses bureaucratic bureaucratically bureaucratism bureaucratization bureaucratize bureaucratized bureaucratizes bureaucratizing bureaucrats bureaus bureaux buret burets burette burettes burg burgage burgages burgee burgees burgeon burgeoned burgeoning burgeons burger burgers burgess burgesses burgh burghal burgher burghers burghley burghs burglar burglaries burglarious burglariously burglarize burglarized burglarizes burglarizing burglarproof burglarproofed burglarproofing burglarproofs burglars burglary burgle burgled burgles burgling burgomaster burgomasters burgonet burgonets burgoo burgoos burgos burgs burgundian burgundians burgundies burgundy burial burials buried burier buriers buries burin burins burke burked burkes burkina burkinese burking burkitt burl burladero burladeros burlap burlaps burled burleigh burler burlers burlesque burlesqued burlesquely burlesquer burlesquers burlesques burlesquing burley burleys burlier burlies burliest burlily burliness burling burls burly burma burman burmans burmese burn burnable burned burner burners burnet burnets burning burningly burnings burnish burnished burnisher burnishers burnishes burnishing burnoose burnoosed burnooses burnous burnouses burnout burnouts burns burnsides burnt burp burped burping burps burr burred burrer burrers burrier burriest burring burrito burritos burro burros burrow burrowed burrower burrowers burrowing burrows burrs burrstone burrstones burry burs bursa bursae bursal bursar bursarial bursaries bursars bursary bursas burse burses bursitis burst bursted burster bursters bursting bursts burthen burthens burton burtons burundi burundian burundians burweed burweeds bury burying bus busbies busboy busboys busby bused buses bush bushbuck bushbucks bushed bushel busheled busheler bushelers busheling bushelman bushels bushes bushfire bushfires bushido bushidos bushier bushiest bushily bushiness bushing bushings bushland bushlands bushman bushmaster bushmasters bushmen bushmills bushnell bushpig bushpigs bushranger bushrangers bushranging bushtit bushtits bushwhack bushwhacked bushwhacker bushwhackers bushwhacking bushwhacks bushy busied busier busies busiest busily business businesses businesslike businessman businessmen businesspeople businessperson businesspersons businesswoman businesswomen busing busk busked busker buskers buskin busking buskins busks busload busloads busman busman's busmen buss bussed busses bussing bust bustard bustards busted buster busters busticate busticated busticates busticating bustier bustiers bustiest busting bustle bustled bustles bustline bustling bustlingly busts busty busulfan busulfans busy busybodies busybody busying busyness busywork but butadiene butane butanes butanol butanols butanone butanones butazolidin butch butcher butcherbird butcherbirds butchered butcherer butcherers butcheries butchering butcherly butchers butchery butches bute butene butenes buteo buteos butler butlers butoxide buts butt butte butted butter butterball butterballs butterbur butterburs buttercup buttercups buttered butterfat butterfingered butterfingers butterfish butterfishes butterflied butterflies butterfly butterflyer butterflyers butterflying butteries butteriness buttering butterless buttermilk buttermilks butternut butternuts butters butterscotch butterweed butterweeds butterwort butterworts buttery buttes butties butting buttinski buttinskies buttinsky buttock buttocks button buttonball buttonballs buttonbush buttonbushes buttoned buttoner buttoners buttonhole buttonholed buttonholer buttonholers buttonholes buttonholing buttonhook buttonhooks buttoning buttonless buttonmold buttonmolds buttonquail buttonquails buttons buttonwood buttonwoods buttony buttress buttressed buttresses buttressing butts buttstock buttstocks butty butut bututs butyl butylate butylated butylates butylating butylation butylene butylenes butyls butyraceous butyraldehyde butyraldehydes butyrate butyrates butyric butyrin butyrins butyrophenone butyrophenones butyrophenoness buxom buxomly buxomness buxtehude buy buyable buyback buybacks buyer buyers buying buyout buyouts buys buzz buzzard buzzards buzzed buzzer buzzers buzzes buzzing buzzword buzzwords bwana bwanas by bye byelaw byelaws byelorussia byelorussian byelorussians byes bygone bygones bylaw bylaws byline bylined byliner byliners bylines bylining byname bynames bypass bypassed bypasses bypassing bypast bypath bypaths byplay byplays byproduct byproducts byre byres byroad byroads byron byronic byssi byssinosis byssus byssuses bystander bystanders bystreet bystreets byte bytes byway byways byword bywords byzantine byzantines byzantium béarn béarnaise béchamel béchamels bêche bêches bête bêtes bêtise bêtises c c'mon cab cabal cabala cabalas cabaletta cabalettas cabalette cabalism cabalist cabalistic cabalistically cabalists caballed caballero caballeros caballing cabals cabana cabanas cabaret cabarets cabaña cabañas cabbage cabbages cabbageworm cabbageworms cabbagy cabbed cabbie cabbies cabbing cabby cabdriver cabdrivers caber cabernet cabernets cabers cabin cabined cabinet cabinetful cabinetmaker cabinetmakers cabinetmaking cabinetry cabinets cabinetwork cabining cabins cable cablecast cablecaster cablecasters cablecasts cabled cablegram cablegrams cabler cablers cables cablet cablets cablevision cableway cableways cabling cabman cabmen cabochon cabochons caboclo caboclos cabomba cabombas caboodle caboose cabooses cabot cabotage cabotages cabretta cabrettas cabrilla cabrillas cabriole cabrioles cabriolet cabriolets cabs cabstand cabstands cacao cacaos cachaca cachalot cachalots cachaça cache cachectic cached cachepot cachepots caches cachet cachets cachexia cachexias caching cachinnate cachinnated cachinnates cachinnating cachinnation cachinnator cachinnators cachou cachous cachucha cachuchas cacique caciques cackle cackled cackler cacklers cackles cackling cacodemon cacodemons cacodyl cacodylic cacodyls cacography cacomistle cacomistles caconym caconyms caconymy cacophonic cacophonies cacophonous cacophonously cacophony cacoëthes cacti cactus cactuses cacuminal cad cadastral cadastre cadaver cadaveric cadaverine cadaverines cadaverous cadaverously cadaverousness cadavers caddie caddied caddies caddis caddish caddishly caddishness caddo caddoan caddoans caddos caddy caddying cade cadelle cadelles cadence cadenced cadences cadencies cadency cadent cadential cadenza cadenzas cadet cadets cadetship cadge cadged cadger cadgers cadges cadging cadillac cadillacs cadiz cadmic cadmium cadmus cadre cadres cads caducean caducei caduceus caducity caducous caecilian caecilians caelian caelum caerphillies caerphilly caesar caesarea caesarean caesareans caesarian caesarians caesarism caesarist caesaristic caesarists caesars caesura caesurae caesural caesuras caesuric cafe cafes cafeteria cafeterias cafetoria cafetorium cafetoriums caffeinated caffeine caffeinism caftan caftans café cafés cage caged cagelike cageling cagelings cages cagey cageyness cagier cagiest cagily caginess caging cagliari cahier cahiers cahoots cahow cahows cahuilla cahuillas caicos caiman caimans cain cainotophobia cainotophobias caird cairds cairn cairned cairngorm cairns cairo caisson caissons caitiff caitiffs cajan cajans cajole cajoled cajoler cajolers cajolery cajoles cajoling cajolingly cajun cajuns cake caked cakes cakewalk cakewalked cakewalker cakewalkers cakewalking cakewalks caking calabash calabashes calaboose calabooses calabrese calabreses calabria calabrian calabrians caladium calais calamanco calamancoes calamander calamanders calamari calamaries calamary calami calamine calamint calamints calamite calamites calamities calamitous calamitously calamitousness calamity calamondin calamondins calamus calando calash calashes calathea calatheas calathi calathus calcanea calcaneal calcanei calcaneocuboid calcaneum calcaneus calcar calcareous calcareously calcaria calceolaria calceolarias calceolate calcic calcicole calcicoles calcicolous calciferol calciferols calciferous calcific calcification calcifications calcified calcifies calcifugal calcifuge calcifugous calcify calcifying calcimine calcimined calciminer calciminers calcimines calcimining calcination calcine calcined calcines calcining calcinosis calcite calcitic calcitonin calcitonins calcium calcspar calcspars calculability calculable calculably calculate calculated calculatedly calculates calculating calculatingly calculation calculations calculative calculator calculators calculi calculous calculus calculuses calcutta caldera calderas caldron caldrons caledonia caledonian caledonians calendal calendar calendared calendaring calendars calender calendered calenderer calenderers calendering calenders calendric calendrical calends calendula calendulas calenture calentures calf calfskin calgarian calgarians calgary caliban caliber calibers calibrate calibrated calibrates calibrating calibration calibrations calibrator calibrators calices caliche caliches calico calicoback calicobacks calicoes calicos calicut california californian californians californite californites californium caliginous caligula calinago calinagos calipash calipashes calipee calipees caliper calipered calipering calipers caliph caliphate caliphates caliphs calisthenic calisthenics calix calk calked calking calks call calla callable callback callbacks callboard callboards callboy callboys called caller callers calligrapher calligraphers calligraphic calligraphist calligraphy calling callings calliope calliopes calliopsis callipygian callisthenes callisto callose calloses callosities callosity callous calloused callouses callousing callously callousness callow callowness calls callus callused calluses callusing calm calmative calmed calmer calmest calming calmly calmness calms calomel caloreceptor caloreceptors caloric calorically calorie calories calorific calorifically calorimeter calorimeters calorimetric calorimetrically calorimetry calotte calottes calpac calpacs calque calques caltrop caltrops calumet calumets calumniate calumniated calumniates calumniating calumniation calumniations calumniator calumniators calumniatory calumnies calumnious calumniously calumny calvados calvarium calvariums calvary calve calved calves calvin calving calvinism calvinist calvinistic calvinistical calvinistically calvinists calx calxes calyces calycine calycular calyculate calyculi calyculus calypso calypsos calyptra calyptrate calyx calyxes calèche cam camaraderie camargue camarilla camarillas camas camber cambered cambering cambers cambia cambial cambium cambiums cambodia cambodian cambodians cambrai cambria cambrian cambric cambrics cambridge cambridgeshire camcorder camcorders came camel camelback camelbacks cameleer cameleers camellia camellias camelopard camelopardalis camelot camels camembert cameo cameoed cameoing cameos camera camerae cameral cameraman cameramen cameraperson camerapersons cameras camerawoman camerawomen camerawork camerlingo camerlingos cameron cameroon cameroonian cameroonians cameroons cameroun cami camion camions camis camise camises camisole camisoles camorra camouflage camouflaged camouflager camouflagers camouflages camouflaging camp campaign campaigned campaigner campaigners campaigning campaigns campania campanile campaniles campanologist campanologists campanology campanula campanulas campanulate camped campeggio camper campers campesino campesinos campestral campfire campfires campground campgrounds camphene camphenes camphor camphoraceous camphorate camphorated camphorates camphorating camphoric camphorweed camphorweeds camping campion campions campo camporee camporees campos camps campsite campsites campstool campstools campus campuses campy campylobacterosis campylotropous cams camshaft camshafts can can't canaan canaanite canaanites canada canadian canadians canaigre canaigres canaille canal canaletto canalicular canaliculate canaliculi canaliculus canalization canalize canalized canalizes canalizing canalled canalling canals canapé canapés canard canards canaries canary canasta canaveral canberra cancan cancans cancel cancelable canceled canceler cancelers canceling cancellate cancellation cancellations cancelled cancelling cancellous cancels cancer cancerian cancerians cancerous cancers cancroid cancroids cancún candela candelabra candelabras candelabrum candelabrums candelas candelilla candelillas candent candescence candescent candescently candia candid candida candidacies candidacy candidas candidate candidates candidature candidatures candidiasis candidly candidness candids candied candies candle candleberries candleberry candled candlefish candleholder candleholders candlelight candlelit candlemas candlemases candlenut candlenuts candlepin candlepins candlepower candler candlers candles candlesnuffer candlesnuffers candlestick candlesticks candlewick candlewicks candlewood candlewoods candling candor candy candying candytuft candytufts cane canebrake canebrakes caned caner caners canes canescence canescent canfield cangue cangues canicular canid canids canine canines caning canistel canistels canister canisters canker cankered cankering cankerous cankerroot cankerroots cankers cankerworm cankerworms canna cannabic cannabidiol cannabidiols cannabin cannabins cannabis canned cannel cannelloni cannelure cannelures canner canneries canners cannery cannes cannibal cannibalism cannibalistic cannibalization cannibalizations cannibalize cannibalized cannibalizes cannibalizing cannibals cannier canniest cannikin cannikins cannily canniness canning cannoli cannon cannonade cannonaded cannonades cannonading cannonball cannonballed cannonballing cannonballs cannoned cannoneer cannoneers cannoning cannonries cannonry cannons cannot cannula cannular cannulas cannulate cannulated cannulates cannulating cannulation canny canoe canoed canoeing canoeist canoeists canoes canola canolas canon canoness canonesses canonic canonical canonically canonicals canonicate canonicates canonicity canonist canonistic canonistical canonists canonization canonizations canonize canonized canonizer canonizers canonizes canonizing canonries canonry canons canoodle canoodled canoodles canoodling canopic canopied canopies canopus canopy canopying canorous canorously canorousness cans cant cantabile cantabiles cantabrigian cantabrigians cantala cantalas cantaloupe cantaloupes cantankerous cantankerously cantankerousness cantata cantatas canted canteen canteens canter canterbury cantered cantering canters cantharides cantharis canthi canthitis canthus canticle canticles cantilated cantilates cantilating cantilena cantilenas cantilever cantilevered cantilevering cantilevers cantillate cantillation cantina cantinas canting cantingly cantingness cantle cantles canto canton cantonal cantonese cantonment cantonments cantons cantor cantorial cantors cantos cants canuck canucks canute canvas canvasback canvasbacks canvases canvass canvassed canvasser canvassers canvasses canvassing canyon canyons canzone canzones canzonet canzonets caoutchouc caoutchoucs cap capabilities capability capable capableness capably capacious capaciously capaciousness capacitance capacitances capacitate capacitated capacitates capacitating capacitation capacities capacitive capacitively capacitor capacitors capacity caparison caparisoned caparisoning caparisons cape caped capelin capelins capella caper capercaillie capercaillies capered capering capers capes capeskin capeskins capet capetian capetians capful capfuls capias capiases capillaries capillarities capillarity capillary capita capital capitalism capitalist capitalistic capitalistically capitalists capitalizable capitalization capitalizations capitalize capitalized capitalizes capitalizing capitally capitals capitate capitation capitations capitative capitella capitellum capitol capitoline capitols capitula capitulant capitular capitularies capitularly capitulary capitulate capitulated capitulates capitulating capitulation capitulations capitulator capitulators capitulatory capitulum caplet caplets capo capon caponata caponatas caponize caponized caponizes caponizing capons caporal caporals capos capote capotes cappadocia cappadocian cappadocians capped cappella capper cappers capping cappuccino cappuccinos capreomycin capreomycins capri capriccio capriccios capriccioso caprice caprices capricious capriciously capriciousness capricorn capricornian capricornians capricorns caprification caprifications caprifig caprifigs capriole caprioled caprioles caprioling capris caps capsaicin capsaicins capsian capsicum capsicums capsid capsids capsize capsized capsizes capsizing capsomere capsomeres capstan capstans capstone capstones capsular capsulate capsulated capsulation capsule capsuled capsules capsuling capsulize capsulized capsulizes capsulizing capsulotomies capsulotomy captain captaincies captaincy captained captaining captains captainship captan captans caption captioned captioning captions captious captiously captiousness captivate captivated captivates captivating captivatingly captivation captivator captivators captive captives captivities captivity captopril captoprils captor captors capture captured captures capturing capuche capuches capuchin capuchins capulet capulets capybara capybaras car carabao carabaos carabid carabids carabineer carabineers carabiner carabiners carabiniere carabinieri caracal caracalla caracals caracara caracaras caracas caracole caracoled caracoles caracoling caractacus caradoc carafe carafes carambola carambolas caramel caramelization caramelize caramelized caramelizes caramelizing caramels carangid carangids carapace carapaces carat caratacus carats caravaggio caravan caravans caravansaries caravansary caravel caravels caraway caraways carbamate carbamates carbamazepine carbamazepines carbamide carbamides carbamoyl carbamoyls carbanion carbanions carbaryl carbaryls carbenicillin carbenicillins carbide carbides carbine carbines carbinol carbinols carbocyclic carbohydrase carbohydrases carbohydrate carbohydrates carbolated carbolic carbon carbonaceous carbonado carbonadoed carbonadoes carbonadoing carbonados carbonara carbonaras carbonate carbonated carbonates carbonating carbonation carbonator carbonators carbonic carboniferous carbonium carboniums carbonization carbonize carbonized carbonizer carbonizers carbonizes carbonizing carbonous carbons carbonyl carbonylic carbonyls carborane carboranes carborundum carboxyhemoglobin carboxyhemoglobins carboxyl carboxylase carboxylases carboxylation carboxylations carboxylic carboxymethylcellulose carboxymethylcelluloses carboxypeptidase carboxypeptidases carboy carboys carbuncle carbuncled carbuncles carbuncular carburet carbureted carbureting carburetion carburetor carburetors carburets carburization carburize carburized carburizes carburizing carcajou carcajous carcanet carcanets carcass carcasses carcassonne carcinogen carcinogenesis carcinogenic carcinogenicity carcinogens carcinoid carcinoids carcinoma carcinomas carcinomatoid carcinomatosis carcinomatous card cardamom cardamoms cardboard carded cardholder cardholders cardholding cardia cardiac cardiacs cardiae cardialgia cardialgias cardiff cardigan cardigans cardinal cardinalate cardinalates cardinalities cardinality cardinals cardinalship carding cardioacceleration cardioaccelerator cardioaccelerators cardiogenic cardiogram cardiograms cardiograph cardiographs cardiography cardioid cardioids cardiological cardiologist cardiologists cardiology cardiomegaly cardiomyopathies cardiomyopathy cardiopathies cardiopathy cardiopulmonary cardiorespiratory cardiothoracic cardiovascular carditis carditises cardoon cardoons cards cardsharp cardsharper cardsharpers cardsharping cardsharps cardstock care cared careen careened careener careeners careening careens career careered careering careerism careerist careerists careers carefree careful carefully carefulness caregiver caregivers caregiving careless carelessly carelessness cares caress caressed caresser caressers caresses caressing caressingly caressive caret caretaker caretakers caretaking carets careworn carfare cargo cargoes carhop carhops carib cariban caribbean caribbeans caribe caribes caribou caribous caribs caricature caricatured caricatures caricaturing caricaturist caricaturists caries carillon carillonned carillonneur carillonneurs carillonning carillons carina carinae carinate caring carinthia carioca cariocan cariocas cariole carioles cariosity carious cariousness cark carked carking carks carl carling carlings carlisle carlist carlists carlo carload carloads carlos carls carlsbad carlyle carmaker carmakers carmel carmelite carmelites carmen carminative carminatives carmine carnac carnage carnal carnality carnallite carnallites carnally carnassial carnassials carnation carnations carnauba carne carnegie carnelian carnelians carnet carnets carnies carniola carniolan carniolans carnitine carnitines carnival carnivals carnivore carnivores carnivorous carnivorously carnivorousness carnotite carnotites carny carob carobs caroche caroches carol carolean caroled caroler carolers carolina carolinas caroline caroling carolingian carolingians carolinian carolinians carols carom caromed caroming caroms carotene carotenemia carotenemias carotenoid carotenoids carotid carotids carousal carousals carouse caroused carousel carousels carouser carousers carouses carousing carp carpaccio carpaccios carpal carpals carpathian carpathians carpe carped carpel carpellary carpellate carpels carpentaria carpenter carpentered carpentering carpenters carpentry carper carpers carpet carpetbag carpetbagger carpetbaggers carpetbaggery carpetbags carpeted carpeting carpetings carpets carpetweed carpetweeds carpi carping carpingly carpool carpooling carpools carpophagous carpophore carpophores carport carports carps carpus carrack carracks carrageen carrageenan carrantuohill carrara carrefour carrefours carrel carrels carreras carriage carriages carried carrier carriers carries carrion carroll carrot carrots carroty carrousel carrousels carry carryall carryalls carrying carryings carryon carryons carryout carryouts carryover carryovers cars carsick carsickness cart carta cartable cartage cartagena carte carted cartel cartelize cartelized cartelizes cartelizing cartels carter carters cartesian cartesianism cartesians carthage carthaginian carthaginians carthorse carthorses carthusian carthusians cartilage cartilaginous carting cartload cartloads cartogram cartograms cartographer cartographers cartographic cartographical cartography carton cartoned cartoning cartons cartoon cartooned cartooning cartoonish cartoonist cartoonists cartoons cartop cartouche cartouches cartridge cartridges carts cartularies cartulary cartwheel cartwheels caruncle caruncles caruncular carunculate carunculated caruso carvacrol carvacrols carve carved carver carvers carves carving carvings caryatid caryatidal caryatidean caryatides caryatidic caryatids caryopses caryopsis casaba casabas casablanca casanova casanovas casaubon casbah cascade cascaded cascades cascading cascara cascaras cascarilla cascarillas case caseate caseated caseates caseating caseation caseations casebook casebooks cased caseharden casehardened casehardening casehardens casein caseload caseloads casemate casemated casemates casement casemented casements caseous casern caserne casernes caserns caserta cases casework caseworker caseworkers cash cashable cashbook cashbooks cashed casher cashers cashes cashew cashews cashier cashiered cashiering cashiers cashing cashless cashmere cashmeres casing casings casino casinos cask casket casketed casketing caskets casks caspian casque casqued casques cassandra cassandras cassation cassations cassava cassavas casserole casseroles cassette cassettes cassia cassias cassimere cassina cassiopeia cassis cassiterite cassius cassock cassocked cassocks cassoulet cassoulets cassowaries cassowary cast castanet castanets castaway castaways caste castellan castellans castellated castellation caster casters castes castigate castigated castigates castigating castigation castigations castigator castigators castigatory castile castilian castilians casting castings castle castled castlereagh castles castling castoff castoffs castor castors castrate castrated castrater castraters castrates castrati castrating castration castrations castrato castrator castrators castroism castroist castroists casts casual casually casualness casuals casualties casualty casuarina casuarinas casuist casuistic casuistically casuistries casuistry casuists casus cat catabolic catabolically catabolism catabolite catabolites catabolize catabolized catabolizes catabolizing catachreses catachresis catachrestic catachrestical catachrestically cataclysm cataclysmal cataclysmic cataclysms catacomb catacombs catadromous catafalque catafalques catalan catalans catalase catalases catalatic catalectic catalepsies catalepsy cataleptic cataleptics catalexis catalog cataloged cataloger catalogers cataloging catalogs catalogue catalogued cataloguer cataloguers catalogues cataloguing catalonia catalonian catalonians catalpa catalpas catalyses catalysis catalyst catalysts catalytic catalytically catalyze catalyzed catalyzer catalyzers catalyzes catalyzing catamaran catamarans catamenia catamenial catamenias catamite catamites catamount catamountain catamountains catamounts catania catanzaro cataphoresis cataphoretic cataphoretically cataplasia cataplasias cataplasm cataplasms cataplastic cataplectic cataplexies cataplexy catapult catapulted catapulting catapults cataract cataracts catarrh catarrhal catarrhally catarrhous catarrhs catastases catastasis catastrophe catastrophes catastrophic catastrophically catastrophism catastrophist catastrophists catatonia catatonic catatonically catatonics catawba catawbas catbird catbirds catboat catboats catbrier catbriers catcall catcalled catcalling catcalls catch catchable catchall catchalls catcher catchers catches catchflies catchfly catchier catchiest catchily catchiness catching catchment catchments catchpenny catchphrase catchphrases catchpole catchpoles catchword catchwords catchy catecheses catechesis catechetical catechin catechins catechism catechisms catechist catechistic catechistical catechists catechization catechize catechized catechizer catechizers catechizes catechizing catechol catecholamine catecholamines catechols catechu catechumen catechumens catechus categoric categorical categorically categoricalness categories categorizable categorization categorizations categorize categorized categorizes categorizing category catena catenae catenaries catenary catenate catenated catenates catenating catenation cater catercorner catercornered catered caterer caterers catering caterpillar caterpillars caters caterwaul caterwauled caterwauling caterwauls catfight catfights catfish catfishes catgut cathar cathari catharism catharist catharists cathars catharses catharsis cathartic cathartics cathay cathead catheads cathect cathected cathectic cathecting cathects cathedra cathedrae cathedral cathedrals cathepsin cathepsins catherine catheter catheterization catheterize catheterized catheterizes catheterizing catheters cathexes cathexis cathode cathodes cathodic cathodically catholic catholically catholicism catholicity catholicize catholicized catholicizes catholicizing catholicon catholicons catholics cathouse cathouses catiline cation cationic cations catjang catjangs catkin catkins catlike catmint catmints catnap catnapped catnapping catnaps catnip catnips cato catoptric catoptrics cats catskill catskills catsup catsups cattail cattails cattalo cattaloes cattalos catted cattier cattiest cattily cattiness catting cattle cattleman cattlemen cattleya cattleyas catty catullus catwalk catwalks caucasian caucasians caucasus caucus caucused caucuses caucusing caudad caudal caudally caudate caudation caudex caudexes caudices caudillismo caudillo caudillos caudle caudles caught caul cauldron cauldrons caulescent cauliflorous cauliflory cauliflower cauliflowers cauline caulk caulked caulking caulkings caulks cauls causable causal causalities causality causally causals causation causations causative causatively cause caused causeless causer causerie causeries causers causes causeway causeways causing caustic caustically causticity caustics cauteries cauterization cauterizations cauterize cauterized cauterizes cauterizing cautery caution cautionary cautioned cautioner cautioners cautioning cautions cautious cautiously cautiousness cava cavae cavalas cavalcade cavalcades cavalier cavalierly cavaliers cavalla cavalries cavalry cavalryman cavalrymen cavatelli cave caveat caveated caveating caveats caved cavefish cavefishes caveman cavemen caver cavern caverned cavernicolous caverning cavernous cavernously caverns cavers caves cavetti cavetto cavettos caviar cavies cavil caviled caviler cavilers caviling cavils caving cavitate cavitated cavitates cavitating cavitation cavitations cavities cavity cavort cavorted cavorting cavorts cavour cavy caw cawdor cawed cawing caws caxton cay cayenne cayman caymans cays cayuga cayugas cayuse cayuses caïque caïques ceanothus cease ceased ceaseless ceaselessly ceaselessness ceases ceasing ceca cecal cecally cecil cecropia cecum cedar cedarbird cedarbirds cedars cede ceded cedes cedi cedilla cedillas ceding cedis cee cees ceiba ceibas ceil ceiled ceilidh ceilidhs ceiling ceilinged ceilings ceilometer ceilometers ceils celadon celadonite celadonites celadons celaeno celandine celandines celeb celebes celebrant celebrants celebrate celebrated celebrates celebrating celebration celebrations celebrator celebrators celebratory celebrities celebrity celebrityhood celebs celeriac celeriacs celeries celerity celery celesta celestas celestial celestially celestials celestine celestines celestite celestites celiac celibacy celibate celibates cell cella cellae cellar cellarage cellarages cellared cellarer cellarers cellarette cellarettes cellaring cellars cellblock cellblocks celled celling cellini cellist cellists cellmate cellmates cello cellobiose cellobioses celloidin celloidins cellophane cellos cells cellular cellularity cellularly cellulase cellulases cellule cellules cellulite cellulitis celluloid celluloids cellulolytic cellulose cellulosic celosia celosias celotex celsius celt celtiberian celtiberians celtic celticism celticisms celticist celticists celtics celts cembalist cembalists cembalo cembalos cement cementation cementations cemented cementer cementers cementing cementite cementites cementitious cements cementum cemeteries cemetery cenacle cenacles cenobite cenobites cenobitic cenobitical cenospecies cenotaph cenotaphic cenotaphs cenozoic cense censed censer censers censes censing censor censorable censored censorial censoring censorious censoriously censoriousness censors censorship censurability censurable censurableness censurably censure censured censurer censurers censures censuring census censuses cent cental centals centaur centauries centaurs centaurus centaury centavo centavos centenarian centenarians centenaries centenary centennial centennially centennials center centerboard centerboards centered centeredly centeredness centerfold centerfolds centering centerline centerlines centermost centerpiece centerpieces centers centesimal centesimally centesimi centesimo centesimos centiampere centiamperes centibecquerel centibecquerels centicandela centicandelas centicoulomb centicoulombs centifarad centifarads centigrade centigram centigrams centihenries centihenry centihenrys centihertz centijoule centijoules centikelvin centikelvins centiliter centiliters centilumen centilumens centilux centime centimes centimeter centimeters centimo centimole centimoles centimos centinewton centinewtons centiohm centiohms centipascal centipascals centipede centipedes centipoise centipoises centiradian centiradians centisecond centiseconds centisiemens centisievert centisieverts centisteradian centisteradians centitesla centiteslas centivolt centivolts centiwatt centiwatts centiweber centiwebers centner centners cento centos centra central centralism centralist centralistic centralists centrality centralization centralize centralized centralizer centralizers centralizes centralizing centrally centrals centric centrically centricity centrifugal centrifugalism centrifugally centrifugation centrifuge centrifuged centrifuges centrifuging centriole centrioles centripetal centripetally centrism centrist centrists centrobaric centroid centroids centrolecithal centrolineal centromere centromeres centromeric centrosome centrosomes centrosomic centrosphere centrospheres centrum centrums cents centuple centurial centuries centurion centurions century centurylong ceorl ceorls cep cephalad cephalalgia cephalalgias cephalexin cephalexins cephalic cephalically cephalin cephalins cephalization cephalizations cephalochordate cephalochordates cephalometer cephalometers cephalometric cephalometry cephalonia cephalopod cephalopodan cephalopodans cephalopods cephalosporin cephalosporins cephalothin cephalothins cephalothorax cephalothoraxes cepheid cepheids cepheus ceps ceraceous ceram ceramal ceramals ceramic ceramics ceramist ceramists cerastes cerate cerated cerates ceratodus ceratoduses ceratoid cerberean cerberus cercaria cercariae cercarial cercarias cerci cercus cere cereal cereals cerebella cerebellar cerebellum cerebellums cerebra cerebral cerebrally cerebrate cerebrated cerebrates cerebrating cerebration cerebrations cerebroside cerebrosides cerebrospinal cerebrovascular cerebrum cerebrums cerecloth cered cerement cerements ceremonial ceremonialism ceremonialist ceremonialists ceremonially ceremonials ceremonies ceremonious ceremoniously ceremoniousness ceremony ceres cereus cereuses ceric cerise cerium cermet cermets cernuous cero ceros cerotype cerotypes cerous certain certainly certainties certainty certes certifiable certifiably certificate certificated certificates certificating certification certifications certificatory certified certifier certifiers certifies certify certifying certiorari certioraris certitude certitudes cerulean ceruloplasmin ceruloplasmins cerumen ceruminous ceruse ceruses cerussite cerussites cervantes cervical cervices cervicitis cervine cervix cervixes cesarean cesareans cesium cespitose cespitosely cessation cessations cession cessions cessna cesspit cesspits cesspool cesspools cesta cestas cesti cestode cestodes cestus cestuses cetacean cetaceans cetaceous cetane cetanes cete cetera ceteris cetes cetological cetologist cetologists cetology cevennes ceviche ceviches ceylon ceylonese chablis chachka chachkas chacma chacmas chaconne chaconnes chacun chad chadian chadians chadless chador chadors chaeronea chaeta chaetae chaetognath chaetognathous chaetognaths chafe chafed chafer chafers chafes chaff chaffed chaffer chaffered chafferer chafferers chaffering chaffers chaffinch chaffinches chaffing chaffs chafing chagall chagrin chagrined chagrining chagrins chain chained chaining chainlike chainlink chainman chainmen chains chainsaw chainsaws chair chaired chairing chairlady chairman chairmanned chairmanning chairmans chairmanship chairmanships chairmen chairperson chairpersons chairs chairwoman chairwomen chaise chaises chakra chakras chalaza chalazae chalazal chalazas chalazia chalazion chalcedon chalcedonic chalcedonies chalcedony chalcid chalcidian chalcidians chalcidice chalcids chalcocite chalcocites chalcopyrite chalcopyrites chaldaic chaldaics chaldea chaldean chaldeans chaldee chaldees chaldron chaldrons chalet chalets chaliapin chalice chalices chalicothere chalicotheres chalk chalkboard chalkboards chalked chalkier chalkiest chalkiness chalking chalks chalkstone chalkstones chalky challah challahs challenge challengeable challenged challenger challengers challenges challenging challengingly challis chalone chalones chalybeate chalybeates cham chamaeleon chamaephyte chamaephytes chamber chambered chambering chamberlain chamberlains chambermaid chambermaids chambers chambray chameleon chameleonic chameleons chamfer chamfered chamfering chamfers chamfron chamfrons chamise chamises chamizal chamois chamomile chamomiles chamonix champ champagne champagnes champaign champaigns champak champaks champed champerties champertous champerty champignon champignons champing champion championed championing champions championship championships champlain champlevé champs champêtre champêtres chams chance chanced chanceful chancel chancelleries chancellery chancellor chancellors chancellorship chancels chanceries chancery chances chancier chanciest chanciness chancing chancre chancres chancroid chancroidal chancroids chancrous chancy chandelier chandeliers chandelle chandelles chandigarh chandler chandlers chandlery chandos chandragupta change changeability changeable changeableness changeably changed changeful changefully changefulness changeless changeling changelings changeover changeovers changer changers changes changeup changeups changing channel channeled channeler channelers channeling channelings channelization channelizations channelize channelized channelizes channelizing channels chanoyu chanoyus chanson chansons chant chanted chanter chanterelle chanterelles chanters chanteuse chanteuses chantey chanteys chanticleer chanticleers chantilly chanting chantingly chantries chantry chants chanukah chaos chaotic chaotically chap chaparral chaparrals chapati chapatis chapbook chapbooks chape chapeau chapeaus chapeaux chapel chapels chaperon chaperonage chaperone chaperoned chaperones chaperoning chaperons chapes chapfallen chapiter chapiters chaplain chaplaincies chaplaincy chaplains chaplainship chaplet chapleted chaplets chaplin chapman chapmen chapped chapping chaps chapter chapters chapultepec char charabanc charabancs characin characins character charactered characterful characteries charactering characteristic characteristically characteristics characterization characterizations characterize characterized characterizer characterizers characterizes characterizing characterless characters charactery charade charades charbroil charbroiled charbroiling charbroils charcoal charcoaled charcoaling charcoals charcuterie charcuteries chard chardonnay chardonnays chare chares charge chargeable chargeableness charged charger chargers charges charging chargé chargés charier chariest charily chariness chariot charioted charioteer charioteers charioting chariots charism charisma charismata charismatic charismatics charitable charitableness charitably charities charity charivari charivaris charkha charkhas charlatan charlatanic charlatanical charlatanism charlatanry charlatans charlemagne charleroi charles charleston charlestons charley charlie charlock charlocks charlotte charlottes charlottesville charm charmed charmer charmers charmeuse charmeuses charming charmingly charmless charmonium charmoniums charms charnel charnels charolais charon charqui charred charring chars chart charted charter chartered charterer charterers charterhouse charterhouses chartering charters charting chartings chartism chartist chartists chartres chartreuse chartroom chartrooms charts charwoman charwomen chary charybdis chase chased chaser chasers chases chasing chasm chasmal chasmogamous chasms chassepots chasseur chasseurs chassis chassises chassé chasséd chasséing chassés chaste chastely chasten chastened chastener chasteners chasteness chastening chastens chaster chastest chastisable chastise chastised chastisement chastisements chastiser chastisers chastises chastising chastity chasuble chasubles chat chateau chateaubriand chateaubriands chateaus chateaux chatelain chatelaine chatelaines chatelains chatoyancy chatoyant chatoyants chats chattahoochee chattanooga chatted chattel chattels chatter chatterbox chatterboxes chattered chatterer chatterers chattering chatters chatterton chattier chattiest chattily chattiness chatting chatty chaucer chaucerian chaucerians chauffeur chauffeured chauffeuring chauffeurs chaulmoogra chaulmoogras chautauqua chauvinism chauvinist chauvinistic chauvinistically chauvinists chaw chawed chawing chaws chayote chayotes chazan chazans cheap cheapen cheapened cheapener cheapeners cheapening cheapens cheaper cheapest cheapie cheapies cheapjack cheapjacks cheaply cheapness cheapskate cheapskates cheat cheated cheater cheaters cheating cheatingly cheats chebec chebecs chebyshev check checkable checkbook checkbooks checkbox checkboxes checked checker checkerberries checkerberry checkerbloom checkerblooms checkerboard checkerboards checkered checkering checkers checking checklist checklists checkmark checkmarks checkmate checkmated checkmates checkmating checkoff checkout checkouts checkpoint checkpoints checkrein checkreins checkroom checkrooms checks checksum checksums checkup checkups cheddar cheddars cheek cheekbone cheekbones cheeked cheekier cheekiest cheekily cheekiness cheeking cheeks cheeky cheep cheeped cheeper cheepers cheeping cheeps cheer cheered cheerer cheerers cheerful cheerfully cheerfulness cheerier cheeriest cheerily cheeriness cheering cheeringly cheerio cheerios cheerlead cheerleader cheerleaders cheerleading cheerleads cheerled cheerless cheerlessly cheerlessness cheers cheery cheese cheeseburger cheeseburgers cheesecake cheesecakes cheesecloth cheesed cheeseparer cheeseparers cheeseparing cheeses cheesier cheesiest cheesiness cheesing cheesy cheetah cheetahs chef chefs chekhov chekhovian chela chelae chelatable chelate chelated chelates chelating chelation chelator chelators chelicera chelicerae cheliform chellian chelonian chelonians chelsea chemic chemical chemically chemicals chemiluminescence chemiluminescent chemin chemins chemise chemises chemisette chemisettes chemisorb chemisorbed chemisorbing chemisorbs chemisorption chemist chemistries chemistry chemists chemoautotroph chemoautotrophic chemoautotrophically chemoautotrophs chemoautotrophy chemoprevention chemopreventions chemopreventive chemoprophylactic chemoprophylaxis chemoreception chemoreceptive chemoreceptivity chemoreceptor chemoreceptors chemosensory chemosphere chemospheres chemosurgery chemosurgical chemosynthesis chemosynthetic chemosynthetically chemosystematics chemotactic chemotactically chemotaxis chemotaxonomic chemotaxonomically chemotaxonomist chemotaxonomists chemotaxonomy chemotherapeutic chemotherapeutically chemotherapist chemotherapists chemotherapy chemotropic chemotropism chemotropisms chemurgic chemurgical chemurgy chenille chenilles chenopod chenopods cheops cheque chequer chequers cheques cherbourg cherimoya cherimoyas cherish cherishable cherished cherisher cherishers cherishes cherishing cherishingly chernobyl chernozem chernozemic chernozems cherokee cherokees cheroot cheroots cherries cherry cherrystone cherrystones chersonese chersoneses chert cherty cherub cherubic cherubically cherubim cherubs chervil chesapeake cheshire chess chessboard chessboards chesses chessman chessmen chessylite chessylites chest chested chesterfield chesterfields chestier chestiest chestiness chestnut chestnuts chests chesty chetrum cheval chevalet chevalets chevalier chevaliers chevaux chevelure chevelures cheviot cheviots chevrolet chevrolets chevron chevrons chevrotain chevrotains chew chewable chewed chewer chewers chewier chewiest chewiness chewing chewink chewinks chews chewy cheyenne cheyennes chez chi chia chianti chiantis chiaroscurist chiaroscurists chiaroscuro chiaroscuros chias chiasma chiasmal chiasmas chiasmata chiasmatic chiasmatypies chiasmatypy chiasmi chiasmic chiasmus chiastolite chiastolites chiaus chibcha chibchan chibchans chibchas chibouk chibouks chic chicago chicagoan chicagoans chicana chicane chicaned chicaner chicaneries chicaners chicanery chicanes chicaning chicano chicanos chicer chicest chichagof chichi chichier chichiest chick chickadee chickadees chickaree chickarees chickasaw chickasaws chicken chickened chickenfeed chickenhearted chickening chickenpox chickens chickpea chickpeas chicks chickweed chickweeds chicle chiclets chicly chicness chicories chicory chid chidden chide chided chider chiders chides chiding chidingly chief chiefdom chiefdoms chiefly chiefs chiefship chieftain chieftaincy chieftains chieftainship chiffchaff chiffchaffs chiffon chiffonier chiffoniers chiffonnier chiffonniers chifforobe chifforobes chigger chiggers chignon chignons chigoe chihuahua chihuahuas chilblain chilblained chilblains child childbearing childbed childbirth childbirths childermas childermases childfree childhood childish childishly childishness childless childlessness childlike childproof childproofed childproofing childproofs children chile chilean chileans chili chiliad chiliads chiliasm chiliast chiliastic chiliburger chiliburgers chilidog chilidogs chilies chill chilled chiller chillers chillier chilliest chillily chilliness chilling chillingly chillness chills chilly chiloe chilopod chilopods chiloé chimaera chimaeras chimborazo chime chimed chimer chimera chimeras chimeric chimerical chimerically chimerism chimerisms chimers chimes chimichanga chimichangas chiming chimney chimneypiece chimneypieces chimneys chimneysweep chimneysweeper chimneysweepers chimneysweeps chimp chimpanzee chimpanzees chimps chin china chinaberries chinaberry chinaman chinamen chinatown chinatowns chinaware chinch chincherinchee chincherinchees chinches chinchilla chinchillas chincoteague chindit chindits chindwin chine chines chinese chink chinked chinking chinks chinky chinless chinned chinning chino chinoiserie chinoiseries chinook chinookan chinooks chinos chinquapin chinquapins chins chintz chintzes chintzier chintziest chintzy chip chipboard chipboards chipewyan chipewyans chipmaker chipmakers chipmunk chipmunks chipped chippendale chipper chippered chippering chippers chippewa chippewas chippier chippies chippiest chipping chippy chips chiral chirality chiricahua chiricahuas chirk chirked chirking chirks chirographer chirographers chirographic chirographical chirography chiromancer chiromancers chiromancy chiron chiropodist chiropodists chiropody chiropractic chiropractor chiropractors chiropteran chiropterans chirp chirped chirpier chirpiest chirpily chirping chirps chirpy chirr chirred chirring chirrs chirrup chirruped chirruping chirrups chisel chiseled chiseler chiselers chiseling chisels chit chitchat chitchats chitchatted chitchatting chitin chitinous chitlins chiton chits chittagong chitter chittered chittering chitterlings chitters chivalric chivalries chivalrous chivalrously chivalrousness chivalry chive chives chivied chivies chivvied chivvies chivvy chivvying chivy chivying chlamydate chlamydeous chlamydes chlamydia chlamydiae chlamydial chlamydospore chlamydospores chlamys chlamyses chloasma chloasmata chloe chloracne chloracnes chloral chloramine chloramines chloramphenicol chlorate chlorates chlordane chlordiazepoxide chlorella chlorenchyma chloric chloride chlorides chloridic chlorinate chlorinated chlorinates chlorinating chlorination chlorinations chlorinator chlorinators chlorine chlorite chlorites chlorobenzene chlorocarbon chlorocarbons chlorofluorocarbon chloroform chloroformed chloroforming chloroforms chlorohydrin chloromycetin chlorophyll chloropicrin chloroplast chloroplasts chloroprene chloroquine chlorosis chlorothiazide chlorothiazides chlorotic chlorotically chlorpromazine chlortetracycline choanocyte choanocytes chock chockablock chocked chockfull chocking chocks chocoholic chocoholics chocolate chocolates choctaw choctawhatchee choctaws choice choicely choiceness choicer choices choicest choir choirboy choirboys choired choirgirl choirgirls choiring choirmaster choirmasters choirs choiseul choke chokeberries chokeberry chokebore chokebores chokecherries chokecherry choked chokedamp chokehold chokeholds chokepoint chokepoints choker chokers chokes chokier chokiest choking chokingly choky cholangiographic cholangiography cholecalciferol cholecyst cholecystectomies cholecystectomy cholecystitis cholecystokinin cholecysts cholelithiasis choler cholera choleraic choleric cholerically choleroid cholestasis cholesterin cholesterol cholestyramine choline cholinergic cholinesterase cholla chomp chomped chomping chomps chomsky chomskyan chondrification chondrified chondrifies chondrify chondrifying chondriosome chondriosomes chondrite chondrites chondritic chondrocrania chondrocranium chondrocraniums chondroma chondromalacia chondromas chondromata chondrule chondrules choose chooser choosers chooses choosier choosiest choosiness choosing choosy chop chophouse chophouses chopin chopine chopines choplogic chopped chopper choppered choppering choppers choppier choppiest choppily choppiness chopping choppy chops chopstick chopsticks choragi choragic choragus choral chorale chorales chorally chord chordal chordate chordates chorded chording chords chore chorea choreograph choreographed choreographer choreographers choreographic choreographically choreographies choreographing choreographs choreography chores choriamb choriambic choriambs choric chorine chorines chorioallantoic chorioallantois chorion chorionic chorions choripetalous chorister choristers chorizo chorizos chorographer chorographers chorographic chorographical chorographically chorography choroid choroids chortle chortled chortler chortlers chortles chortling chorus chorused choruses chorusing chose chosen chott chotts choucroute choucroutes chough choughs chouse choused chouses chousing chow chowchow chowchows chowder chowders chowed chowhound chowhounds chowing chows chresard chresards chrestomathic chrestomathies chrestomathy chris chrism chrismal chrisms chrisom chrisoms christ christchurch christen christendom christened christening christenings christens christi christian christiania christianities christianity christianization christianize christianized christianizer christianizers christianizes christianizing christianly christians christie christies christina christine christlike christlikeness christliness christly christmas christmases christmassy christmastide christmastime christmastimes christogram christograms christological christologies christology christopher chroma chromaffin chromate chromatic chromatically chromaticism chromaticity chromatics chromatid chromatids chromatin chromatinic chromatist chromatists chromatogram chromatograms chromatograph chromatographed chromatographer chromatographers chromatographic chromatographically chromatographing chromatographs chromatography chromatolysis chromatolytic chromatophilic chromatophore chromatophores chromatophoric chrome chromed chromes chromic chroming chromite chromium chromodynamics chromogen chromogenic chromogens chromolithograph chromolithographer chromolithographers chromolithographic chromolithographs chromolithography chromomere chromomeres chromomeric chromonema chromonemal chromonemata chromonemic chromophil chromophore chromophores chromophoric chromoplast chromoprotein chromoproteins chromosomal chromosomally chromosome chromosomes chromosomic chromosphere chromospheres chromospheric chromous chronaxie chronaxies chronic chronically chronicity chronicle chronicled chronicler chroniclers chronicles chronicling chronobiology chronogram chronogrammatic chronogrammatically chronograms chronograph chronographic chronographically chronographs chronological chronologically chronologies chronologist chronologists chronologize chronologized chronologizes chronologizing chronology chronometer chronometers chronometric chronometrical chronometrically chronometry chronoscope chronoscopes chronoscopic chrysalid chrysalides chrysalids chrysalis chrysalises chrysanthemum chrysanthemums chryselephantine chrysler chryslers chrysoberyl chrysolite chrysolites chrysomelid chrysomelids chrysoprase chrysoprases chrysotherapy chrysotile chrysotiles chthonic chub chubbier chubbiest chubbily chubbiness chubby chubs chuck chucked chuckhole chuckholes chucking chuckle chuckled chucklehead chuckleheaded chuckleheads chuckler chucklers chuckles chucklesome chuckling chucklingly chucks chuckwalla chuckwallas chuddar chuddars chufa chufas chuff chuffed chuffing chuffs chuffy chug chugalug chugalugged chugalugging chugalugs chugged chugger chuggers chugging chugs chukar chukars chukka chukkas chukker chukkers chum chummed chummier chummiest chummily chumminess chumming chummy chump chumped chumping chumps chums chungking chunk chunked chunkier chunkiest chunkily chunkiness chunking chunks chunky chunnel chunnels chunter chuntered chuntering chunters church churched churches churchgoer churchgoers churchgoing churchier churchiest churchill churchillian churching churchliness churchly churchman churchmanly churchmanship churchmen churchwarden churchwardens churchwoman churchwomen churchy churchyard churchyards churl churlish churlishly churlishness churls churn churned churner churners churning churns churr churred churrigueresque churring churro churros churrs chute chuted chutes chuting chutist chutists chutney chutneys chutzpa chutzpah chutzpas chuvash chuvashes chylaceous chyle chyles chylomicron chylomicrons chylous chyme chymes chymopapain chymopapains chymosin chymosins chymotrypsin chymotrypsins chymotryptic chymous châlons château châteaux châtelherault chèvre ciao cibber ciboria ciborium cicada cicadae cicadas cicala cicalas cicatrices cicatricial cicatricose cicatrix cicatrization cicatrize cicatrized cicatrizes cicatrizing cicero cicerone cicerones ciceroni ciceronian cichlid cichlids cider ciders cigar cigarette cigarettes cigarillo cigarillos cigars cilantro cilia ciliary ciliate ciliated ciliately ciliates ciliation cilice cilices cilicia cilician cilicians ciliolate cilium cimarron cimetidine cimex cimices cimmerian cinch cinched cincher cinchers cinches cinching cinchona cinchonas cinchonic cinchonine cinchonism cincinnati cincture cinctured cinctures cincturing cinder cindered cinderella cindering cinders cindery cindy cine cineaste cineastes cinema cinemagoer cinemagoers cinemas cinematheque cinematheques cinematic cinematically cinematization cinematizations cinematize cinematized cinematizes cinematizing cinematograph cinematographer cinematographers cinematographically cinematographs cinematography cineole cineoles cinephile cinephiles cineradiography cinerama cineraria cinerarium cinerary cinereous cinerin cinerins cines cingalese cingula cingulate cingulated cingulum cinnabar cinnamic cinnamon cinquain cinquains cinque cinquecentist cinquecentists cinquecento cinquefoil cinquefoils cinques cinéma cipher ciphered ciphering ciphers circa circadian circadianly circassia circassian circassians circe circean circinate circinately circinus circle circled circler circlers circles circlet circlets circling circuit circuited circuiting circuitous circuitously circuitousness circuitries circuitry circuits circuity circular circularities circularity circularization circularize circularized circularizer circularizers circularizes circularizing circularly circulars circulate circulated circulates circulating circulation circulations circulative circulator circulators circulatory circumambience circumambiency circumambient circumambiently circumambulate circumambulated circumambulates circumambulating circumambulation circumambulations circumboreal circumcise circumcised circumciser circumcisers circumcises circumcising circumcision circumcisions circumduction circumductions circumference circumferences circumferential circumflex circumflexes circumfluent circumfuse circumfused circumfuses circumfusing circumfusion circumlocution circumlocutions circumlocutorily circumlocutory circumlunar circumnavigate circumnavigated circumnavigates circumnavigating circumnavigation circumnavigations circumnavigator circumnavigators circumpolar circumrotate circumrotated circumrotates circumrotating circumrotation circumrotations circumrotatory circumscissile circumscribable circumscribe circumscribed circumscriber circumscribers circumscribes circumscribing circumscription circumscriptions circumscriptive circumscriptively circumsolar circumspect circumspection circumspectly circumstance circumstanced circumstances circumstancing circumstantial circumstantialities circumstantiality circumstantially circumstantiate circumstantiated circumstantiates circumstantiating circumstantiation circumstantiations circumterrestrial circumvallate circumvallated circumvallates circumvallating circumvallation circumvallations circumvent circumvented circumventer circumventers circumventing circumvention circumventions circumventive circumvents circumvolution circumvolutions circumvolve circumvolved circumvolves circumvolving circus circuses circusy cirque cirques cirrate cirrhoses cirrhosis cirrhotic cirri cirriped cirripeds cirrocumuli cirrocumulus cirrostrati cirrostratus cirrus ciré cisalpine cisatlantic ciscaucasia cisco ciscoes cislunar cismontane cist cistercian cistercians cistern cisterna cisternae cisternal cisterns cistron cistronic cistrons cists cit citable citadel citadels citation citational citations citatory cite cited cites cithaeron cithara citharas cither cithers citied cities citification citified citifies citify citifying citing citizen citizeness citizenesses citizenly citizenries citizenry citizens citizenship citlaltépetl citral citrals citrate citrates citric citriculture citricultures citriculturist citriculturists citrine citrines citroen citron citronella citronellal citronellals citronellas citronellol citronellols citrons citrulline citrullines citrus citruses cittern citterns city cityscape cityscapes citywide civet civets civic civics civil civilian civilianization civilianize civilianized civilianizes civilianizing civilians civilities civility civilizable civilization civilizations civilize civilized civilizer civilizers civilizes civilizing civilly civism civisms civitavecchia civvies clabber clabbered clabbering clabbers clack clacked clacker clackers clacking clacks clactonian clad cladding claddings clade clades cladist cladistic cladistically cladistics cladists cladoceran cladocerans cladode cladodes cladodial cladogenesis cladogenetic cladogenetically cladogram cladograms cladophyll cladophylls clads clafouti claim claimable claimant claimants claimed claimer claimers claiming claims clair clairaudience clairaudiences clairaudient claire clairvaux clairvoyance clairvoyant clairvoyants clam clamant clamantly clambake clambakes clamber clambered clamberer clamberers clambering clambers clammed clammer clammers clammier clammiest clammily clamminess clamming clammy clamor clamored clamorer clamorers clamoring clamorous clamorously clamorousness clamors clamp clampdown clampdowns clamped clamper clampers clamping clamps clams clamshell clamshells clamworm clamworms clan clandestine clandestinely clandestineness clandestinity clang clanged clanging clangor clangored clangoring clangorous clangorously clangors clangs clank clanked clanking clanks clanky clannish clannishly clannishness clans clansman clansmen clanswoman clanswomen clap clapboard clapboarded clapboarding clapboards clapped clapper clappers clapping claps claptrap claque claques clarence clarences claret clarets claries clarification clarifications clarificatory clarified clarifier clarifiers clarifies clarify clarifying clarinet clarinetist clarinetists clarinets clarion clarions clarity clarkia clarkias clary clash clashed clashes clashing clasp clasped clasper claspers clasping clasps class classed classes classic classical classicality classically classicalness classicism classicist classicists classicize classicized classicizes classicizing classics classier classiest classifiable classification classifications classificatorily classificatory classified classifieds classifier classifiers classifies classify classifying classiness classing classis classism classisms classist classless classman classmate classmates classmen classon classons classroom classrooms classy clast clastic clasts clathrate clathrates clatter clattered clatterer clatterers clattering clatters clattery claude claudication claudications claudius claus clausal clause clauses clausewitz claustrophobe claustrophobia claustrophobic claustrophobically clavate clavately clavichord clavichordist clavichordists clavichords clavicle clavicles clavicular claviculate clavier claviers clavus claw clawed clawing claws clay clayey clayish claylike claymation claymore claymores clays clayware clean cleanable cleaned cleaner cleaners cleanest cleaning cleanlier cleanliest cleanliness cleanly cleanness cleans cleanse cleansed cleanser cleansers cleanses cleansing cleanthes cleanup cleanups clear clearable clearance clearances clearchus cleared clearer clearers clearest clearheaded clearheadedly clearing clearinghouse clearinghouses clearings clearly clearness clears clearweed clearweeds clearwing clearwings cleat cleated cleating cleats cleavable cleavage cleavages cleave cleaved cleaver cleavers cleaves cleaving clef clefs cleft clefts cleisthenes cleistogamous cleistogamously cleistogamy cleistothecia cleistothecium clematis clematises clemenceau clemencies clemency clement clementine clementines clemently clench clenched clenches clenching cleome cleomes cleopatra clepsydra clepsydrae clepsydras clerestories clerestory clergies clergy clergyman clergymen clergywoman clergywomen cleric clerical clericalism clericalist clericalists clerically clericals clerics clerihew clerihews clerisies clerisy clerk clerkdom clerkdoms clerked clerking clerklier clerkliest clerkliness clerkly clerks clerkship clerkships cleveland clever cleverer cleverest cleverly cleverness cleves clevis clevises clew clewed clewing clews cliché clichéd clichés click clicked clicker clickers clicking clicks client clientage cliental clientele clienteles clients cliff cliffhanger cliffhangers cliffhanging clifford cliffs cliffy climacteric climacterics climactic climactically climate climates climatic climatically climatologic climatological climatologically climatologist climatologists climatology climax climaxed climaxes climaxing climb climbable climbed climber climbers climbing climbs clime climes clinandria clinandrium clinch clinched clincher clinchers clinches clinching cline clines cling clinger clingers clingfish clingfishes clinging clings clingstone clingstones clingy clinic clinical clinically clinician clinicians clinics clink clinked clinker clinkered clinkering clinkers clinking clinks clinometer clinometers clinometric clinometrical clinometry clinquant clinquants clinton clintonia clintonias clio cliometric cliometrician cliometricians cliometrics clios clip clipboard clipboards clipped clipper clippers clipping clippings clips clipsheet clipsheets clique cliqued cliques cliquey cliquing cliquish cliquishly cliquishness clisthenes clitella clitellum clitoral clitoris clitorises clive cloaca cloacae cloacal cloak cloaked cloaking cloakroom cloakrooms cloaks clobber clobbered clobbering clobbers clochard clochards cloche cloches clock clocked clocker clockers clocking clockmaker clockmakers clocks clockwise clockwork clockworks clod cloddish cloddishly cloddishness clodhopper clodhoppers clodhopping clods clofibrate clofibrates clog clogged clogging clogs cloisonné cloister cloistered cloistering cloisters cloistral clomiphene clomiphenes clomp clomped clomping clomps clonal clonally clone cloned cloner cloners clones clonic clonicity clonidine clonidines cloning clonism clonus clonuses clop clopped clopping clops cloque cloques close closed closedown closedowns closefisted closely closemouthed closeness closeout closeouts closer closers closes closest closet closeted closetful closeting closets closing closings clostridia clostridial clostridium closure closured closures closuring clot cloth clothbound clothe clothed clothes clothesbasket clothesbaskets clotheshorse clotheshorses clothesline clotheslined clotheslines clotheslining clothespin clothespins clothespress clothespresses clothier clothiers clothing clotho cloths clots clotted clotting cloture clotured clotures cloturing cloud cloudberries cloudberry cloudburst cloudbursts clouded cloudier cloudiest cloudily cloudiness clouding cloudland cloudlands cloudless cloudlessness cloudlet cloudlets clouds cloudscape cloudscapes cloudy clout clouted clouting clouts clove cloven clover cloverleaf cloverleaves clovers cloves clovis clown clowned clowning clownish clownishly clownishness clowns cloxacillin cloxacillins cloy cloyed cloying cloyingly cloyingness cloys cloze club clubbable clubbed clubber clubbers clubbier clubbiest clubbiness clubbing clubby clubface clubfaces clubfeet clubfoot clubfooted clubfoots clubhouse clubhouses clubman clubmate clubmates clubmen clubroom clubrooms clubs clubwoman clubwomen cluck clucked clucking clucks clue clued clueing clueless clues clump clumped clumping clumpings clumps clumpy clumsier clumsiest clumsily clumsiness clumsy clung cluniac clunk clunked clunker clunkers clunkier clunkiest clunking clunks clunky cluny clupeid clupeids cluster clustered clustering clusters clutch clutched clutches clutching clutter cluttered cluttering clutters clwyd clydesdale clydesdales clypeal clypeate clypeated clypei clypeus clyster clysters clytemnestra cnidoblast cnidoblasts cnut coacervate coacervated coacervates coacervating coacervation coach coachable coached coacher coachers coaches coaching coachman coachmen coachwork coact coacted coacting coaction coactions coactive coactively coactor coactors coacts coadaptation coadapted coadjutant coadjutants coadjutor coadjutors coadministration coadunate coadunation coadunative coagula coagulability coagulable coagulant coagulants coagulase coagulases coagulate coagulated coagulates coagulating coagulation coagulations coagulative coagulator coagulators coagulum coal coaled coaler coalers coalesce coalesced coalescence coalescent coalesces coalescing coalfield coalfields coalfish coalfishes coalification coalifications coaling coalition coalitionist coalitionists coalitions coals coalsack coalsacks coaming coamings coanchor coanchors coarctate coarctation coarctations coarse coarsely coarsen coarsened coarseness coarsening coarsens coarser coarsest coassignee coassignees coast coastal coasted coaster coasters coastguard coastguards coastguardsman coastguardsmen coasting coastland coastlands coastline coastlines coasts coastward coastwards coastwise coat coatdress coatdresses coated coati coatimundi coating coatings coatis coatroom coatrooms coats coattail coattails coatzacoalcos coauthor coauthored coauthoring coauthors coauthorship coax coaxed coaxer coaxers coaxes coaxial coaxing coaxingly cob cobalamin cobalamins cobalt cobaltic cobaltite cobaltites cobaltous cobber cobbers cobbett cobble cobbled cobbler cobblers cobbles cobblestone cobblestones cobbling cobden cobelligerent cobelligerents cobia cobias coble cobles cobnut cobnuts cobourg cobra cobras cobs coburg cobweb cobwebbed cobwebbing cobwebby cobwebs coca cocaine cocainism cocainisms cocainization cocainize cocainized cocainizes cocainizing cocaptain cocaptains cocarcinogen cocarcinogenic cocarcinogens cocas cocatalyst cocatalysts cocci coccid coccidia coccidioidomycosis coccidiosis coccidium coccids coccobacilli coccobacillus coccoid coccoids coccolith coccoliths coccus coccygeal coccyges coccyx cochair cochairman cochairmen cochairperson cochairpersons cochairs cochairwoman cochairwomen cochampion cochampions cochere cochineal cochlea cochleae cochlear cochleate cock cockade cockaded cockades cockaigne cockalorum cockalorums cockamamie cockatiel cockatiels cockatoo cockatoos cockatrice cockatrices cockboat cockboats cockchafer cockchafers cockcrow cocked cocker cockered cockerel cockerels cockering cockers cockeye cockeyed cockeyes cockfight cockfighting cockfights cockhorse cockhorses cockier cockiest cockily cockiness cocking cockle cockleboat cockleboats cocklebur cockleburs cockled cockles cockleshell cockleshells cockling cockloft cocklofts cockney cockneys cockpit cockpits cockroach cockroaches cocks cockscomb cockscombs cocksfoot cocksfoots cockshies cockshy cocksucker cocksuckers cocksure cocksurely cocksureness cocktail cocktails cocky coco cocoa cocoas cocobolo cocobolos cocomposer cocomposers coconspirator coconspirators coconut coconuts cocoon cocooned cocooning cocoonings cocoons cocos cocotte cocottes cocounsel cocoyam cocoyams cocreate cocreated cocreates cocreating cocreator cocreators cocteau cocultivate cocultivated cocultivates cocultivating cocultivation coculture cocurator cocurators cocurricular cocytus cod coda codas coddle coddled coddler coddlers coddles coddling code codebook codebooks codebreaker codebreakers codeclination codeclinations coded codefendant codefendants codeine codeines codemaker codemakers coder coders codes codesign codesigned codesigning codesigns codetermination codeterminations codetermine codetermined codetermines codetermining codevelop codeveloped codeveloper codevelopers codeveloping codevelops codex codfish codfishes codger codgers codices codicil codicillary codicils codification codifications codified codifier codifiers codifies codify codifying coding codirect codirected codirecting codirection codirector codirectors codirects codiscover codiscovered codiscoverer codiscoverers codiscovering codiscovers codling codlings codominance codominances codominant codominants codon codons codpiece codpieces codrive codriven codriver codrivers codrives codriving codrove cods codswallop codswallops coed coedit coedited coediting coeditor coeditors coedits coeds coeducation coeducational coeducationally coefficient coefficients coelacanth coelacanthine coelacanthous coelacanths coelentera coelenterate coelenterates coelenteric coelenteron coelom coelomate coelomic coeloms coenocyte coenocytes coenocytic coenuri coenurus coenzymatic coenzymatically coenzyme coenzymes coequal coequality coequally coequals coerce coerced coercer coercers coerces coercible coercing coercion coercionary coercive coercively coerciveness coessential coessentiality coessentially coessentialness coetaneous coetaneously coetaneousness coeternal coeternally coeternity coeur coeval coevally coevals coevolution coevolutionary coevolve coevolved coevolves coevolving coexecutor coexecutors coexist coexisted coexistence coexistent coexisting coexists coextend coextended coextending coextends coextension coextensive coextensively cofactor cofactors cofavorite cofavorites cofeature cofeatures coffee coffeecake coffeecakes coffeehouse coffeehouses coffeemaker coffeemakers coffeepot coffeepots coffees coffer cofferdam cofferdams coffered coffering coffers coffin coffined coffining coffins coffle coffled coffles coffling cofinance cofound cofounded cofounder cofounders cofounding cofounds cofunction cofunctions cog cogency cogeneration cogent cogently cogged cogging cogitable cogitate cogitated cogitates cogitating cogitation cogitations cogitative cogitatively cogitativeness cogitator cogitators cognac cognacs cognate cognates cognation cognition cognitional cognitive cognitively cognizable cognizably cognizance cognizant cognize cognized cognizes cognizing cognomen cognomens cognomina cognominal cognoscente cognoscenti cogon cogons cogs cogwheel cogwheels cohabit cohabitant cohabitants cohabitate cohabitation cohabitational cohabited cohabiter cohabiters cohabiting cohabits cohead coheads coheir coheiress coheiresses coheirs cohere cohered coherence coherencies coherency coherent coherently coheres cohering cohesion cohesionless cohesive cohesively cohesiveness coho coholder coholders cohort cohorts cohos cohosh cohoshes cohost cohosted cohostess cohostesses cohosting cohosts cohune cohunes coif coifed coiffeur coiffeurs coiffeuse coiffeuses coiffure coiffured coiffures coiffuring coifing coifs coign coigns coil coiled coiler coilers coiling coils coin coinable coinage coinages coincide coincided coincidence coincidences coincident coincidental coincidentally coincides coinciding coined coiner coiners coining coins coinsurance coinsurances coinsure coinsured coinsures coinsuring coinvent coinvented coinventing coinventor coinventors coinvents coinvestigator coinvestigators coinvestor coinvestors coir coirs coital coitally coition coitus cojoin cojoined cojoining cojoins coke coked cokehead cokeheads cokes coking col cola colada colander colanders colas colcannon colcannons colchicine colchicines colchicum colcothar colcothars cold coldcock coldcocked coldcocking coldcocks colder coldest coldhearted coldheartedly coldheartedness coldly coldness colds coldshoulder coldshouldered coldshouldering coldshoulders cole colead coleader coleaders coleading coleads colectomies colectomy coled colemanite colemanites coleopteran coleopterous coleoptile coleoptiles coleorhiza coleorhizae coleridge coles coleslaw coleus coleuses colewort coleworts coli colic colicin colicins colicky colicroot colicroots coliform colinear colinearity coliseum coliseums colistin colistins colitis collaborate collaborated collaborates collaborating collaboration collaborationism collaborationist collaborationists collaborations collaborative collaboratively collaborator collaborators collage collaged collagen collagenase collagenases collagenic collagenous collages collaging collagist collagists collapse collapsed collapses collapsibility collapsible collapsing collar collarbone collarbones collard collards collared collaring collars collate collated collateral collateralize collateralized collateralizes collateralizing collaterally collates collating collation collations collator collators colleague colleagues colleagueship collect collectable collectables collectanea collected collectedly collectedness collectible collectibles collecting collection collections collective collectively collectiveness collectives collectivism collectivist collectivistic collectivistically collectivists collectivities collectivity collectivization collectivize collectivized collectivizes collectivizing collector collectors collectorship collects colleen colleens college colleges collegia collegial collegiality collegially collegian collegians collegiate collegium collegiums collembolan collembolans collenchyma collenchymas collenchymatous collenchyme collenchymes collet collets collide collided collider colliders collides colliding collie collier collieries colliers colliery collies colligate colligated colligates colligating colligation colligative collimate collimated collimates collimating collimation collimator collimators collinear collinearity collingwood collins collinsia collision collisional collisions collocate collocated collocates collocating collocation collocational collocations collodion collogue collogued collogues colloguing colloid colloidal colloidally colloids collop collops colloquia colloquial colloquialism colloquialisms colloquially colloquialness colloquies colloquium colloquiums colloquy collotype collotypes collude colluded colluder colluders colludes colluding collusion collusive collusively collusiveness colluvia colluvial colluvium colluviums collyria collyrium collyriums collywobbles coloboma colobomata colobomatous colocynth colocynths cologne colognes colombia colombian colombians colombo colon colonel colonelcy colonels colonelship colonial colonialism colonialist colonialists colonially colonials colonic colonies colonist colonists colonitis colonization colonizations colonize colonized colonizer colonizers colonizes colonizing colonnade colonnaded colonnades colonoscope colonoscopes colonoscopies colonoscopy colons colony colophon colophons color colorability colorable colorableness colorably colorado colorant colorants coloration coloratura coloraturas colorblind colorblindness colorbred colorbreed colorbreeding colorbreeds colorcast colorcasted colorcasting colorcasts colorectal colored coloreds colorer colorers colorfast colorfastness colorful colorfully colorfulness colorific colorimeter colorimeters colorimetric colorimetrically colorimetry coloring colorings colorist coloristic colorists colorization colorizations colorize colorized colorizer colorizers colorizes colorizing colorless colorlessly colorlessness colors coloscope coloscopes coloscopies coloscopy colossal colossally colosseum colossi colossians colossus colossuses colostomies colostomy colostral colostrum colpitis colportage colportages colporteur colporteurs colposcope colposcopes colposcopic colposcopies colposcopy cols colt coltish coltishly coltishness colts coltsfoot coltsfoots colubrid colubrids colubrine colugo colugos columba columbaria columbarium columbia columbian columbine columbines columbite columbites columbium columbus columella columellae columellar columellate column columnar columnea columned columniation columniations columnist columnists columns colza colzas coma comae comal comanage comanaged comanagement comanager comanagers comanages comanaging comanche comanches comas comate comates comatose comatosely comatulid comatulids comb combat combatant combatants combated combating combative combatively combativeness combats combed comber combers combinable combination combinational combinations combinative combinatorial combinatorics combinatory combine combined combiner combiners combines combing combings combining combinings combo combos combs combust combusted combustibility combustible combustibles combustibly combusting combustion combustive combustor combustors combusts come comeback comebacks comecon comedian comedians comedic comedically comedienne comediennes comedies comedo comedogenic comedones comedos comedown comedowns comedy comelier comeliest comeliness comely comember comembers comer comers comes comestible comestibles comet cometary cometic comets comeuppance comfier comfiest comfit comfits comfort comfortable comfortableness comfortably comforted comforter comforters comforting comfortingly comfortless comfortlessly comforts comfrey comfreys comfy comic comical comicality comically comicalness comice comices comics coming comings comintern comique comitia comitial comities comity comix comma command commandant commandants commanded commandeer commandeered commandeering commandeers commander commanders commanding commandingly commandingness commandment commandments commando commandos commands commas comme commedia commemorate commemorated commemorates commemorating commemoration commemorations commemorative commemoratives commemorator commemorators commemoratory commence commenced commencement commencements commencer commencers commences commencing commend commendable commendableness commendably commendation commendations commendatory commended commending commends commensal commensalism commensally commensals commensurability commensurable commensurably commensurate commensurately commensuration comment commentarial commentaries commentary commentate commentated commentates commentating commentator commentators commented commenting comments commerce commercial commercialism commercialist commercialistic commercialists commercialization commercialize commercialized commercializes commercializing commercially commercials commie commies commination comminations comminatory commingle commingled commingles commingling comminute comminuted comminutes comminuting comminution comminutions commiserate commiserated commiserates commiserating commiseration commiserations commiserative commiseratively commiserator commiserators commissar commissariat commissariats commissaries commissars commissary commission commissionaire commissionaires commissional commissioned commissioner commissioners commissionership commissioning commissions commissural commissure commissures commissurotomies commissurotomy commit commitment commitments commits committable committal committals committed committee committeeman committeemen committees committeewoman committeewomen committing commix commixed commixes commixing commixture commixtures commode commodes commodious commodiously commodiousness commodities commodity commodore commodores common commonage commonages commonalities commonality commonalties commonalty commoner commoners commonest commonly commonness commonplace commonplaceness commonplaces commons commonsense commonsensible commonsensibly commonsensical commonweal commonwealth commonwealths commotion commove commoved commoves commoving communal communalism communalist communalistic communalists communality communalize communalized communalizes communalizing communally communard communards commune communed communes communicability communicable communicableness communicably communicant communicants communicate communicated communicates communicating communication communicational communications communicative communicatively communicativeness communicator communicators communicatory communing communion communions communiqué communiqués communism communist communistic communistically communists communitarian communitarians communities community communization communize communized communizes communizing commutability commutable commutate commutated commutates commutating commutation commutations commutative commutativity commutator commutators commute commuted commuter commuters commutes commuting como comonomer comonomers comoran comorans comoros comose comp compact compacted compacting compaction compactions compactly compactness compactor compactors compacts companied companies companion companionable companionableness companionably companionate companioned companioning companionless companions companionship companionships companionway companionways company companying comparability comparable comparableness comparably comparatist comparatists comparative comparatively comparatives comparator comparators compare compared comparer comparers compares comparing comparison comparisons comparitor compart comparted comparting compartment compartmental compartmentalization compartmentalize compartmentalized compartmentalizes compartmentalizing compartmentation compartmented compartmenting compartments comparts compass compassable compassed compasses compassing compassion compassionate compassionated compassionately compassionateness compassionates compassionating compassionless compatibility compatible compatibleness compatibles compatibly compatriot compatriotic compatriots comped compeer compeers compel compellable compellably compellation compellations compelled compeller compellers compelling compellingly compels compend compendia compendious compendiously compendiousness compendium compendiums compends compensable compensate compensated compensates compensating compensation compensational compensations compensative compensator compensators compensatory compere compered comperes compering compete competed competence competencies competency competent competently competes competing competition competitions competitive competitively competitiveness competitor competitors compilation compilations compile compiled compiler compilers compiles compiling comping complacence complacency complacent complacently complain complainant complainants complained complainer complainers complaining complains complaint complaints complaisance complaisant complaisantly compleat complect complected complecting complects complement complemental complementally complementarily complementariness complementarity complementary complementation complementations complemented complementing complements complete completed completely completeness completer completes completest completing completion completions completive complex complexes complexion complexional complexioned complexions complexities complexity complexly complexness compliance compliancy compliant compliantly complicacies complicacy complicate complicated complicatedly complicatedness complicates complicating complication complications complicit complicities complicity complied complier compliers complies compliment complimentarily complimentary complimented complimenting compliments complin compline complins complot complots comply complying compo component componential components componentwise comport comported comporting comportment comports compos compose composed composedly composedness composer composers composes composing composite compositely compositeness composites composition compositional compositionally compositions compositive compositor compositorial compositors compost composted compostela composting composts composure compote compotes compound compoundable compounded compounder compounding compounds comprador compradors comprehend comprehended comprehendible comprehending comprehendingly comprehends comprehensibility comprehensible comprehensibleness comprehensibly comprehension comprehensions comprehensive comprehensively comprehensiveness comprehensives compress compressed compresses compressibility compressible compressibleness compressing compression compressional compressions compressive compressively compressor compressors comprisable comprise comprised comprises comprising compromise compromised compromiser compromisers compromises compromising comps comptroller comptrollers compulsion compulsions compulsive compulsively compulsiveness compulsives compulsivity compulsories compulsorily compulsoriness compulsory compunction compunctions compunctious compunctiously compurgation compurgations compurgator compurgators computability computable computably computation computational computationally computations compute computed computer computerate computerdom computerdoms computerese computerist computerists computerizable computerization computerize computerized computerizes computerizing computers computes computing compôte compôtes comrade comradely comrades comradeship comsat comsymp comsymps comus comédie con conakry conan conation conational conations conative concatenate concatenated concatenates concatenating concatenation concatenations concave concaved concavely concaveness concaves concaving concavities concavity conceal concealable concealed concealer concealers concealing concealment conceals concede conceded concededly conceder conceders concedes conceding conceit conceited conceitedly conceitedness conceiting conceits conceivability conceivable conceivableness conceivably conceive conceived conceiver conceivers conceives conceiving concelebrant concelebrants concelebrate concelebrated concelebrates concelebrating concelebration concelebrations concenter concentered concentering concenters concentrate concentrated concentrates concentrating concentration concentrations concentrative concentratively concentrator concentrators concentric concentrically concentricity concept conceptacle conceptacles conception conceptional conceptions conceptive conceptively concepts conceptual conceptualism conceptualist conceptualistic conceptualistically conceptualists conceptuality conceptualization conceptualizations conceptualize conceptualized conceptualizer conceptualizers conceptualizes conceptualizing conceptually conceptus concern concerned concernedly concerning concernment concernments concerns concert concerted concertedly concertgoer concertgoers concertgoing concerti concertina concertinas concerting concertino concertinos concertize concertized concertizes concertizing concertmaster concertmasters concertmistress concertmistresses concerto concertos concerts concession concessionaire concessionaires concessional concessionary concessioner concessioners concessions concessive concessively conch concha conchae conchal conches conchiferous conchiolin conchiolins conchoidal conchoidally conchological conchologist conchologists conchology conchs concierge concierges conciliable conciliar conciliate conciliated conciliates conciliating conciliation conciliations conciliator conciliators conciliatory concinnities concinnity concise concisely conciseness concision concisions conclave conclaves conclude concluded concluder concluders concludes concluding conclusion conclusions conclusive conclusively conclusiveness conclusory concoct concocted concocter concocters concocting concoction concoctions concocts concomitance concomitant concomitantly concomitants concord concordance concordances concordant concordantly concordat concordats concords concours concourse concourses concrescence concrescent concrete concreted concretely concreteness concretes concreting concretion concretionary concretions concretism concretisms concretist concretists concretization concretize concretized concretizes concretizing concrète concubinage concubinages concubine concubines concupiscence concupiscent concur concurred concurrence concurrencies concurrency concurrent concurrently concurring concurs concuss concussed concusses concussing concussion concussions concussive concussively condemn condemnable condemnation condemnations condemnatory condemned condemner condemners condemning condemns condensability condensable condensate condensates condensation condensational condensations condense condensed condenser condensers condenses condensing condescend condescended condescendence condescendences condescender condescenders condescending condescendingly condescends condescension condign condignly condiment condimental condiments condition conditional conditionally conditionals conditioned conditioner conditioners conditioning conditionings conditions condo condolatory condole condoled condolence condolences condolent condoler condolers condoles condoling condom condominial condominium condominiums condoms condonable condonation condonations condone condoned condoner condoners condones condoning condor condors condos condottiere condottieri conduce conduced conducer conducers conduces conducing conducingly conducive conduciveness conduct conductance conducted conductibility conductible conductimetry conducting conduction conductive conductivities conductivity conductor conductorial conductors conductorship conductress conductresses conducts conduit conduits conduplicate conduplication condylar condyle condyles condyloid condyloma condylomas condylomata condylomatous cone coned coneflower coneflowers conenose cones conestoga conestogas coney coneys confab confabbed confabbing confabs confabulate confabulated confabulates confabulating confabulation confabulations confabulator confabulators confabulatory confect confected confecting confection confectionaries confectionary confectioned confectioner confectioneries confectioners confectionery confectioning confections confects confederacies confederacy confederal confederalist confederalists confederate confederated confederates confederating confederation confederationism confederationist confederationists confederations confederative confer conferee conferees conference conferences conferencing conferential conferment conferrable conferral conferrals conferred conferrer conferrers conferring confers confess confessable confessed confessedly confesses confessing confession confessional confessionals confessions confessor confessors confetti confidant confidante confidantes confidants confide confided confidence confidences confident confidential confidentiality confidentially confidentialness confidently confider confiders confides confiding confidingly confidingness configurable configuration configurational configurationally configurationism configurations configurative configure configured configures configuring confinable confine confined confinement confinements confiner confiners confines confining confirm confirmability confirmable confirmand confirmands confirmation confirmations confirmatory confirmed confirmedly confirmer confirmers confirming confirms confiscable confiscate confiscated confiscates confiscating confiscation confiscations confiscator confiscators confiscatory confiteor confiteors confiture confitures conflagrant conflagration conflagrations conflate conflated conflates conflating conflation conflations conflict conflicted conflicting confliction conflictive conflicts conflictual confluence confluences confluent confluents conflux confluxes confocal confocally conform conformability conformable conformableness conformably conformal conformance conformant conformation conformational conformationally conformations conformed conformer conformers conforming conformist conformists conformities conformity conforms confound confounded confoundedly confoundedness confounder confounders confounding confounds confraternities confraternity confrere confreres confront confrontation confrontational confrontationist confrontationists confrontations confrontative confronted confronter confronters confronting confrontment confronts confucian confucianism confucianist confucianists confucians confucius confusable confuse confused confusedly confusedness confuser confusers confuses confusing confusingly confusion confusional confusions confutable confutation confutative confute confuted confuter confuters confutes confuting conga congaed congaing congas congeal congealable congealed congealer congealers congealing congealment congeals congelation congelations congener congeneric congenerous congeners congenial congeniality congenially congenialness congenital congenitally conger congeries congers congest congested congesting congestion congestive congests congii congius conglobate conglobated conglobates conglobating conglobation conglobe conglobed conglobes conglobing conglomerate conglomerated conglomerates conglomeratic conglomerating conglomeration conglomerations conglomerator conglomerators conglutinate conglutinated conglutinates conglutinating conglutination congo congolese congou congous congratulate congratulated congratulates congratulating congratulation congratulations congratulator congratulators congratulatory congregant congregants congregate congregated congregates congregating congregation congregational congregationalism congregationalist congregationalists congregations congregative congregativeness congregator congregators congress congresses congressional congressionally congressman congressmen congresspeople congressperson congresspersons congresswoman congresswomen congreve congruence congruences congruencies congruency congruent congruently congruities congruity congruous congruously congruousness congé conic conical conics conidia conidial conidiophore conidiophores conidiophorous conidium conies conifer coniferous conifers coniine coniines coning conium coniums conjecturable conjecturably conjectural conjecturally conjecture conjectured conjecturer conjecturers conjectures conjecturing conjoin conjoined conjoiner conjoiners conjoining conjoins conjoint conjointly conjugal conjugality conjugally conjugant conjugants conjugate conjugated conjugately conjugates conjugating conjugation conjugational conjugationally conjugations conjugative conjugator conjugators conjunct conjunction conjunctional conjunctionally conjunctions conjunctiva conjunctivae conjunctival conjunctivas conjunctive conjunctively conjunctives conjunctivitis conjunctly conjuncts conjuncture conjunctures conjunto conjuntos conjuration conjure conjured conjurer conjurers conjures conjuring conjuror conjurors conk conked conker conkers conking conks conky connate connately connateness connatural connaturality connaturally connaturalness connect connectable connected connectedly connectedness connectible connecticut connecting connection connectional connectionless connections connective connectively connectives connectivity connector connectors connects conned conner conners conning conniption conniptions connivance connive connived connivent conniver connivers connivery connives conniving connoisseur connoisseurs connoisseurship connotation connotations connotative connotatively connote connoted connotes connoting connubial connubialism connubiality connubially conodont conodonts conoid conoids conominee conominees conquer conquerable conquered conquering conqueror conquerors conquers conquest conquests conquian conquians conquistador conquistadors conrad cons consanguine consanguineous consanguineously consanguinities consanguinity conscience conscienceless consciences conscientious conscientiously conscientiousness conscionable conscious consciously consciousness conscript conscripted conscripting conscription conscripts consecrate consecrated consecrates consecrating consecration consecrations consecrative consecrator consecrators consecratory consecution consecutive consecutively consecutiveness consensual consensually consensus consensuses consent consentaneity consentaneous consentaneously consentaneousness consented consenter consenters consenting consents consequence consequences consequent consequential consequentialities consequentiality consequentially consequentialness consequently consequents conservable conservancies conservancy conservation conservational conservationist conservationists conservations conservatism conservative conservatively conservativeness conservatives conservatize conservatized conservatizes conservatizing conservatoire conservatoires conservator conservatorial conservatories conservators conservatorship conservatory conserve conserved conserver conservers conserves conserving consider considerable considerably considerate considerately considerateness consideration considerations considered considerer considerers considering considers consigliere consiglieri consign consignable consignation consigned consignee consignees consigning consignment consignments consignor consignors consigns consist consisted consistence consistencies consistency consistent consistently consisting consistorial consistories consistory consists consociate consociated consociates consociating consociation consociational consociations consolable consolably consolation consolations consolatory console consoled consoler consolers consoles consolidate consolidated consolidates consolidating consolidation consolidations consolidator consolidators consoling consolingly consolute consommé consommés consonance consonant consonantal consonantally consonantly consonants consort consorted consortia consortial consorting consortium consortiums consorts conspecific conspecifics conspectus conspectuses conspicuity conspicuous conspicuously conspicuousness conspiracies conspiracist conspiracists conspiracy conspirator conspiratorial conspiratorialist conspiratorialists conspiratorially conspirators conspire conspired conspirer conspirers conspires conspiring conspiringly constable constables constableship constabular constabularies constabulary constance constancy constant constantan constantans constantine constantinople constantly constants constellate constellated constellates constellating constellation constellational constellations constellatory consternate consternated consternates consternating consternation constipate constipated constipates constipating constipation constituencies constituency constituent constituently constituents constitute constituted constituter constituters constitutes constituting constitution constitutional constitutionalism constitutionalist constitutionalists constitutionality constitutionalization constitutionalize constitutionalized constitutionalizes constitutionalizing constitutionally constitutionals constitutions constitutive constitutively constrain constrainable constrained constrainedly constrainer constrainers constraining constrains constraint constraints constrict constricted constricting constriction constrictions constrictive constrictively constrictor constrictors constricts constringe constringed constringency constringent constringes constringing construal construct constructed constructible constructing construction constructional constructionally constructionist constructionists constructions constructive constructively constructiveness constructivism constructivisms constructivist constructivists constructor constructors constructs construe construed construes construing consubstantial consubstantiate consubstantiated consubstantiates consubstantiating consubstantiation consubstantiations consuetude consuetudinary consul consular consulate consulates consuls consulship consult consultancies consultancy consultant consultants consultantship consultation consultations consultative consulted consulter consulters consulting consultor consultors consults consumable consumables consume consumed consumedly consumer consumerism consumerist consumeristic consumerists consumers consumership consumes consuming consummate consummated consummately consummates consummating consummation consummations consummative consummator consummators consummatory consumption consumptive consumptively consumptives contact contacted contacting contacts contactual contactually contagia contagion contagious contagiously contagiousness contagium contain containable contained container containerboard containerboards containerization containerize containerized containerizes containerizing containerport containerports containers containership containing containment containments contains contaminant contaminants contaminate contaminated contaminates contaminating contamination contaminations contaminative contaminator contaminators conte contemn contemned contemner contemners contemning contemns contemplate contemplated contemplates contemplating contemplation contemplations contemplative contemplatively contemplativeness contemplatives contemplator contemplators contemporaneity contemporaneous contemporaneously contemporaneousness contemporaries contemporarily contemporary contemporization contemporize contemporized contemporizes contemporizing contempt contemptibility contemptible contemptibleness contemptibly contempts contemptuous contemptuously contemptuousness contend contended contender contenders contending contends content contented contentedly contentedness contenting contention contentions contentious contentiously contentiousness contentment contents conterminous conterminously conterminousness contes contessa contessas contest contestable contestant contestants contestation contested contester contesters contesting contests context contexts contextual contextualization contextualize contextualized contextualizes contextualizing contextually contextural contexture contextures contiguities contiguity contiguous contiguously contiguousness continence continent continental continentalism continentalist continentalists continentality continentally continentals continently continents contingence contingencies contingency contingent contingently contingents continua continuable continual continually continuance continuances continuant continuants continuation continuations continuative continuatively continuatives continuator continuators continue continued continuer continuers continues continuing continuities continuity continuo continuos continuous continuously continuousness continuum continuums contort contorted contortedly contortedness contorting contortion contortionist contortionistic contortionists contortions contortive contorts contour contoured contouring contours contra contraband contrabandage contrabandist contrabandists contrabands contrabass contrabasses contrabassist contrabassists contrabassoon contrabassoons contraception contraceptive contraceptives contract contracted contractibility contractible contractibleness contractile contractility contracting contraction contractions contractor contractors contracts contractual contractually contracture contractures contracyclical contradance contradances contradict contradictable contradicted contradicter contradicters contradicting contradiction contradictions contradictor contradictories contradictorily contradictoriness contradictors contradictory contradicts contradistinction contradistinctions contradistinctive contradistinctively contradistinguish contradistinguished contradistinguishes contradistinguishing contragestation contragestive contragestives contrail contrails contraindicate contraindicated contraindicates contraindicating contraindication contraindications contraindicative contraire contralateral contralto contraltos contraposition contrapositions contrapositive contrapositives contrapposto contrappostos contraption contraptions contrapuntal contrapuntally contrapuntist contrapuntists contrarian contrarians contraries contrarieties contrariety contrarily contrariness contrarious contrariously contrariwise contrary contras contrast contrasted contrasting contrastive contrastively contrasts contrasty contrate contravariance contravene contravened contravener contraveners contravenes contravening contravention contretemps contribute contributed contributes contributing contribution contributions contributive contributively contributiveness contributor contributories contributors contributory contrite contritely contriteness contrition contrivance contrivances contrive contrived contrivedly contriver contrivers contrives contriving control controllability controllable controllably controlled controller controllers controllership controlling controls controversial controversialist controversialists controversiality controversially controversies controversy controvert controverted controvertibility controvertible controvertibly controverting controverts contumacies contumacious contumaciously contumaciousness contumacy contumelies contumelious contumeliously contumely contuse contused contuses contusing contusion contusions conundrum conundrums conurbation convalesce convalesced convalescence convalescent convalescents convalesces convalescing convect convected convecting convection convectional convective convectively convector convectors convects convenable convene convened convener conveners convenes convenience conveniences conveniencies conveniency convenient conveniently convening convent conventicle conventicler conventiclers conventicles convention conventional conventionalism conventionalist conventionalists conventionalities conventionality conventionalization conventionalize conventionalized conventionalizes conventionalizing conventionally conventioneer conventioneers conventions convents conventual conventuals converge converged convergence convergencies convergency convergent converges converging conversance conversances conversancies conversancy conversant conversantly conversation conversational conversationalist conversationalists conversationally conversations conversazione conversaziones converse conversed conversely converses conversing conversion conversional conversionary conversions convert converted converter converters convertibility convertible convertibleness convertibles convertibly converting convertiplane convertiplanes converts convex convexities convexity convexly convey conveyable conveyance conveyancer conveyancers conveyances conveyancing conveyancings conveyed conveyer conveyers conveying conveyor conveyors conveys convict convicted convicting conviction convictional convictions convictive convictively convicts convince convinced convincement convincer convincers convinces convincible convincing convincingly convincingness convivial conviviality convivially convocation convocational convocations convoke convoked convoker convokers convokes convoking convolute convoluted convolutely convolutes convoluting convolution convolutional convolutions convolve convolved convolves convolving convolvuli convolvulus convolvuluses convoy convoyed convoying convoys convulsant convulsants convulse convulsed convulses convulsing convulsion convulsions convulsive convulsively convulsiveness cony coo cooed cooer cooers cooing cook cookbook cookbooks cooked cooker cookeries cookers cookery cookhouse cookhouses cookie cookies cooking cookout cookouts cooks cooktown cookware cool coolant coolants cooled cooler coolers coolest coolgardie coolheaded coolie coolies cooling coolish coolly coolness cools coon cooncan cooncans coonhound coonhounds coons coonskin coonskins coontie coonties coop cooped cooper cooperage cooperate cooperated cooperates cooperating cooperation cooperationist cooperationists cooperative cooperatively cooperativeness cooperatives cooperator cooperators coopers cooping coops coordinate coordinated coordinately coordinateness coordinates coordinating coordination coordinations coordinative coordinator coordinators coos coot cootie cooties coots cop copacetic copaiba copal coparcenaries coparcenary coparcener coparceners copartner copartners copartnership cope coped copenhagen copepod copepods coper copernican copernicans copernicus copers copes copestone copestones copied copier copiers copies copilot copilots coping copings copious copiously copiousness coplanar coplanarity copland copolymer copolymeric copolymerization copolymerize copolymerized copolymerizes copolymerizing copolymers copout copouts copped copper copperas coppered copperfield copperhead copperheads coppering copperleaf copperleafs copperplate copperplates coppers coppersmith coppersmiths copperware copperwares coppery coppice coppices copping copra copresent copresented copresenting copresents copresident copresidents coprince coprinces coprincipal coprincipals coprisoner coprisoners coprocessing coprocessor coprocessors coproduce coproduced coproducer coproducers coproduces coproducing coproduction coproductions coprolalia coprolalias coprolite coprolites coprolitic coprology copromoter copromoters coprophagous coprophagy coprophilia coprophiliac coprophiliacs coprophilic coprophilous coproprietor coproprietors coprosperity cops copse copses copt copter copters coptic copts copublish copublished copublisher copublishers copublishes copublishing copula copular copulas copulate copulated copulates copulating copulation copulations copulative copulatively copulatory copy copyable copybook copybooks copyboy copyboys copycat copycats copycatted copycatting copydesk copydesks copyedit copyedited copyediting copyeditor copyeditors copyedits copyholder copyholders copying copyist copyists copyreader copyreaders copyright copyrightable copyrighted copyrighter copyrighters copyrighting copyrights copywriter copywriters coq coquet coquetries coquetry coquets coquette coquetted coquettes coquetting coquettish coquettishly coquettishness coquille coquilles coquina coquinas coquito coquitos coracle coracles coracoid coracoids coral coralberries coralberry coralline corallines coralloid coralroot coralroots corals corban corbans corbeil corbeils corbel corbeled corbeling corbelings corbels corbina corbinas corbusier corcovado cord cordage cordate cordately corded cordelia corder corders cordial cordiale cordiality cordially cordialness cordials cordierite cordierites cordiform cordillera cordilleran cordilleras cording cordite cordless cordlessly cordoba cordon cordoned cordoning cordons cordova cordovan cordovans cords corduroy corduroyed corduroying corduroys cordwood core corecipient corecipients cored coreligionist coreligionists coreopsis corepressor corepressors corer corers cores coresearcher coresearchers coresident coresidential coresidents corespondency corespondent corespondents corf corfu corgi corgis coria coriaceous coriander coring corinth corinthian corinthians coriolanus corium cork corkage corkages corkboard corkboards corked corker corkers corkier corkiest corkiness corking corks corkscrew corkscrewed corkscrewing corkscrews corkwood corkwoods corky corm cormel cormels cormorant cormorants corms corn cornball cornballs cornbraid cornbraided cornbraiding cornbraids cornbread corncob corncobs corncrake corncrakes corncrib corncribs corndodger corndodgers cornea corneal corneas corned corneitis cornel cornell cornels corneous corner cornerback cornerbacks cornered cornering corners cornerstone cornerstones cornerwise cornet cornetist cornetists cornets cornfield cornfields cornflower cornflowers cornhusk cornhusker cornhuskers cornhusking cornhuskings cornhusks cornice corniced cornices corniche cornicing cornicle cornicles corniculate cornier corniest cornification cornifications cornified cornifies cornify cornifying cornily corniness corning cornish cornishman cornishmen cornishwoman cornishwomen cornmeal cornpone cornrow cornrowed cornrowing cornrows corns cornstalk cornstalks cornstarch cornu cornua cornual cornucopia cornucopian cornucopias cornute cornwall corny corolla corollaries corollary corollas corollate corona coronae coronagraph coronagraphs coronal coronals coronaries coronary coronas coronation coronations coroner coroners coronership coronet coronets corot corotate corotated corotates corotating corotation corotational coroutine coroutines corpocracies corpocracy corpocratic corpora corporal corporality corporally corporals corporate corporately corporation corporations corporative corporator corporators corporeal corporeality corporeally corporealness corporeity corposant corposants corps corpse corpses corpsman corpsmen corpulence corpulent corpulently corpus corpuscle corpuscles corpuscular corpuses corrade corraded corrades corrading corral corralled corralling corrals corrasion corrasive correct correctable corrected correcting correction correctional corrections correctitude correctitudes corrective correctively correctives correctly correctness corrector correctors corrects correggio correlate correlated correlates correlating correlation correlational correlations correlative correlatively correlatives correspond corresponded correspondence correspondences correspondencies correspondency correspondent correspondently correspondents corresponding correspondingly corresponds corresponsive corresponsively corrida corridas corridor corridors corrie corries corrigenda corrigendum corrigibility corrigible corrigibly corrival corrivalry corrivals corroborant corroborate corroborated corroborates corroborating corroboration corroborations corroborative corroborator corroborators corroboratory corroboree corroborees corrode corroded corrodes corrodible corroding corrosible corrosion corrosions corrosive corrosively corrosiveness corrosives corrosivity corrugate corrugated corrugates corrugating corrugation corrugations corrupt corrupted corrupter corrupters corruptibility corruptible corruptibleness corruptibly corrupting corruption corruptionist corruptionists corruptions corruptive corruptly corruptness corrupts corsage corsages corsair corsairs corselet corselets corset corseted corseting corsets corsica corsican corsicans cortege corteges cortex cortexes cortez cortical cortically corticate cortices corticoid corticoids corticolous corticospinal corticosteroid corticosteroids corticosterone corticosterones corticotrophin corticotrophins corticotropin corticotropins cortin cortins cortisol cortisols cortisone cortège cortèges coruler corulers corundum corunna coruscant coruscate coruscated coruscates coruscating coruscation coruscations coruña corves corvette corvettes corvine corvus corvée corybant corybantes corybantic corybants corydalis corymb corymbose corymbosely corymbous corynebacterium corynebacteriums coryneform coryphaei coryphaeus coryphée coryphées coryza cosa coscript coscripted coscripting coscripts cosec cosecant cosecants coseismal coseismic cosign cosignatories cosignatory cosigned cosigner cosigners cosigning cosigns cosine cosines cosmetic cosmetically cosmetician cosmeticians cosmeticize cosmeticized cosmeticizes cosmeticizing cosmetics cosmetologist cosmetologists cosmetology cosmic cosmically cosmochemical cosmochemistry cosmodrome cosmodromes cosmogenic cosmogonic cosmogonical cosmogonically cosmogonies cosmogonist cosmogonists cosmogony cosmographer cosmographers cosmographic cosmographical cosmographically cosmographies cosmography cosmologic cosmological cosmologically cosmologies cosmologist cosmologists cosmology cosmonaut cosmonauts cosmopolis cosmopolitan cosmopolitanism cosmopolitans cosmopolite cosmopolites cosmopolitism cosmos cosmoses cosponsor cosponsored cosponsoring cosponsors cosponsorship cossack cossacks cosset cosseted cosseting cossets cost costa costae costal costar costard costards costarred costarring costars costate costed coster costermonger costermongers costers costing costings costive costively costiveness costless costlessness costlier costliest costliness costly costmaries costmary costochondritis costrel costrels costs costume costumed costumer costumers costumes costuming cosurfactant cosy cot cotangent cotangential cotangents cote cotenancy cotenant cotenants coterie coteries coterminous cotes cothurni cothurnus cotidal cotillion cotillions cotman cotoneaster cotoneasters cotopaxi cotransduce cotransduced cotransduces cotransducing cotransduction cotransfer cotransferred cotransferring cotransfers cotransport cotrustee cotrustees cots cotswold cotswolds cotta cottae cottage cottager cottagers cottages cottas cotter cotters cotton cottoned cottoning cottonmouth cottonmouths cottons cottonseed cottonseeds cottontail cottontails cottonweed cottonweeds cottonwood cottonwoods cottony coturnix coturnixs cotyledon cotyledonal cotyledonous cotyledons cotyloid couch couchant couched coucher couchers couches couchette couchettes couching cougar cougars cough coughed coughing coughs could could've couldest couldn couldn't couldst coulee coulees coulisse coulisses couloir couloirs coulomb coulombic coulombs coulometric coulometrically coulometry coulter coulters coumaric coumarin coumarins council councilman councilmen councilor councilors councils councilwoman councilwomen counsel counseled counseling counselor counselors counselorship counsels count countability countable countably countdown countdowns counted countenance countenanced countenancer countenancers countenances countenancing counter counteraccusation counteract counteracted counteracting counteraction counteractions counteractive counteractively counteracts counteradaptation counteradvertising counteragent counteraggression counterargue counterargued counterargues counterarguing counterargument counterarguments counterassault counterattack counterattacked counterattacker counterattacking counterattacks counterbalance counterbalanced counterbalances counterbalancing counterbid counterblast counterblockade counterblow counterblows countercampaign counterchallenge counterchallenges counterchange counterchanged counterchanges counterchanging countercharge countercharged countercharges countercharging countercheck counterchecked counterchecking counterchecks counterclaim counterclaimant counterclaimants counterclaimed counterclaiming counterclaims counterclockwise countercommercial countercomplaint counterconditioning counterconditionings counterconspiracy counterconvention countercountermeasure countercoup countercoups countercriticism countercry countercultural counterculture countercultures counterculturist counterculturists countercurrent countercurrently countercurrents countercyclical counterdemand counterdemonstrate counterdemonstration counterdemonstrations counterdemonstrator counterdemonstrators counterdeployment countered countereducational countereffort counterespionage counterevidence counterexample counterexamples counterfactual counterfeit counterfeited counterfeiter counterfeiters counterfeiting counterfeits counterfire counterfoil counterfoils counterforce counterforces counterglow counterglows countergovernment counterhypothesis counterimage counterincentive counterinflation counterinflationary counterinfluence countering counterinstance counterinstitution counterinsurgencies counterinsurgency counterinsurgent counterinsurgents counterintelligence counterinterpretation counterintuitive counterirritant counterirritants counterirritation counterman countermand countermanded countermanding countermands countermarch countermarched countermarches countermarching countermeasure countermeasures countermemo countermen countermine countermined countermines countermining countermobilization countermove countermoved countermovement countermoves countermoving countermyth counteroffensive counteroffensives counteroffer counteroffers counterorder counterpane counterpanes counterpart counterparts counterperson counterpersons counterpetition counterpicket counterplan counterplans counterplay counterplayer counterplays counterplea counterpleas counterplot counterplots counterplotted counterplotting counterploy counterpoint counterpointed counterpointing counterpoints counterpoise counterpoised counterpoises counterpoising counterpose counterposed counterposes counterposing counterpower counterpressure counterproductive counterproductively counterprogramming counterprogrammings counterproject counterproliferation counterpropaganda counterproposal counterproposals counterprotest counterpunch counterpunched counterpuncher counterpunchers counterpunches counterpunching counterquestion counterraid counterrally counterreaction counterreform counterreformation counterreformations counterreformer counterresponse counterretaliation counterrevolution counterrevolutionaries counterrevolutionary counterrevolutionist counterrevolutionists counterrevolutions counters counterscientific countershading countershadings countershaft countershafts countershot countersign countersignature countersignatures countersigned countersigning countersigns countersink countersinking countersinks countersniper counterspell counterspies counterspy counterstain counterstained counterstaining counterstains counterstate counterstatement counterstep counterstrategist counterstrategy counterstream counterstrike counterstroke counterstrokes counterstyle countersue countersued countersues countersuggestion countersuing countersuit countersuits countersunk countersurveillance countertactics countertendency countertenor countertenors counterterror counterterrorism counterterrorist counterterrorists counterterrors counterthreat counterthrust countertop countertops countertrade countertrader countertraders countertrades countertradition countertransference countertransferences countertrend countervail countervailed countervailing countervails counterviolence counterweigh counterweighed counterweighing counterweighs counterweight counterweighted counterweights counterwoman counterwomen counterworld countess countesses counties counting countinghouse countless countlessly countries countrified country countryman countrymen countryseat countryseats countryside countrysides countrywide countrywoman countrywomen counts county countywide coup coupe coupes couple coupled coupler couplers couples couplet couplets coupling couplings coupon couponing couponings coupons coups coupé coupés courage courageous courageously courageousness courant courante courantes courgette courgettes courier couriers courlan courlans course coursed courser coursers courses courseware coursework coursing coursings court courted courteous courteously courteousness courtesan courtesans courtesies courtesy courthouse courthouses courtier courtiers courting courtlier courtliest courtliness courtly courtroom courtrooms courts courtship courtships courtside courtyard courtyards couscous cousin cousinhood cousinly cousins cousinship couth coutts couture couturier couturiers couturière couturières couvade couvades covalence covalency covalent covalently covariance covariant cove coved covellite covellites coven covenant covenantal covenantally covenanted covenantee covenantees covenanter covenanters covenanting covenantor covenantors covenants covens coventry cover coverable coverage coverall coveralls coverdale covered coverer coverers covering coverings coverless coverlet coverlets covers covert covertly covertness coverts coverture covertures coves covet covetable coveted coveter coveters coveting covetingly covetous covetously covetousness covets covey coveys coving cow coward cowardice cowardliness cowardly cowards cowbane cowbanes cowbell cowbells cowberries cowberry cowbird cowbirds cowboy cowboys cowcatcher cowcatchers cowed cowedly cower cowered cowering cowers cowfish cowfishes cowgirl cowgirls cowhand cowhands cowherb cowherbs cowherd cowherds cowhide cowhided cowhides cowhiding cowing cowinner cowinners cowl cowled cowlick cowlicks cowling cowlings cowls cowman cowmen coworker coworkers cowpea cowpeas cowper cowpoke cowpokes cowponies cowpony cowpox cowpoxes cowpuncher cowpunchers cowrie cowries cowrite cowriter cowriters cowrites cowriting cowritten cowrote cowry cows cowshed cowsheds cowslip cowslips cox coxa coxae coxal coxalgia coxalgias coxalgic coxcomb coxcombries coxcombry coxcombs coxed coxes coxing coxitis coxitises coxsackievirus coxsackieviruses coxswain coxswained coxswaining coxswains coy coydog coydogs coyer coyest coyly coyness coyote coyotes coyotillo coyotillos coypu coypus cozen cozenage cozenages cozened cozener cozeners cozening cozens cozied cozier cozies coziest cozily coziness cozumel cozy cozying crab crabapple crabapples crabbe crabbed crabbedly crabbedness crabber crabbers crabbier crabbiest crabbily crabbiness crabbing crabby crabgrass crabmeat crabmeats crabs crabstick crabsticks crabwise crack crackbrain crackbrained crackbrains crackdown crackdowns cracked cracker crackerjack crackerjacks crackers cracking crackings crackle crackled crackles crackleware cracklewares cracklier crackliest crackling cracklings crackly cracknel cracknels crackpot crackpots cracks cracksman cracksmen crackup crackups cracow cradle cradleboard cradleboards cradled cradler cradlers cradles cradlesong cradlesongs cradling craft crafted crafter crafters craftier craftiest craftily craftiness crafting crafts craftsman craftsmanlike craftsmanly craftsmanship craftsmen craftspeople craftsperson craftspersons craftswoman craftswomen craftwork craftworker craftworkers craftworks crafty crag cragged craggier craggiest craggily cragginess craggy crags craig crake crakes cram crambe crambes crambo cramboes crammed crammer crammers cramming cramp cramped crampfish crampfishes cramping crampon crampons cramps crams cranberries cranberry crane craned cranes cranesbill cranesbills crania cranial cranially craniate craniates craniectomies craniectomy craning craniocerebral craniofacial craniological craniologically craniologist craniologists craniology craniometer craniometers craniometric craniometrical craniometry craniosacral craniotomies craniotomy cranium craniums crank crankcase crankcases cranked crankier crankiest crankily crankiness cranking crankpin cranks crankshaft crankshafts cranky cranmer crannied crannies cranny crap crape craped crapehanger crapehangers crapes craping crapped crapper crappers crappie crappier crappies crappiest crapping crappy craps crapshoot crapshooter crapshooters crapshoots crapulence crapulent crapulous crapulously crash crashed crasher crashers crashes crashing crashworthiness crashworthy crass crasser crassest crassitude crassly crassness crate crated crater cratered cratering craterlet craterlets craters crates crating cravat cravats crave craved craven cravenly cravenness cravens craver cravers craves craving cravingly cravings craw crawdad crawdads crawfish crawfished crawfishes crawfishing crawl crawled crawler crawlers crawlier crawliest crawling crawlingly crawls crawlspace crawlspaces crawlway crawlways crawly craws crayfish crayfishes crayon crayoned crayoning crayonist crayonists crayons craze crazed crazes crazier crazies craziest crazily craziness crazinesses crazing crazy crazyweed crazyweeds creak creaked creakier creakiest creakily creakiness creaking creakingly creaks creaky cream creamcups creamed creamer creameries creamers creamery creamier creamiest creamily creaminess creaming creampuff creampuffs creams creamy crease creased creaseless creaseproof creaser creasers creases creasing creasy create created creates creatine creatines creating creatinine creatinines creation creational creationism creationist creationists creations creative creatively creativeness creativity creator creators creatural creature creatureliness creaturely creatures credence credential credentialed credentialing credentialism credentialisms credentials credenza credenzas credibility credible credibleness credibly credit creditability creditable creditableness creditably credited crediting creditor creditors credits creditworthiness creditworthy credo credos credulity credulous credulously credulousness creed creedal creeds creek creeks creel creels creep creeper creepers creepier creepiest creepily creepiness creeping creeps creepy cremains cremate cremated cremates cremating cremation cremations cremator crematoria crematories crematorium crematoriums cremators crematory creme cremes cremona crenate crenately crenation crenations crenature crenatures crenel crenelated crenelation crenellate crenellated crenellates crenellating crenellation crenellations crenellé crenels crenshaw crenshaws crenulate crenulation creodont creodonts creole creoles creolization creolize creolized creolizes creolizing creon creosol creosols creosote creosoted creosotes creosoting crepe crepehanger crepehangers crepes crepitant crepitate crepitated crepitates crepitating crepitation crepitations crept crepuscular crepuscule crepuscules crescendi crescendo crescendoed crescendoes crescendoing crescendos crescent crescentic crescents cresol cresols cress cresset cressets cressida crest cresta crested crestfallen crestfallenly crestfallenness cresting crestings crests cresyl cresylic cresyls cretaceous cretaceously cretan cretans crete cretic cretics cretin cretinism cretinize cretinized cretinizes cretinizing cretinoid cretinous cretins cretonne cretonnes crevalle crevalles crevasse crevassed crevasses crevassing crevice creviced crevices crew crewcut crewed crewel crewels crewelwork crewelworks crewing crewman crewmate crewmates crewmember crewmembers crewmen crews creüsa cri crib cribbage cribbed cribber cribbers cribbing cribriform cribs cricetid cricetids crick cricked cricket cricketed cricketer cricketers cricketing crickets crickety cricking cricks cricoid cricoids cried crier criers cries crime crimea crimean crimeless crimelessness crimes criminal criminalities criminality criminalization criminalize criminalized criminalizes criminalizing criminally criminals criminate criminated criminates criminating crimination criminative criminator criminators criminatory criminogenic criminological criminologically criminologist criminologists criminology crimp crimped crimper crimpers crimpier crimpiest crimpiness crimping crimps crimpy crimson crimsoned crimsoning crimsons cringe cringed cringes cringing cringle cringles crinkle crinkled crinkleroot crinkleroots crinkles crinkling crinkly crinoid crinoids crinoline crinolined crinolines crinum crinums criollo criollos criosphinx criosphinxes cripple crippled crippler cripplers cripples crippling cripps cris crises crisis crisp crispate crispation crispations crisped crisper crispers crispest crispier crispiest crispin crispiness crisping crisply crispness crisps crispy crissa crissal crisscross crisscrossed crisscrosses crisscrossing crissum crista cristae cristate criteria criterial criterion criterions critic critical criticality critically criticalness criticaster criticasters criticism criticisms criticizable criticize criticized criticizer criticizers criticizes criticizing critics critique critiqued critiques critiquing critter critters croak croaked croaker croakers croakily croaking croaks croaky croat croatia croatian croatians croats crocein croceins crochet crocheted crocheting crochets crocidolite crocidolites crock crocked crockery crocket crockets crocking crocks crocodile crocodiles crocodilian crocodilians crocoite crocoites crocus crocuses croesus crofter crofters crohn croissant croissants cromlech cromlechs cromwell cromwellian crone crones cronies cronin cronus crony cronyism crook crookbacked crooked crookedly crookedness crookeries crookery crooking crookneck crooknecks crooks croon crooned crooner crooners crooning croons crop cropland croplands cropped cropper croppers cropping crops croquet croqueted croqueting croquets croquette croquettes croquignole croquignoles crosier crosiers cross crossbar crossbars crossbeam crossbeams crossbill crossbills crossbones crossbow crossbowman crossbows crossbred crossbreed crossbreeding crossbreeds crosscheck crosschecked crosschecking crosschecks crosscourt crosscurrent crosscurrents crosscut crosscuts crosscutting crosscuttings crosse crossed crosser crossers crosses crossfire crosshair crosshairs crosshatch crosshatched crosshatches crosshatching crosshead crossheads crossing crossings crossly crossness crossopterygian crossopterygians crossover crossovers crosspatch crosspatches crosspiece crosspieces crossroad crossroads crossruff crossruffed crossruffing crossruffs crosstalk crosstalks crosstie crossties crosstree crosstrees crosswalk crosswalks crossway crossways crosswayss crosswind crosswinds crosswise crossword crosswords crotch crotched crotches crotchet crotchetiness crotchets crotchety croton crotons crottin crottins crouch crouched crouches crouching croup croupier croupiers croupous croupy crouse croustade croustades crouton croutons crow crowbar crowbarred crowbarring crowbars crowberries crowberry crowd crowded crowder crowders crowding crowds crowed crowfoot crowfoots crowing crown crowned crowning crowns crows croze crozes cru crucial crucially cruciate cruciately crucible crucibles crucifer cruciferous crucifers crucified crucifier crucifiers crucifies crucifix crucifixes crucifixion crucifixions cruciform cruciformly crucify crucifying crud cruddier cruddiest cruddiness cruddy crude crudely crudeness cruder crudest crudities crudity crudités cruel crueler cruelest cruelly cruelties cruelty cruet cruets cruise cruised cruiser cruisers cruiserweight cruiserweights cruises cruising cruller crullers crumb crumbed crumbing crumble crumbled crumbles crumblier crumbliest crumbliness crumbling crumbly crumbs crummier crummiest crummy crump crumped crumpet crumpets crumping crumple crumpled crumples crumpling crumply crumps crunch crunchable crunched crunches crunchier crunchiest crunchiness crunching crunchy crupper cruppers crura crural crus crusade crusaded crusader crusaders crusades crusading crusado crusadoes cruse cruses crush crushable crushed crusher crushers crushes crushing crushingly crushproof crusoe crust crustacean crustaceans crustaceous crustal crusted crustier crustiest crustily crustiness crusting crustless crustose crusts crusty crutch crutched crutches crutching crux cruxes cruz cruzeiro cruzeiros cry crybabies crybaby crying crymotherapies crymotherapy cryobank cryobanks cryobiological cryobiologically cryobiologist cryobiologists cryobiology cryogen cryogenic cryogenically cryogenics cryogeny cryolite cryolites cryometer cryometers cryonic cryonics cryophilic cryopreservation cryopreserve cryopreserved cryopreserves cryopreserving cryoprobe cryoprobes cryoprotectant cryoprotectants cryoprotective cryoscope cryoscopes cryoscopic cryoscopies cryoscopy cryostat cryostatic cryostats cryosurgeon cryosurgeons cryosurgery cryosurgical cryotherapies cryotherapy crypt cryptanalysis cryptanalyst cryptanalysts cryptanalytic cryptanalyze cryptanalyzed cryptanalyzes cryptanalyzing cryptesthesia cryptic cryptically crypticness crypto cryptoclastic cryptococcal cryptococcosis cryptococcus cryptocrystalline cryptogam cryptogamic cryptogamous cryptogams cryptogenic cryptogram cryptogrammic cryptograms cryptograph cryptographed cryptographer cryptographers cryptographic cryptographically cryptographing cryptographs cryptography cryptologic cryptological cryptologist cryptologists cryptology cryptomeria cryptomerias cryptorchid cryptorchism cryptos cryptosporidiosis cryptozoite cryptozoites cryptozoological cryptozoologist cryptozoologists cryptozoology crypts crystal crystalliferous crystalline crystallinity crystallite crystallites crystallitic crystallizable crystallization crystallize crystallized crystallizer crystallizers crystallizes crystallizing crystallographer crystallographers crystallographic crystallographical crystallographically crystallography crystalloid crystalloidal crystalloids crystals crécy crèche crèches crème crèmes crêpe crêpes ctenidia ctenidium ctenoid ctenophoran ctenophore ctenophores cuadrilla cuadrillas cuatro cuatros cub cuba cubage cubages cuban cubans cubature cubatures cubbies cubby cubbyhole cubbyholes cube cubeb cubebs cubed cuber cubers cubes cubic cubical cubically cubicalness cubicle cubicles cubicly cubics cubiform cubing cubism cubist cubistic cubistically cubists cubit cubits cuboid cuboidal cuboids cubs cubé cuchifrito cuchifritos cuchulain cuckold cuckolded cuckolding cuckoldries cuckoldry cuckolds cuckoo cuckooed cuckooflower cuckooflowers cuckooing cuckoopint cuckoopints cuckoos cucullate cucullately cucumber cucumbers cucurbit cucurbits cud cudbear cudbears cuddies cuddle cuddled cuddles cuddlesome cuddlier cuddliest cuddling cuddly cuddy cudgel cudgeled cudgeling cudgels cudweed cudweeds cue cued cueing cuernavaca cues cuesta cuestas cuff cuffed cuffing cufflink cufflinks cuffs cui cuing cuirass cuirassed cuirasses cuirassier cuirassiers cuirassing cuisinart cuisine cuisse cuisses cul culch culches culet culets culex culiacán culices culinary cull culled culler cullers cullet cullets cullies culling cullis cullises culloden culls cully culm culminant culminate culminated culminates culminating culmination culminations culms culotte culottes culpa culpability culpable culpably culprit culprits cult cultic cultigen cultigens cultish cultism cultist cultists cultivability cultivable cultivar cultivatable cultivate cultivated cultivates cultivating cultivation cultivations cultivator cultivators cultrate cults cultural culturally culturati culture cultured cultures culturing cultus cultuses culver culverin culverins culvers culvert culverts cum cumaean cumber cumbered cumberer cumberers cumbering cumberland cumbers cumbersome cumbersomely cumbria cumbrian cumbrians cumbrous cumbrously cumbrousness cumin cummerbund cummerbunds cumshaw cumshaws cumulate cumulated cumulates cumulating cumulation cumulations cumulative cumulatively cumulativeness cumuli cumuliform cumulonimbi cumulonimbus cumulonimbuses cumulous cumulus cunard cunctation cunctations cunctative cunctator cunctators cuneal cuneate cuneately cuneiform cunha cunner cunners cunnilingual cunnilingus cunnilinguses cunning cunningly cunningness cunnings cunt cunts cup cupbearer cupbearers cupboard cupboards cupcake cupcakes cupel cupeled cupeling cupellation cupellations cupeller cupellers cupels cupflower cupflowers cupful cupfuls cupid cupidity cupids cupola cupolas cupped cuppier cuppiest cupping cuppings cuppy cupreous cupric cupriferous cuprite cuprites cupronickel cupronickels cuprous cups cupulate cupule cupules cur curability curable curableness curably curacies curacy curare curarization curarize curarized curarizes curarizing curassow curassows curate curates curative curatively curativeness curatives curator curatorial curators curatorship curaçao curaçaos curb curbed curbing curbs curbside curbsides curbstone curbstones curculio curculios curcuma curcumas curd curded curding curdle curdled curdles curdling curds curdy cure cured cureless curer curers cures curettage curette curettement curettements curettes curfew curfews curia curiae curial curie curies curing curio curios curiosa curiosities curiosity curious curiously curiousness curium curl curled curler curlers curlew curlews curlicue curlicued curlicues curlier curliest curlily curliness curling curlings curls curly curmudgeon curmudgeonly curmudgeonry curmudgeons currant currants currencies currency current currently currentness currents curricle curricles curricula curricular curriculum curriculums curried currier currieries curriers curriery curries currish currishly curry currycomb currycombed currycombing currycombs currying curs curse cursed cursedly cursedness curser cursers curses cursing cursive cursively cursiveness cursives cursor cursorial cursorily cursoriness cursors cursory curt curtail curtailed curtailer curtailers curtailing curtailment curtailments curtails curtain curtained curtaining curtains curtate curter curtesies curtest curtesy curtilage curtilages curtly curtness curtsey curtseyed curtseying curtseys curtsied curtsies curtsy curtsying curule curvaceous curvaceously curvaceousness curvature curvatures curve curveball curveballs curved curvedness curves curvet curvets curvetted curvetting curvilinear curvilinearity curvilinearly curving curvy curé curés cuscus cuscuses cusec cusecs cushaw cushaws cushier cushiest cushily cushiness cushion cushioned cushioning cushions cushiony cushitic cushy cusk cusp cuspate cusped cuspid cuspidate cuspidation cuspidations cuspidor cuspidors cuspids cusps cuss cussed cussedly cussedness cusses cussing cussword cusswords custard custards custardy custodial custodian custodians custodianship custodies custody custom customable customarily customariness customary customer customers customhouse customhouses customizable customization customizations customize customized customizer customizers customizes customizing customs cut cutaneous cutaneously cutaway cutaways cutback cutbacks cutch cutches cute cutely cuteness cuter cutes cutesier cutesiest cutesiness cutest cutesy cutgrass cutgrasses cuticle cuticles cuticular cutie cuties cutin cutinization cutinize cutinized cutinizes cutinizing cutins cutis cutlass cutlasses cutler cutlers cutlery cutlet cutlets cutoff cutoffs cutout cutouts cutover cutpurse cutpurses cuts cuttable cutter cutters cutthroat cutthroats cutting cuttingly cuttings cuttingss cuttlebone cuttlebones cuttlefish cuttlefishes cutup cutups cutwater cutwaters cutwork cutworks cutworm cutworms cuvette cuvettes cuvier cyan cyanamide cyanamides cyanate cyanates cyanic cyanide cyanided cyanides cyaniding cyanine cyanines cyanoacrylate cyanoacrylates cyanobacterium cyanobacteriums cyanocobalamin cyanocobalamins cyanogen cyanogenesis cyanogenetic cyanogens cyanohydrin cyanohydrins cyanosed cyanoses cyanosis cyanotic cyanotype cyanotypes cyathium cyathiums cybele cyberconference cybernate cybernated cybernates cybernating cybernation cybernetic cybernetically cybernetician cyberneticians cyberneticist cyberneticists cybernetics cyberspace cyborg cyborgs cycad cycads cyclades cycladic cyclamate cyclamates cyclamen cyclamens cyclase cyclases cycle cycled cycler cyclers cycles cyclic cyclical cyclicality cyclically cycling cyclist cyclists cyclization cyclizations cycloalkane cycloalkanes cyclohexane cyclohexanes cycloheximide cycloheximides cycloid cycloidal cycloids cyclometer cyclometers cyclometric cyclometry cyclone cyclones cyclonic cyclonical cyclooxygenase cycloparaffin cycloparaffins cyclopean cyclopedia cyclopedias cyclopedic cyclopedist cyclopedists cyclopentane cyclopentanes cyclopes cyclophosphamide cyclophosphamides cycloplegia cycloplegias cyclopropane cyclopropanes cyclops cyclopses cyclorama cycloramas cycloramic cycloserine cycloserines cycloses cyclosis cyclosporine cyclosporines cyclostomate cyclostomatous cyclostome cyclostomes cyclostyle cyclostyled cyclostyles cyclostyling cyclothyme cyclothymes cyclothymia cyclothymias cyclothymic cyclotron cyclotrons cygnet cygnets cygnus cylinder cylinders cylindric cylindrical cylindricality cylindrically cylindroid cylindroids cyma cymas cymatia cymatium cymbal cymbaleer cymbaleers cymbalist cymbalists cymbals cymbeline cymbidium cymbidiums cyme cymene cymenes cymes cymiferous cymling cymlings cymogene cymogenes cymoid cymophane cymophanes cymose cymosely cymric cymry cynic cynical cynically cynicalness cynicism cynicisms cynics cynoscephalae cynosural cynosure cynosures cynthia cypress cypresses cyprian cyprians cyprinid cyprinids cyprinodont cyprinodonts cyprinoid cyprinoids cypriot cypriots cypripedium cypripediums cyproheptadine cyproheptadines cyproterone cyproterones cyprus cypsela cypselae cyrenaic cyrenaica cyrenaics cyrene cyrillic cyst cystectomies cystectomy cysteine cysteines cystic cysticerci cysticercoid cysticercoids cysticercosis cysticercus cystine cystines cystitis cystocele cystoceles cystoid cystoids cystolith cystoliths cystoscope cystoscopes cystoscopic cystoscopy cystostomies cystostomy cysts cythera cytherean cytidine cytidines cytochemical cytochemistry cytochrome cytochromes cytogenesis cytogenetic cytogenetical cytogenetically cytogeneticist cytogeneticists cytogenetics cytogeny cytokinesis cytokinetic cytokinin cytokinins cytologic cytological cytologist cytologists cytology cytolyses cytolysin cytolysins cytolysis cytolytic cytomegalic cytomegalovirus cytomegaloviruses cytomembrane cytomembranes cytopathic cytopathogenic cytopathogenicity cytophilic cytophotometer cytophotometers cytophotometric cytophotometrically cytophotometry cytoplasm cytoplasmic cytoplasmically cytoplast cytoplastic cytoplasts cytosine cytosines cytoskeleton cytoskeletons cytosol cytosols cytostasis cytostatic cytostatically cytostatics cytotaxonomic cytotaxonomies cytotaxonomist cytotaxonomists cytotaxonomy cytotechnologist cytotechnologists cytotechnology cytotoxic cytotoxicity cytotoxin cytotoxins czar czardas czardom czarevitch czarevitches czarevna czarevnas czarina czarinas czarism czarisms czarist czarists czaritza czaritzas czars czech czechoslovak czechoslovakia czechoslovakian czechoslovakians czechoslovaks czechs cádiz cárdenas céleste célestes célèbre célèbres cévennes cézanne cézannesque cèpe cèpes cíbola córdoba côte côtes d d'affaires d'antibes d'aosta d'art d'azur d'elegance d'esprit d'estime d'hôte d'hôtel d'oc d'oeil d'oeuvre d'oeuvres d'oyly d'oïl d'état d'être d'œil d'œuvre d'œuvres da dab dabbed dabber dabbers dabbing dabble dabbled dabbler dabblers dabbles dabbling dabchick dabchicks dabs dacca dace daces dacha dachas dachau dachshund dachshunds dacoit dacoits dacoity dacquoise dacquoises dacron dactinomycin dactinomycins dactyl dactylic dactylically dactylogram dactylograms dactylographic dactylography dactylology dactyls dad dada dadaism dadaist dadaistic dadaists daddies daddy daddyish dado dadoed dadoes dadoing dados dadra dads daedal daedalian daedalus daemon daemonic daemons daffier daffiest daffily daffiness daffodil daffodils daffy daft dafter daftest daftly daftness dag dagan dagestan dagger daggers dagon dags daguerre daguerreotype daguerreotyped daguerreotyper daguerreotypers daguerreotypes daguerreotyping daguerreotypy dagwood dagwoods dahabeah dahabeahs dahl dahlia dahlias dahomey dahoon dahoons daikon dailies dailiness daily daimio daimios daimon daimons daintier dainties daintiest daintily daintiness dainty daiquiri daiquiris dairies dairy dairyer dairyers dairying dairymaid dairymaids dairyman dairymen dairywoman dairywomen dais daises daisies daisy dakar dakota dakotan dakotans dakotas dalai dalapon dalapons dalasi dale dalek daleks dales daleth dalhousie dallas dalles dalliance dalliances dallied dallier dalliers dallies dally dallying dallyingly dalmatia dalmatian dalmatians dalmatic dalmatics dalrymple dalton daltonian daltonic daltonism daltons dam damage damageability damageable damaged damager damagers damages damaging damagingly daman damascene damascened damascener damasceners damascenes damascening damascus damask damasked damasking damasks dame dames daminozide daminozides dammar dammars dammed dammer dammers damming dammit damn damnable damnableness damnably damnation damnatory damnder damndest damned damneder damnedest damnification damnified damnifies damnify damnifying damning damningly damns damocles damon damp damped dampen dampened dampener dampeners dampening dampens damper dampers dampest damping dampings dampish damply dampness damps dams damsel damselfish damselfishes damselflies damselfly damsels damson damsons dan dana danaides danaë dance danceability danceable danced dancegoer dancegoers dancegoing dancer dancerly dancers dances dancewear dancewears dancier danciest dancing dancingly dancy dandelion dandelions dander dandiacal dandier dandies dandiest dandification dandified dandifies dandify dandifying dandily dandle dandled dandles dandling dandruff dandruffy dandy dandyish dandyishly dandyism dandyisms dane danegeld danegelds danelaw danelaws danes dang danged danger dangerous dangerously dangerousness dangers dangle dangleberries dangleberry dangled dangler danglers dangles dangling dangly dangs daniel danielle danio danios danish danishes danite danites dank danker dankest dankly dankness dans danseur danseurs danseuse danseuses dante dantean danteans dantesque danton danube danubian danville danzig dap daphne daphnes daphnia daphnis dapped dapper dapperly dapperness dapping dapple dappled dapples dappling daps dapsone dapsones dardanelles dardanus dare dared daredevil daredevilry daredevils daredeviltry daren daren't darer darers dares daresay daring daringly daringness dariole darioles darius darién darjeeling dark darken darkened darkener darkeners darkening darkens darker darkest darkish darkle darkled darkles darkling darklings darkly darkness darkroom darkrooms darks darksome darlene darling darlingly darlingness darlings darn darnation darned darnedest darnedests darnel darnels darner darners darning darnley darns daro dart dartboard dartboards darted darter darters darting dartmouth darts darvon darwin darwinian darwinians darwinism darwinist darwinistic darwinists dash dashboard dashboards dashed dasheen dasheens dasher dashers dashes dashi dashiki dashikis dashing dashingly dashis dashpot dashpots dassie dassies dastard dastardliness dastardly dastards dasyure dasyures data databanks database databased databases databasing datable datagram datamation date dateable dated datedly datedness dateless dateline datelined datelines datelining dater daters dates dating dative datively datives datum datums datura daturas daub daubed dauber daubers daubery daubing daubs daugavpils daughter daughterless daughterly daughters daunt daunted daunter daunters daunting dauntingly dauntless dauntlessly dauntlessness daunts dauphin dauphine dauphines dauphins dauphiné dave davenant davenport davenports david davit davits davos davy daw dawdle dawdled dawdler dawdlers dawdles dawdling dawdlingly dawn dawned dawning dawns daws day dayak dayaks daybed daybeds daybook daybooks daybreak daybreaks daycare daydream daydreamed daydreamer daydreamers daydreaming daydreams daydreamt dayflies dayflower dayflowers dayfly dayhop dayhops daylight daylights daylilies daylily daylong daypack daypacks dayroom dayrooms days dayside daysides dayspring daystar daystars daytime daytimes dayton daytona daywear daze dazed dazedly dazedness dazes dazing dazzle dazzled dazzler dazzlers dazzles dazzling dazzlingly de deaccession deaccessioned deaccessioning deaccessions deacidification deacidified deacidifies deacidify deacidifying deacon deaconess deaconesses deaconries deaconry deacons deactivate deactivated deactivates deactivating deactivation deactivations deactivator deactivators dead deadbeat deadbeats deadbolt deadbolts deaden deadened deadener deadeners deadening deadeningly deadenings deadens deader deadest deadeye deadeyes deadfall deadfalls deadhead deadheaded deadheading deadheads deadlier deadliest deadlight deadlights deadline deadlined deadlines deadliness deadlining deadlock deadlocked deadlocking deadlocks deadly deadness deadpan deadpanned deadpanner deadpanners deadpanning deadpans deadweight deadwood deaerate deaerated deaerates deaerating deaeration deaerator deaerators deaf deafen deafened deafening deafeningly deafens deafer deafest deafly deafness deal dealate dealated dealateds dealates dealation dealcoholization dealcoholize dealcoholized dealcoholizes dealcoholizing dealer dealers dealership dealerships dealfish dealfishes dealignment dealignments dealing dealings deallocate deallocated deallocates deallocating deallocation deallocations deallocator dealmaker dealmakers dealmaking deals dealt deaminase deaminases deaminate deaminated deaminates deaminating deamination deaminization deaminize deaminized deaminizes deaminizing dean deaneries deanery deans deanship dear dearborn dearer dearest dearly dearness dears dearth death deathbed deathbeds deathblow deathblows deathless deathlessly deathlessness deathlike deathly deaths deathtrap deathtraps deathward deathwatch deathwatches deattribution deattributions deauville deb debacle debacles debar debark debarkation debarkations debarked debarking debarks debarment debarments debarred debarring debars debase debased debasement debasements debaser debasers debases debasing debatable debatably debate debated debatement debater debaters debates debating debauch debauched debauchedly debauchee debauchees debaucher debaucheries debauchers debauchery debauches debauching debenture debentures debilitate debilitated debilitates debilitating debilitation debilitations debilitative debilities debility debit debited debiting debits debonair debonairly debonairness debone deboned deboner deboners debones deboning deborah debouch debouched debouches debouching debouchment debouchments debouchure debouchures debra debrief debriefed debriefing debriefings debriefs debris debt debtless debtor debtors debts debug debugged debugger debuggers debugging debugs debunk debunked debunker debunkers debunking debunks debussy debut debutant debutante debutantes debutants debuted debuting debuts decaampere decaamperes decabecquerel decabecquerels decacandela decacandelas decacoulomb decacoulombs decade decadelong decadence decadencies decadency decadent decadently decadents decades decaf decafarad decafarads decaffeinate decaffeinated decaffeinates decaffeinating decaffeination decagon decagonal decagonally decagons decagram decagrams decagynous decahedra decahedral decahedron decahedrons decahenries decahenry decahenrys decahertz decajoule decajoules decakelvin decakelvins decal decalcification decalcified decalcifier decalcifiers decalcifies decalcify decalcifying decalcomania decalescence decalescences decalescent decaliter decaliters decalogue decalogues decals decalumen decalumens decalux decameron decameter decameters decametric decamole decamoles decamp decamped decamping decampment decamps decandrous decane decanes decanewton decanewtons decant decantation decanted decanter decanters decanting decants decaohm decaohms decapascal decapascals decapitate decapitated decapitates decapitating decapitation decapitations decapitator decapitators decapod decapodal decapodan decapodous decapods decapolis decaradian decaradians decarbonate decarbonated decarbonates decarbonating decarbonation decarbonization decarbonize decarbonized decarbonizer decarbonizers decarbonizes decarbonizing decarboxylase decarboxylases decarboxylation decarboxylations decarburization decarburize decarburized decarburizes decarburizing decare decares decasecond decaseconds decasiemens decasievert decasieverts decasteradian decasteradians decastyle decastyles decasualization decasyllabic decasyllabics decasyllable decasyllables decatesla decateslas decathlete decathletes decathlon decathlons decatur decavolt decavolts decawatt decawatts decaweber decawebers decay decayed decayer decayers decaying decays decca deccan decease deceased deceases deceasing decedent decedents deceit deceitful deceitfully deceitfulness deceits deceivable deceive deceived deceiver deceivers deceives deceiving deceivingly decelerate decelerated decelerates decelerating deceleration decelerations decelerator decelerators december decembers decembrist decembrists decemvir decemviral decemvirate decemvirates decemviri decemvirs decencies decency decennaries decennary decennia decennial decennially decennials decennium decenniums decent decently decentness decentralization decentralizationist decentralizationists decentralizations decentralize decentralized decentralizes decentralizing deception deceptional deceptions deceptive deceptively deceptiveness decerebrate decerebrated decerebrates decerebrating decerebration decertification decertified decertifies decertify decertifying dechlorinate dechlorinated dechlorinates dechlorinating dechlorination deciampere deciamperes deciare deciares decibecquerel decibecquerels decibel decibels decicandela decicandelas decicoulomb decicoulombs decidability decidable decide decided decidedly decidedness decider deciders decides deciding decidua deciduae decidual deciduas deciduate deciduous deciduously deciduousness decifarad decifarads decigram decigrams decihenries decihenry decihenrys decihertz decijoule decijoules decikelvin decikelvins decile deciles deciliter deciliters decillion decillions decillionth decillionths decilumen decilumens decilux decimal decimalization decimalize decimalized decimalizes decimalizing decimally decimals decimate decimated decimates decimating decimation decimations decimator decimators decimeter decimeters decimole decimoles decinewton decinewtons deciohm deciohms decipascal decipascals decipher decipherability decipherable deciphered decipherer decipherers deciphering decipherment deciphers deciradian deciradians decisecond deciseconds decisiemens decisievert decisieverts decision decisional decisioned decisioning decisions decisive decisively decisiveness decisteradian decisteradians decitesla deciteslas decivolt decivolts deciwatt deciwatts deciweber deciwebers deck decked decker deckers deckhand deckhands deckhouse deckhouses decking deckle deckled deckles deckling decks declaim declaimed declaimer declaimers declaiming declaims declamation declamations declamatory declarable declarant declarants declaration declarations declarative declaratively declaratives declaratory declare declared declarer declarers declares declaring declass declassed declasses declassifiable declassification declassifications declassified declassifies declassify declassifying declassing declaw declawed declawing declaws declension declensional declensions declinable declination declinational declinations decline declined decliner decliners declines declining declivities declivitous declivity deco decoct decocted decocting decoction decoctions decocts decode decoded decoder decoders decodes decoding decodings decollate decollated decollates decollating decollation decollations decollator decollators decollectivization decollectivize decollectivized decollectivizes decollectivizing decolonization decolonize decolonized decolonizes decolonizing decolorant decolorants decolorization decolorize decolorized decolorizer decolorizers decolorizes decolorizing decommission decommissioned decommissioning decommissions decompensate decompensated decompensates decompensating decompensation decompile decompiled decompiler decompilers decompiles decompiling decomposability decomposable decompose decomposed decomposer decomposers decomposes decomposing decomposition decompositional decompositions decompound decompounded decompounding decompounds decompress decompressed decompresses decompressing decompression decompressions deconcentrate deconcentrated deconcentrates deconcentrating deconcentration decondition deconditioned deconditioning deconditions decongest decongestant decongestants decongested decongesting decongestion decongestive decongests deconsecrate deconsecrated deconsecrates deconsecrating deconsecration deconsecrations deconstruct deconstructed deconstructing deconstruction deconstructionism deconstructionist deconstructionists deconstructs decontaminant decontaminate decontaminated decontaminates decontaminating decontamination decontaminations decontaminator decontaminators decontextualize decontextualized decontextualizes decontextualizing decontrol decontrolled decontrolling decontrols decor decorate decorated decorates decorating decoration decorations decorative decoratively decorativeness decorator decorators decorous decorously decorousness decors decorticate decorticated decorticates decorticating decortication decorticator decorticators decorum decos decoupage decoupages decouple decoupled decoupler decouplers decouples decoupling decoy decoyed decoyer decoyers decoying decoys decrease decreased decreases decreasing decreasingly decree decreeable decreed decreeing decreer decreers decrees decrement decremental decremented decrementing decrements decreolization decreolizations decrepit decrepitate decrepitated decrepitates decrepitating decrepitation decrepitly decrepitude decrescendo decrescendos decrescent decretal decretals decretive decretory decried decrier decriers decries decriminalization decriminalize decriminalized decriminalizes decriminalizing decry decrying decrypt decrypted decrypting decryption decrypts decumbence decumbency decumbent decuple decurrent decurrently decussate decussated decussately decussates decussating decussation decussations dedans dedicate dedicated dedicatedly dedicatee dedicatees dedicates dedicating dedication dedications dedicative dedicator dedicators dedicatory dedifferentiate dedifferentiated dedifferentiates dedifferentiating dedifferentiation deduce deduced deduces deducible deducing deduct deducted deductibility deductible deductibles deducting deduction deductions deductive deductively deducts deed deeded deeding deedless deeds deejay deejays deem deemed deeming deems deep deepen deepened deepening deepens deeper deepest deepfreeze deeply deepness deeps deepwater deer deerflies deerfly deerhound deerhounds deerskin deerskins deerstalker deerstalkers deeryard deeryards deescalate deescalated deescalates deescalating deet deets deface defaceable defaced defacement defacements defacer defacers defaces defacing defalcate defalcated defalcates defalcating defalcation defalcations defalcator defalcators defamation defamatory defame defamed defamer defamers defames defaming defang defanged defanging defangs defat defats defatted defatting default defaulted defaulter defaulters defaulting defaults defeasance defeasances defeasibility defeasible defeasibleness defeat defeated defeater defeaters defeating defeatism defeatist defeatists defeats defecate defecated defecates defecating defecation defecations defecator defecators defect defected defecting defection defections defective defectively defectiveness defectives defector defectors defects defeminize defeminized defeminizes defeminizing defend defendable defendant defendants defended defender defenders defending defends defenestrate defenestrated defenestrates defenestrating defenestration defenestrations defense defensed defenseless defenselessly defenselessness defenseman defensemen defenses defensibility defensible defensibleness defensibly defensing defensive defensively defensiveness defensives defer deference deferens deferent deferentia deferential deferentially deferment deferments deferrable deferral deferrals deferred deferrer deferrers deferring defers defervesce defervesced defervescence defervescences defervescent defervesces defervescing defiance defiant defiantly defibrillate defibrillated defibrillates defibrillating defibrillation defibrillative defibrillator defibrillators defibrillatory deficiencies deficiency deficient deficiently deficit deficits defied defier defiers defies defilade defiladed defilades defilading defile defiled defilement defiler defilers defiles defiling defilingly definability definable definably define defined definement definer definers defines definienda definiendum definiens definientia defining definite definitely definiteness definition definitional definitions definitive definitively definitiveness definitives definitude definitudes deflagrate deflagrated deflagrates deflagrating deflagration deflate deflated deflates deflating deflation deflationary deflationist deflationists deflations deflator deflators deflect deflectable deflected deflecting deflection deflections deflective deflector deflectors deflects deflexed deflexion deflexions defloration deflorations deflower deflowered deflowerer deflowerers deflowering deflowers defoam defoamed defoaming defoams defocus defocused defocuses defocusing defocussed defocusses defocussing defoe defog defogged defogger defoggers defogging defogs defoliant defoliants defoliate defoliated defoliates defoliating defoliation defoliator defoliators deforce deforced deforcement deforces deforcing deforest deforestation deforested deforester deforesters deforesting deforests deform deformability deformable deformation deformational deformations deformed deforming deformities deformity deforms defraud defraudation defrauded defrauder defrauders defrauding defrauds defray defrayable defrayal defrayals defrayed defraying defrays defrock defrocked defrocking defrocks defrost defrosted defroster defrosters defrosting defrosts deft defter deftest deftly deftness defuel defueled defueling defuels defunct defunctive defunctness defund defunded defunding defunds defuse defused defuses defusing defy defying degas degassed degasses degassing degauss degaussed degausser degaussers degausses degaussing degeneracies degeneracy degenerate degenerated degenerately degenerateness degenerates degenerating degeneration degenerations degenerative deglamorize deglamorized deglamorizes deglamorizing deglaze deglazed deglazes deglazing deglutinate deglutinated deglutinates deglutinating deglutination deglutition deglutitory deglycerolize deglycerolized deglycerolizes deglycerolizing degradability degradable degradation degradations degrade degraded degradedly degradedness degrader degraders degrades degrading degradingly degranulation degrease degreased degreaser degreasers degreases degreasing degree degreed degrees degression degressions degressive degressively degum degumming degust degustation degusted degusting degusts dehire dehired dehires dehiring dehisce dehisced dehiscence dehiscent dehisces dehiscing dehorn dehorned dehorning dehorns dehumanization dehumanize dehumanized dehumanizes dehumanizing dehumidification dehumidifications dehumidified dehumidifier dehumidifiers dehumidifies dehumidify dehumidifying dehydratase dehydratases dehydrate dehydrated dehydrates dehydrating dehydration dehydrator dehydrators dehydrochlorinase dehydrochlorinases dehydrochlorinate dehydrochlorinated dehydrochlorinates dehydrochlorinating dehydrochlorination dehydrogenase dehydrogenases dehydrogenate dehydrogenated dehydrogenates dehydrogenating dehydrogenation dehydrogenization dehydrogenize dehydrogenized dehydrogenizes dehydrogenizing dehypnotize dehypnotized dehypnotizes dehypnotizing dei deice deiced deicer deicers deices deicide deicides deicing deictic deictically deific deification deified deifier deifiers deifies deify deifying deign deigned deigning deigns deimos deindustrialization deindustrialize deindustrialized deindustrializes deindustrializing deinstitutionalization deinstitutionalize deinstitutionalized deinstitutionalizes deinstitutionalizing deionization deionize deionized deionizer deionizers deionizes deionizing deipnosophist deipnosophists deirdre deism deist deistic deistical deistically deists deities deity deject dejected dejectedly dejectedness dejecting dejection dejects dekagram dekagrams dekaliter dekaliters dekameter dekameters deke deked dekes deking dekker del delacroix delaminate delaminated delaminates delaminating delamination delaminations delate delated delates delating delation delations delator delators delaware delawarean delawares delay delayed delayer delayers delaying delays dele delectability delectable delectableness delectables delectably delectation delectations deled delegable delegacies delegacy delegalization delegalize delegalized delegalizes delegalizing delegate delegated delegates delegating delegation delegations delegator delegators delegitimization delegitimize delegitimized delegitimizes delegitimizing deleing deles delete deleted deleterious deleteriously deleteriousness deletes deleting deletion deletions delft delfts delftware delhi deli deliberant deliberate deliberated deliberately deliberateness deliberates deliberating deliberation deliberations deliberative deliberatively deliberativeness deliberator deliberators delicacies delicacy delicate delicately delicateness delicates delicatessen delicatessens delicious deliciously deliciousness delict delicti delicto delicts delight delighted delightedly delightedness delighter delighters delightful delightfully delightfulness delighting delights delightsome delightsomely delightsomeness delilah delimit delimitate delimitated delimitates delimitating delimitation delimitative delimited delimiter delimiters delimiting delimits delineate delineated delineates delineating delineation delineations delineative delineator delineators delinquencies delinquency delinquent delinquently delinquents deliquesce deliquesced deliquescence deliquescent deliquesces deliquescing deliria deliriant delirious deliriously deliriousness delirium deliriums delis delist delisted delisting delists deliver deliverability deliverable deliverables deliverance delivered deliverer deliverers deliveries delivering delivers delivery deliveryman deliverymen dell dell'arte dells delmonico delocalization delocalize delocalized delocalizes delocalizing delouse deloused delouses delousing delphi delphian delphic delphically delphinium delphiniums delphinus delta deltaic deltas deltic deltiology deltoid deltoids delude deluded deluder deluders deludes deluding deludingly deluge deluged deluges deluging delusion delusional delusionary delusions delusive delusively delusiveness delusory deluster deluxe delve delved delver delvers delves delving demagnetization demagnetize demagnetized demagnetizer demagnetizers demagnetizes demagnetizing demagnification demagog demagogic demagogically demagogism demagogs demagogue demagoguery demagogues demagogy demand demandable demanded demander demanders demanding demandingly demands demantoid demantoids demarcate demarcated demarcates demarcating demarcation demarcations demarcator demarcators demark dematerialization dematerialize dematerialized dematerializes dematerializing deme demean demeaned demeaning demeaningly demeanor demeanors demeans dement demented dementedly dementedness dementia demential dementing dements demerit demeritorious demeritoriously demerits demerol demersal demes demesne demesnes demeter demeton demetons demies demigod demigoddess demigoddesses demigods demijohn demijohns demilitarization demilitarize demilitarized demilitarizes demilitarizing demimondaine demimondaines demimonde demimondes demineralization demineralize demineralized demineralizer demineralizers demineralizes demineralizing demirelief demireliefs demirep demireps demisable demise demised demisemiquaver demisemiquavers demises demising demission demissions demit demitasse demitasses demits demitted demitting demiurge demiurgeous demiurges demiurgic demiurgical demiurgically demiworld demiworlds demo demob demobbed demobbing demobilization demobilize demobilized demobilizes demobilizing demobs democracies democracy democrat democratic democratically democratization democratize democratized democratizer democratizes democratizing democrats democritus demodulate demodulated demodulates demodulating demodulation demodulations demodulator demodulators demoed demogorgon demographer demographers demographic demographical demographically demographics demography demoing demoiselle demoiselles demolish demolished demolisher demolishers demolishes demolishing demolishment demolition demolitionist demolitionists demolitions demon demonetization demonetizations demonetize demonetized demonetizes demonetizing demoniac demoniacal demoniacally demonian demonic demonical demonically demonism demonization demonize demonized demonizes demonizing demonolatry demonologic demonological demonologist demonologists demonology demons demonstrability demonstrable demonstrableness demonstrably demonstrandum demonstrate demonstrated demonstrates demonstrating demonstration demonstrational demonstrations demonstrative demonstratively demonstrativeness demonstratives demonstrator demonstrators demoralization demoralize demoralized demoralizer demoralizers demoralizes demoralizing demoralizingly demos demosthenes demote demoted demotes demotic demoting demotion demotions demount demountable demounted demounting demounts demulcent demulcents demur demure demurely demureness demurer demurest demurrable demurrage demurrages demurral demurrals demurred demurrer demurrers demurring demurs demy demyelinate demyelinated demyelinates demyelinating demyelination demystification demystified demystifier demystifiers demystifies demystify demystifying demythologization demythologize demythologized demythologizer demythologizers demythologizes demythologizing den denarii denarius denary denationalization denationalize denationalized denationalizes denationalizing denaturalization denaturalize denaturalized denaturalizes denaturalizing denaturant denaturants denaturation denature denatured denatures denaturing dendriform dendrimers dendrite dendrites dendritic dendritically dendrobium dendrobiums dendrochronological dendrochronologically dendrochronologist dendrochronologists dendrochronology dendroid dendrologic dendrological dendrologist dendrologists dendrology dendron dendrons dene deneb denebola denegation denegations denervate denervated denervates denervating denervation denes dengue deniability deniable deniably denial denials denied denier deniers denies denigrate denigrated denigrates denigrating denigration denigrations denigrative denigrator denigrators denigratory denim denims denise denitrification denitrified denitrifies denitrify denitrifying denizen denizenation denizened denizening denizens denmark denned denning denominable denominate denominated denominates denominating denomination denominational denominationalism denominationalist denominationalists denominationally denominations denominative denominatives denominator denominators denormalize denormalized denotable denotation denotational denotationally denotations denotative denotatively denote denoted denotement denotes denoting denotive denouement denouements denounce denounced denouncement denouncements denouncer denouncers denounces denouncing dens dense densely denseness denser densest densification densify densimeter densimeters densimetric densities densitometer densitometers densitometric densitometry density dent dental dentalia dentalium dentaliums dentally dentals dentate dentately dentation dentations dente dented denticle denticles denticular denticulate denticulated denticulately denticulation dentiform dentifrice dentigerous dentil dentils dentin dentinal dentine denting dentins dentist dentistry dentists dentition dentoid dents dentulous denture dentures denturist denturists denuclearization denuclearize denuclearized denuclearizes denuclearizing denudate denudated denudates denudating denudation denudations denude denuded denudement denudes denuding denumerability denumerable denumerably denunciate denunciated denunciates denunciating denunciation denunciations denunciative denunciator denunciators denunciatory denver deny denying denyingly deo deodar deodara deodaras deodars deodorant deodorants deodorization deodorizations deodorize deodorized deodorizer deodorizers deodorizes deodorizing deontological deontologist deontologists deontology deorbit deorbited deorbiting deorbits deoxidation deoxidization deoxidize deoxidized deoxidizer deoxidizers deoxidizes deoxidizing deoxycorticosterone deoxycorticosterones deoxygenate deoxygenated deoxygenates deoxygenating deoxygenation deoxyribonuclease deoxyribonucleases deoxyribonucleic deoxyribonucleotide deoxyribonucleotides deoxyribose deoxyriboses depart departed departeds departing department departmental departmentalization departmentalize departmentalized departmentalizes departmentalizing departmentally departments departs departure departures depauperate depauperation depend dependability dependable dependableness dependably depended dependence dependences dependencies dependency dependent dependently dependents depending depends depersonalization depersonalize depersonalized depersonalizes depersonalizing depict depicted depicter depicting depiction depictions depicts depigmentation depigmentations depilate depilated depilates depilating depilation depilator depilatories depilators depilatory deplane deplaned deplanes deplaning depletable deplete depleted depletes depleting depletion depletions depletive deplorability deplorable deplorableness deplorably deplore deplored deplorer deplorers deplores deploring deploringly deploy deployability deployable deployed deployer deployers deploying deployment deployments deploys deplumation deplume deplumed deplumes depluming depolarization depolarize depolarized depolarizer depolarizers depolarizes depolarizing depoliticization depoliticize depoliticized depoliticizes depoliticizing depollute depolluted depollutes depolluting depone deponed deponent deponents depones deponing depopulate depopulated depopulates depopulating depopulation depopulations depopulator depopulators deport deportable deportation deportations deported deportee deportees deporting deportment deports deposable deposal deposals depose deposed deposes deposing deposit depositaries depositary deposited depositing deposition depositional depositions depositor depositories depositors depository deposits depot depots depravation depravations deprave depraved depravedly depravedness depravement depraver depravers depraves depraving depravities depravity deprecate deprecated deprecates deprecating deprecatingly deprecation deprecations deprecative deprecator deprecatorily deprecators deprecatory depreciable depreciate depreciated depreciates depreciating depreciatingly depreciation depreciations depreciative depreciator depreciators depreciatory depredate depredated depredates depredating depredation depredations depredator depredators depredatory depress depressant depressants depressed depresses depressible depressing depressingly depression depressions depressive depressively depressiveness depressives depressor depressors depressurization depressurize depressurized depressurizes depressurizing deprivable deprival deprivation deprivations deprive deprived deprives depriving deprogram deprogrammed deprogrammer deprogrammers deprogramming deprograms depth depthless depths depurate depurated depurates depurating depuration depurations depurative depurator depurators deputation deputations depute deputed deputes deputies deputing deputization deputize deputized deputizes deputizing deputy dequeue dequeued dequeueing dequeues dequeuing der deracinate deracinated deracinates deracinating deracination derail derailed derailing derailleur derailleurs derailment derailments derails derange deranged derangement derangements deranges deranging derate derated derates derating derbies derby derbyshire derecognition derecognize derecognized derecognizes derecognizing dereference dereferenced dereferencer dereferencers dereferences dereferencing deregulate deregulated deregulates deregulating deregulation deregulations deregulator deregulators deregulatory derelict dereliction derelicts derepress derepressed derepresses derepressing derepression derib deribbed deribbing deribs deride derided derider deriders derides deriding deridingly derision derisive derisively derisiveness derisory derivability derivable derivate derivation derivational derivationally derivations derivative derivatively derivativeness derivatives derive derived deriver derivers derives deriving derma dermabrasion dermabrasions dermal dermapteran dermapterans dermas dermatitis dermatogen dermatogens dermatoid dermatologic dermatological dermatologist dermatologists dermatology dermatome dermatomes dermatophyte dermatophytes dermatophytic dermatophytosis dermatoplasty dermatoses dermatosis dermis dermises derogate derogated derogates derogating derogation derogations derogative derogatively derogator derogatorily derogatoriness derogators derogatory derrick derricks derriere derrieres derring derringer derringers derris derrière derrières dervish dervishes desacralize desacralized desacralizes desacralizing desalinate desalinated desalinates desalinating desalination desalinator desalinators desalinization desalinize desalinized desalinizes desalinizing desalt desalted desalting desalts descant descanted descanter descanters descanting descants descartes descend descendant descendants descended descendent descendents descender descenders descendible descending descends descent descents deschutes descramble descrambled descrambler descramblers descrambles descrambling describable describe described describer describers describes describing descried descrier descriers descries description descriptions descriptive descriptively descriptiveness descriptor descriptors descry descrying desdemona desecrate desecrated desecrater desecraters desecrates desecrating desecration desecrations desecrator desecrators desegregate desegregated desegregates desegregating desegregation desegregationist desegregationists deselect deselected deselecting deselects desensitization desensitize desensitized desensitizer desensitizers desensitizes desensitizing desert deserted deserter deserters desertic desertification deserting desertion desertions deserts deserve deserved deservedly deservedness deserver deservers deserves deserving deservingly desex desexed desexes desexing desexualization desexualize desexualized desexualizes desexualizing desiccant desiccants desiccate desiccated desiccates desiccating desiccation desiccations desiccative desiccator desiccators desiderata desiderate desiderated desiderates desiderating desideration desiderative desideratum design designable designate designated designates designating designation designations designative designator designators designatory designed designedly designee designees designer designers designing designingly designs desipramine desipramines desirability desirable desirableness desirables desirably desire desired desirer desirers desires desiring desirous desirously desirousness desist desistance desisted desisting desists desk deskill deskilled deskilling deskills deskman deskmen desks desktop desktops desman desmans desmid desmids desolate desolated desolately desolateness desolater desolaters desolates desolating desolatingly desolation desolator desolators desorb desorbed desorbing desorbs desorption despair despaired despairer despairers despairing despairingly despairs despatch despatched despatches despatching desperado desperadoes desperados desperate desperately desperateness desperation despicable despicableness despicably despisal despise despised despisement despisements despiser despisers despises despising despite despiteful despitefully despitefulness despoil despoiled despoiler despoilers despoiling despoilment despoilments despoils despoliation despond desponded despondence despondency despondent despondently desponding despondingly desponds despot despotic despotically despotism despots desquamate desquamated desquamates desquamating desquamation dessert desserts dessertspoon dessertspoonful dessertspoonfuls dessertspoons destabilization destabilize destabilized destabilizes destabilizing destain destained destaining destains destalinization destalinizations desterilize desterilized desterilizes desterilizing destination destinations destine destined destines destinies destining destiny destitute destituteness destitution destroy destroyed destroyer destroyers destroying destroys destruct destructed destructibility destructible destructibleness destructing destruction destructionist destructionists destructions destructive destructively destructiveness destructivity destructor destructors destructs desuetude desulfurization desulfurize desulfurized desulfurizes desulfurizing desultorily desultoriness desultory desynchronize desynchronized desynchronizes desynchronizing detach detachability detachable detachably detached detachedly detachedness detaches detaching detachment detachments detail detailed detailedly detailedness detailer detailers detailing details detain detained detainee detainees detainer detainers detaining detainment detains detect detectability detectable detected detecter detecters detecting detection detections detective detectives detector detectors detects detent detente detentes detention detentions detents deter deterge deterged detergence detergences detergency detergent detergents deterges deterging deteriorate deteriorated deteriorates deteriorating deterioration deteriorations deteriorative determent determents determinability determinable determinableness determinably determinacy determinant determinantal determinants determinate determinately determinateness determinater determinaters determination determinations determinative determinatively determinativeness determinatives determine determined determinedly determinedness determiner determiners determines determining determinism determinist deterministic deterministically determinists deterrable deterred deterrence deterrent deterrently deterrents deterrer deterrers deterring deters detersive detersives detest detestability detestable detestableness detestably detestation detested detester detesters detesting detests dethatch dethatched dethatcher dethatchers dethatches dethatching dethrone dethroned dethronement dethrones dethroning detinue detinues detonabilities detonability detonable detonatable detonate detonated detonates detonating detonation detonations detonative detonator detonators detour detoured detouring detours detox detoxed detoxes detoxicant detoxicants detoxicate detoxicated detoxicates detoxicating detoxication detoxification detoxified detoxifies detoxify detoxifying detoxing detract detracted detracting detractingly detraction detractions detractive detractively detractor detractors detracts detrain detrained detraining detrainment detrains detribalization detribalize detribalized detribalizes detribalizing detriment detrimental detrimentally detriments detrital detrition detritions detritus detroit detumescence detumescences detumescent deucalion deuce deuced deucedly deuces deucing deum deums deus deuteragonist deuteragonists deuteranope deuteranopia deuteranopias deuteranopic deuterate deuterated deuterates deuterating deuteration deuterations deuterium deuterocanonical deuterogamy deuteron deuteronomic deuteronomy deuterons deutoplasm deutoplasmic deutoplasms deutsch deutsche deutschmark deutschmarks deutzia deutzias deux devaluate devaluated devaluates devaluating devaluation devaluations devalue devalued devalues devaluing devanagari devastate devastated devastates devastating devastatingly devastation devastations devastative devastator devastators develop developable developed developer developers developing development developmental developmentally developments develops deverbative deverbatives devereux devest devested devesting devests devi deviance deviances deviancies deviancy deviant deviants deviate deviated deviates deviating deviation deviational deviationism deviationist deviationists deviations deviator deviators deviatory device devices devil deviled devilfish devilfishes deviling devilish devilishly devilishness devilkin devilkins devilled devilling devilment devilments devilries devilry devils deviltries deviltry devilwood devilwoods devious deviously deviousness devisable devise devised devisee devisees deviser devisers devises devising devisor devisors devitalization devitalize devitalized devitalizes devitalizing devitrifiable devitrification devitrified devitrifies devitrify devitrifying devocalization devocalize devocalized devocalizes devocalizing devoice devoiced devoices devoicing devoid devoir devoirs devolatilization devolatilize devolatilized devolatilizes devolatilizing devolution devolutionary devolutionist devolutionists devolve devolved devolvement devolves devolving devon devonian devote devoted devotedly devotedness devotee devotees devotement devotes devoting devotion devotional devotionally devotionals devotions devour devoured devourer devourers devouring devouringly devours devout devouter devoutest devoutly devoutness dew dewali dewan dewans dewater dewatered dewatering dewaters dewberries dewberry dewclaw dewclawed dewdrop dewdrops dewed dewfall dewier dewiest dewily dewiness dewing dewlap dewlaps dewless deworm dewormed dewormer dewormers deworming deworms dews dewy dex dexamethasone dexamethasones dexedrine dexes dexie dexies dexter dexterity dexterous dexterously dexterousness dextral dextrality dextrally dextran dextrans dextrin dextro dextroamphetamine dextroamphetamines dextroglucose dextroglucoses dextrorotation dextrorotations dextrorotatory dextrorse dextrorsely dextrose dhabi dharma dharmic dharna dharnas dhaulagiri dhole dholes dhoti dhotis dhow dhows dhurrie dhurries di diabase diabases diabetes diabetic diabetics diable diablerie diableries diablo diabolic diabolical diabolically diabolicalness diabolism diabolist diabolists diabolize diabolized diabolizes diabolizing diacetylmorphine diachronic diachronically diachronies diachrony diaconal diaconate diaconates diacritic diacritical diacritically diacritics diadelphous diadem diademed diademing diadems diadromous diads diaeresis diagenesis diagenetic diageotropic diageotropism diaghilev diagnosable diagnose diagnoseable diagnosed diagnoses diagnosing diagnosis diagnostic diagnostically diagnostician diagnosticians diagnostics diagonal diagonalizable diagonalization diagonalize diagonalized diagonalizes diagonalizing diagonally diagonals diagram diagramed diagraming diagrammable diagrammatic diagrammatical diagrammatically diagrammed diagramming diagrams diakineses diakinesis diakinetic dial dialect dialectal dialectally dialectic dialectical dialectically dialectician dialecticians dialectics dialectological dialectologically dialectologist dialectologists dialectology dialects dialed dialer dialers dialing dialled dialling dialog dialoged dialogic dialogical dialogically dialoging dialogist dialogistic dialogistical dialogistically dialogists dialogs dialogue dialogued dialoguer dialoguers dialogues dialoguing dials dialup dialups dialyses dialysis dialytic dialytically dialyzabilities dialyzability dialyzable dialyze dialyzed dialyzer dialyzers dialyzes dialyzing diamagnet diamagnetic diamagnetism diamagnets diamante diamantes diamanté diamantés diameter diameters diametral diametric diametrical diametrically diamine diamines diamond diamondback diamondbacks diamonded diamondiferous diamonding diamonds diana diandrous diane dianthus diapason diapasons diapause diapauses diapedeses diapedesis diapedetic diaper diapered diapering diapers diaphaneity diaphanous diaphanously diaphanousness diaphone diaphoreses diaphoresis diaphoretic diaphoretics diaphragm diaphragmatic diaphragmatically diaphragms diaphyseal diaphyses diaphysial diaphysis diapir diapiric diapirs diapophyses diapophysial diapophysis diapositive diapsid diapsids diarchal diarchic diarchies diarchy diaries diarist diarists diarize diarized diarizes diarizing diarrhea diarrheal diarrheas diarrheic diarrhetic diarthrodial diarthroses diarthrosis diary diaspora diasporas diaspore diaspores diastase diastases diastasic diastasis diastatic diastema diastemata diastematic diastole diastoles diastolic diastrophic diastrophically diastrophism diastrophisms diatessaron diatessarons diathermic diathermy diatheses diathesis diathetic diatom diatomaceous diatomic diatomite diatoms diatonic diatonically diatonicism diatribe diatribes diatropic diatropism diatropisms diaz diazepam diazine diazines diazinon diazinons diazo diazonium diazoniums dibasic dibber dibbers dibble dibbled dibbler dibblers dibbles dibbling dibden dibranchiate dibranchiates dibromide dibromides dibs dicarboxylic dicast dicastic dicasts dice diced dicentra dicentras dicephalous dicer dicers dices dicey dichasia dichasial dichasially dichasium dichloride dichlorodiphenyl dichlorodiphenyltrichloroethane dichlorodiphenyltrichloroethanes dichlorvos dichogamous dichogamy dichondra dichondras dichotic dichotically dichotomic dichotomies dichotomist dichotomists dichotomization dichotomize dichotomized dichotomizes dichotomizing dichotomous dichotomously dichotomousness dichotomy dichroic dichroism dichroisms dichroite dichroites dichromat dichromate dichromatic dichromatism dichromats dichromic dicier diciest dicing dick dickcissel dickcissels dickens dickensian dickensians dicker dickered dickering dickers dickey dickeys dickies dicks dicky diclinous dicliny dicofol dicofols dicot dicots dicotyledon dicotyledonous dicotyledons dicrotic dicrotism dicta dictaphone dictaphones dictate dictated dictates dictating dictation dictations dictator dictatorial dictatorially dictatorialness dictators dictatorship dictatorships diction dictional dictionally dictionaries dictionary dictu dictum dictums dictyosome dictyosomes dictyostelium did didact didactic didactical didactically didacticism didactics didacts didapper didappers diddle diddled diddler diddlers diddles diddling diddly diddlysquat diderot didn didn't dido didoes didos didst didymium didymous didynamous die dieback diebacks died dieffenbachia dieffenbachias diego diehard diehards dieldrin dieldrins dielectric dielectrically dielectrics diem diemen diencephalic diencephalon diencephalons dieppe diereses dieresis dies diesel dieselize dieselized dieselizes dieselizing diesels dieses diesinker diesinkers diesinking diesis diestock diestocks diestrous diestrus diet dietaries dietarily dietary dieted dieter dieters dietetic dietetically dietetics diethyl diethylcarbamazine diethylstilbestrol dietician dieticians dieting dietitian dietitians dietrich diets differ differed difference differenced differences differencing different differentia differentiability differentiable differentiae differential differentially differentials differentiate differentiated differentiates differentiating differentiation differentiations differentiator differentiators differently differentness differing differs difficile difficult difficulties difficultly difficulty diffidence diffident diffidently diffract diffracted diffracting diffraction diffractions diffractive diffractively diffractiveness diffractometer diffractometers diffracts diffuse diffused diffusely diffuseness diffuser diffusers diffuses diffusible diffusibly diffusing diffusion diffusional diffusions diffusive diffusively diffusiveness dig digamma digammas digamous digamy digastric digastrics digest digested digester digesters digestibility digestible digestibleness digestibly digesting digestion digestions digestive digestively digestiveness digestives digests digger diggers digging diggings digit digital digitalin digitalins digitalis digitalization digitalize digitalized digitalizes digitalizing digitally digitals digitate digitately digitation digitations digitigrade digitization digitize digitized digitizer digitizers digitizes digitizing digitoxin digitoxins digits diglossia diglossias diglyceride diglycerides dignified dignifiedly dignifies dignify dignifying dignitaries dignitary dignities dignity digoxin digoxins digraph digraphic digraphs digress digressed digresses digressing digression digressional digressionary digressions digressive digressively digressiveness digs dihedral dihedrals dihybrid dihybrids dihydric dihydroxy dihydroxyphenylalanine dihydroxyphenylalanines dijkstra dijon dikaryon dikaryons dike diked dikes diking diktat diktats dilantin dilapidate dilapidated dilapidates dilapidating dilapidation dilapidations dilatability dilatable dilatably dilatancies dilatancy dilatant dilatants dilatation dilatational dilatations dilatator dilatators dilate dilated dilatedness dilates dilating dilation dilations dilative dilatometer dilatometers dilatometric dilatometry dilator dilatorily dilatoriness dilators dilatory dildo dildos dilemma dilemmas dilemmatic dilettante dilettantes dilettantish dilettantism diligence diligent diligently dill dillies dills dilly dillydallied dillydallies dillydally dillydallying diluent diluents dilute diluted diluteness diluter diluters dilutes diluting dilution dilutions dilutive dilutor dilutors diluvial dim dime dimenhydrinate dimenhydrinates dimension dimensional dimensionality dimensionally dimensioned dimensioning dimensionless dimensions dimer dimercaprol dimercaprols dimeric dimerism dimerization dimerize dimerized dimerizes dimerizing dimerous dimers dimes dimeter dimeters dimethoate dimethoates dimethyl dimethylnitrosamine dimethylnitrosamines dimethyls dimethylsulfoxide dimethylsulfoxides diminish diminishable diminished diminishes diminishing diminishment diminishments diminuendo diminuendos diminution diminutional diminutive diminutively diminutiveness diminutives dimities dimittis dimity dimly dimmable dimmed dimmer dimmers dimmest dimming dimness dimorph dimorphic dimorphism dimorphisms dimorphous dimorphs dimout dimple dimpled dimples dimpling dimply dims dimwit dimwits dimwitted dimwittedly dimwittedness din dinar dinard dinars dine dined diner diners dines dinette dinettes ding dingbat dingbats dingdong dingdonged dingdonging dingdongs dinged dinghies dinghy dingier dingiest dingily dinginess dinging dingle dingles dingo dingoes dings dingus dinguses dingy dining dinitrobenzene dinitrobenzenes dink dinkey dinkeys dinkier dinkiest dinks dinkum dinky dinned dinner dinnerless dinners dinnertime dinnerware dinning dinoflagellate dinoflagellates dinosaur dinosaurian dinosaurians dinosauric dinosaurlike dinosaurs dinothere dinotheres dins dint dinted dinting dints dinucleotide dinucleotides diocesan diocesans diocese dioceses diocletian diode diodes diodorus dioecious dioeciously dioecism diogenes dioicous diomede diomedes dione dionysia dionysiac dionysian dionysius dionysos dionysus diophantine diopside diopsides diopter diopters dioptometer dioptometers dioptometry dioptral dioptric dioptrics diorama dioramas dioramic diorite diorites dioritic dioscuri dioxane dioxanes dioxide dioxides dioxin dioxins dip dipeptidase dipeptidases dipeptide dipeptides dipetalous diphase diphasic diphenyl diphenylamine diphenylaminechloroarsine diphenylaminechloroarsines diphenylamines diphenylhydantoin diphenylhydantoins diphenylketone diphenylketones diphenyls diphosgene diphosgenes diphosphate diphosphates diphosphoglyceric diphtheria diphtherial diphtheric diphtheritic diphtheroid diphtheroids diphthong diphthongal diphthongization diphthongize diphthongized diphthongizes diphthongizing diphthongs diphycercal diphycercy diphyletic diphyllous diphyodont diplegia diplegias diplex diplexer diplexers diploblastic diplococcal diplococci diplococcic diplococcus diplodocus diplodocuses diploe diploes diploic diploid diploids diploidy diploma diplomacies diplomacy diplomas diplomat diplomate diplomates diplomatic diplomatically diplomatics diplomatist diplomatists diplomats diplont diplontic diplonts diplopia diplopias diplopic diplopod diplopodous diplopods diplosis dipnoan dipnoans dipodic dipodies dipody dipolar dipole dipoles dipped dipper dipperful dipperfuls dippers dippier dippiest dipping dippy dipropellant dipropellants diprotic dips dipsomania dipsomaniac dipsomaniacal dipsomaniacs dipstick dipsticks dipteral dipteran dipterans dipterous diptych diptychs dipyridamole dipyridamoles diquat diquats dirac dire direct directed directing direction directional directionality directionally directionals directionless directions directive directives directivity directly directness directoire director directorate directorates directorial directorially directories directors directorship directorships directory directress directresses directrices directrix directrixes directs direful direfully direfulness direly direness direr direst dirge dirgeful dirges dirham dirhams dirichlet dirigible dirigibles dirk dirked dirking dirks dirndl dirndls dirt dirtied dirtier dirties dirtiest dirtily dirtiness dirty dirtying disabilities disability disable disabled disablement disables disabling disablingly disabuse disabused disabuses disabusing disaccharidase disaccharidases disaccharide disaccharides disaccord disaccorded disaccording disaccords disaccustom disaccustomed disaccustoming disaccustoms disadvantage disadvantaged disadvantagedness disadvantageous disadvantageously disadvantageousness disadvantages disadvantaging disaffect disaffected disaffectedly disaffecting disaffection disaffects disaffiliate disaffiliated disaffiliates disaffiliating disaffiliation disaffiliations disaffirm disaffirmance disaffirmation disaffirmed disaffirming disaffirms disaggregate disaggregated disaggregates disaggregating disaggregation disaggregative disagree disagreeable disagreeableness disagreeably disagreed disagreeing disagreement disagreements disagrees disallow disallowable disallowance disallowed disallowing disallows disambiguate disambiguated disambiguates disambiguating disambiguation disambiguations disannul disannulled disannulling disannulment disannuls disappear disappearance disappearances disappeared disappearing disappears disappoint disappointed disappointedly disappointing disappointingly disappointment disappointments disappoints disapprobation disapproval disapprove disapproved disapprover disapprovers disapproves disapproving disapprovingly disarm disarmament disarmed disarmer disarmers disarming disarmingly disarms disarrange disarranged disarrangement disarranges disarranging disarray disarrayed disarraying disarrays disarticulate disarticulated disarticulates disarticulating disarticulation disarticulator disarticulators disassemble disassembled disassembler disassemblers disassembles disassembling disassembly disassociate disassociated disassociates disassociating disassociation disaster disasters disastrous disastrously disastrousness disavow disavowable disavowal disavowals disavowed disavowing disavows disband disbanded disbanding disbandment disbandments disbands disbar disbarment disbarred disbarring disbars disbelief disbelieve disbelieved disbeliever disbelievers disbelieves disbelieving disbelievingly disbranch disbranched disbranches disbranching disbud disbudded disbudding disbuds disburden disburdened disburdening disburdenment disburdens disbursable disbursal disbursals disburse disbursed disbursement disbursements disburser disbursers disburses disbursing disc discalced discard discardable discarded discarder discarders discarding discards discarnate discern discerned discerner discerners discernible discernibly discerning discerningly discernment discerns discharge dischargeable discharged dischargee dischargees discharger dischargers discharges discharging disci disciform disciple disciples discipleship disciplinable disciplinal disciplinarian disciplinarians disciplinarily disciplinarity disciplinary discipline disciplined discipliner discipliners disciplines disciplining disclaim disclaimed disclaimer disclaimers disclaiming disclaims disclamation disclamations disclimax disclimaxes disclosable disclose disclosed discloser disclosers discloses disclosing disclosure disclosures disco discoed discographer discographers discographic discographical discographies discography discoid discoidal discoideum discoing discolor discoloration discolored discoloring discolors discombobulate discombobulated discombobulates discombobulating discombobulation discomfit discomfited discomfiting discomfits discomfiture discomfort discomfortable discomforted discomforting discomfortingly discomforts discommend discommendable discommended discommending discommends discommode discommoded discommodes discommoding discompose discomposed discomposedly discomposes discomposing discomposingly discomposure disconcert disconcerted disconcerting disconcertingly disconcertment disconcerts disconfirm disconfirmatory disconfirmed disconfirming disconfirms disconformities disconformity disconnect disconnected disconnectedly disconnectedness disconnecting disconnection disconnects disconsolate disconsolately disconsolateness disconsolation discontent discontented discontentedly discontentedness discontenting discontentment discontents discontinuance discontinuation discontinuations discontinue discontinued discontinues discontinuing discontinuities discontinuity discontinuous discontinuously discontinuousness discophile discophiles discord discordance discordancy discordant discordantly discorded discording discords discorporate discos discotheque discotheques discothèque discothèques discount discountable discounted discountenance discountenanced discountenances discountenancing discounter discounters discounting discounts discourage discourageable discouraged discouragement discouragements discourager discouragers discourages discouraging discouragingly discourse discoursed discourser discoursers discourses discoursing discourteous discourteously discourteousness discourtesies discourtesy discover discoverability discoverable discovered discoverer discoverers discoveries discovering discovers discovery discredit discreditable discreditably discredited discrediting discredits discreet discreetly discreetness discrepance discrepances discrepancies discrepancy discrepant discrepantly discrete discretely discreteness discretion discretional discretionally discretionarily discretionary discretization discretize discretized discretizes discretizing discriminability discriminable discriminably discriminant discriminants discriminate discriminated discriminately discriminates discriminating discriminatingly discrimination discriminational discriminations discriminative discriminatively discriminator discriminatorily discriminators discriminatory discs discursion discursive discursively discursiveness discus discuses discuss discussable discussant discussants discussed discusser discussers discusses discussible discussing discussion discussions disdain disdained disdainful disdainfully disdainfulness disdaining disdains disease diseased diseases diseconomies diseconomy disembark disembarkation disembarked disembarking disembarks disembarrass disembarrassed disembarrasses disembarrassing disembarrassment disembodied disembodies disembodiment disembody disembodying disembogue disembogued disemboguement disembogues disemboguing disembowel disemboweled disemboweling disembowelment disembowelments disembowels disemploy disemployed disemploying disemployment disemploys disempower disempowered disempowering disempowerment disempowers disenable disenabled disenables disenabling disenchant disenchanted disenchanter disenchanters disenchanting disenchantingly disenchantment disenchants disencumber disencumbered disencumbering disencumberment disencumbers disendow disendowed disendower disendowers disendowing disendowment disendows disenfranchise disenfranchised disenfranchisement disenfranchises disenfranchising disengage disengaged disengagement disengages disengaging disentail disentailed disentailing disentailment disentails disentangle disentangled disentanglement disentangles disentangling disenthrall disenthralled disenthralling disenthralls disentitle disentitled disentitles disentitling disentomb disentombed disentombing disentombs disentwine disentwined disentwines disentwining disequilibrate disequilibrated disequilibrates disequilibrating disequilibration disequilibrium disestablish disestablished disestablishes disestablishing disestablishment disestablishmentarian disestablishmentarians disesteem disesteemed disesteeming disesteems diseur diseurs diseuse diseuses disfavor disfavored disfavoring disfavors disfeature disfeatured disfeaturement disfeatures disfeaturing disfiguration disfigure disfigured disfigurement disfigurements disfigurer disfigurers disfigures disfiguring disfranchise disfranchised disfranchisement disfranchiser disfranchisers disfranchises disfranchising disfrock disfrocked disfrocking disfrocks disgorge disgorged disgorgement disgorges disgorging disgrace disgraced disgraceful disgracefully disgracefulness disgracer disgracers disgraces disgracing disgruntle disgruntled disgruntlement disgruntles disgruntling disguise disguised disguisedly disguisement disguisements disguiser disguisers disguises disguising disgust disgusted disgustedly disgustful disgustfully disgusting disgustingly disgusts dish dishabille disharmonic disharmonies disharmonious disharmoniously disharmonize disharmonized disharmonizes disharmonizing disharmony dishcloth dishcloths dishearten disheartened disheartening dishearteningly disheartenment disheartenments disheartens dished dishes dishevel disheveled disheveling dishevelment dishevels dishier dishiest dishing dishonest dishonesties dishonestly dishonesty dishonor dishonorable dishonorableness dishonorably dishonored dishonorer dishonorers dishonoring dishonors dishpan dishpans dishrag dishrags dishtowel dishtowels dishware dishwares dishwasher dishwashers dishwashing dishwater dishwaters dishy disillusion disillusioned disillusioning disillusionment disillusions disillusive disincarnate disincentive disincentives disinclination disinclinations disincline disinclined disinclines disinclining disincorporate disincorporated disincorporates disincorporating disincorporation disinfect disinfectant disinfectants disinfected disinfecting disinfection disinfects disinfest disinfestant disinfestants disinfestation disinfested disinfesting disinfests disinflation disinflationary disinform disinformant disinformants disinformation disinformed disinformer disinformers disinforming disinforms disingenuous disingenuously disingenuousness disinherit disinheritance disinheritances disinherited disinheriting disinherits disinhibit disinhibited disinhibiting disinhibition disinhibitions disinhibits disintegrate disintegrated disintegrates disintegrating disintegration disintegrations disintegrative disintegrator disintegrators disinter disinterest disinterested disinterestedly disinterestedness disintermediation disintermediations disinterment disinterred disinterring disinters disintoxicate disintoxicated disintoxicates disintoxicating disintoxication disinvent disinvented disinventing disinvention disinvents disinvest disinvested disinvesting disinvestment disinvestments disinvests disinvitation disinvite disinvited disinvites disinviting disjoin disjoined disjoining disjoins disjoint disjointed disjointedly disjointedness disjointing disjoints disjunct disjunction disjunctive disjunctively disjuncture disjunctures disk disked diskette diskettes disking diskless disklike disks dislikable dislike disliked dislikes disliking dislocate dislocated dislocates dislocating dislocation dislocations dislodge dislodged dislodgement dislodges dislodging dislodgment disloyal disloyally disloyalties disloyalty dismal dismally dismalness dismantle dismantled dismantlement dismantles dismantling dismast dismasted dismasting dismasts dismay dismayed dismaying dismayingly dismays dismember dismembered dismembering dismemberment dismembers dismiss dismissal dismissals dismissed dismisses dismissible dismissing dismission dismissive dismount dismountable dismounted dismounting dismounts disney disneyland disobedience disobedient disobediently disobey disobeyed disobeyer disobeyers disobeying disobeys disoblige disobliged disobliges disobliging disobligingly disorder disordered disorderedly disorderedness disordering disorderliness disorderly disorders disorganization disorganize disorganized disorganizes disorganizing disorient disorientate disorientated disorientates disorientating disorientation disoriented disorienting disorients disown disowned disowning disownment disowns disparage disparaged disparagement disparager disparagers disparages disparaging disparagingly disparate disparately disparateness disparities disparity disparlure disparlures dispassion dispassionate dispassionately dispassionateness dispatch dispatched dispatcher dispatchers dispatches dispatching dispel dispelled dispelling dispels dispensability dispensable dispensableness dispensaries dispensary dispensation dispensational dispensations dispensatories dispensatory dispense dispensed dispenser dispensers dispenses dispensing dispeople dispeopled dispeoples dispeopling dispersal dispersant disperse dispersed dispersedly disperser dispersers disperses dispersible dispersing dispersion dispersions dispersive dispersively dispersiveness dispirit dispirited dispiritedly dispiritedness dispiriting dispirits displace displaceable displaced displacement displacements displacer displacers displaces displacing displant displanted displanting displants display displayable displayed displaying displays displease displeased displeases displeasing displeasingly displeasure disport disported disporting disportment disports disposability disposable disposal disposals dispose disposed disposer disposers disposes disposing disposition dispositions dispossess dispossessed dispossesses dispossessing dispossession dispossessions dispossessor dispossessors dispossessory dispraise dispraised dispraiser dispraisers dispraises dispraising dispraisingly disproof disproportion disproportional disproportionally disproportionate disproportionately disproportionateness disproportionation disproportioned disproportioning disproportions disprovable disproval disprove disproved disproves disproving disputability disputable disputably disputant disputants disputation disputations disputatious disputatiously disputatiousness dispute disputed disputer disputers disputes disputing disqualification disqualifications disqualified disqualifies disqualify disqualifying disquiet disquieted disquieting disquietingly disquietly disquietness disquiets disquietude disquisition disraeli disrate disrated disrates disrating disregard disregarded disregarder disregarders disregardful disregarding disregards disrelish disrelished disrelishes disrelishing disremember disremembered disremembering disremembers disrepair disreputability disreputable disreputableness disreputably disrepute disrespect disrespectability disrespectable disrespected disrespectful disrespectfully disrespectfulness disrespecting disrespects disrobe disrobed disrober disrobers disrobes disrobing disrupt disrupted disrupter disrupters disrupting disruption disruptions disruptive disruptively disruptiveness disruptor disruptors disrupts dissatisfaction dissatisfactions dissatisfactory dissatisfied dissatisfiedly dissatisfies dissatisfy dissatisfying dissect dissected dissectible dissecting dissection dissections dissector dissectors dissects disseize disseized disseizes disseizin disseizing disseizins dissemblance dissemble dissembled dissembler dissemblers dissembles dissembling dissemblingly disseminate disseminated disseminates disseminating dissemination disseminations disseminator disseminators disseminule disseminules dissension dissensions dissent dissented dissenter dissenters dissentience dissentient dissentients dissenting dissentingly dissents dissepiment dissepimental dissepiments dissert dissertate dissertated dissertates dissertating dissertation dissertations dissertator dissertators disserted disserting disserts disserve disserved disserves disservice disserving dissever disseverance dissevered dissevering disseverment dissevers dissidence dissident dissidents dissilient dissimilar dissimilarities dissimilarity dissimilarly dissimilate dissimilated dissimilates dissimilating dissimilation dissimilations dissimilatory dissimilitude dissimulate dissimulated dissimulates dissimulating dissimulation dissimulations dissimulative dissimulator dissimulators dissipate dissipated dissipatedly dissipatedness dissipater dissipaters dissipates dissipating dissipation dissipations dissipative dissipator dissipators dissociability dissociable dissociableness dissociably dissociate dissociated dissociates dissociating dissociation dissociations dissociative dissolubility dissoluble dissolubleness dissolute dissolutely dissoluteness dissolution dissolutive dissolvable dissolve dissolved dissolvent dissolvents dissolver dissolvers dissolves dissolving dissonance dissonances dissonancies dissonancy dissonant dissonantly dissuade dissuaded dissuader dissuaders dissuades dissuading dissuasion dissuasions dissuasive dissuasively dissuasiveness dissymmetric dissymmetrical dissymmetrically dissymmetries dissymmetry distaff distaffs distal distally distance distanced distances distancing distant distantly distantness distaste distasted distasteful distastefully distastefulness distastes distasting distemper distemperate distempered distempering distempers distend distended distending distends distensibility distensible distension distensions distention distich distichous distichously distichs distil distill distillable distillate distillates distillation distillations distilled distiller distilleries distillers distillery distilling distills distils distinct distinction distinctions distinctive distinctively distinctiveness distinctly distinctness distinguish distinguishability distinguishable distinguishably distinguished distinguishes distinguishing distingué distort distortable distorted distortedly distorter distorters distorting distortion distortional distortionary distortions distortive distorts distract distracted distractedly distracter distracters distractibility distractible distracting distractingly distraction distractions distractive distracts distrain distrainable distrained distrainee distrainees distrainer distrainers distraining distrainment distrainor distrainors distrains distraint distraints distrait distraught distraughtly distress distressed distresses distressful distressfully distressfulness distressing distressingly distributable distributaries distributary distribute distributed distributee distributes distributing distribution distributional distributions distributive distributively distributiveness distributives distributivity distributor distributors distributorship distributorships district districted districting districts districtwide distrust distrusted distrustful distrustfully distrustfulness distrusting distrusts disturb disturbance disturbances disturbed disturber disturbers disturbing disturbingly disturbs disulfide disulfides disulfoton disulfotons disunion disunionist disunionists disunite disunited disunites disunities disuniting disunity disuse disused disutility disvalue disvalued disvalues disvaluing disyllabic disyllable disyllables ditch ditched ditcher ditchers ditches ditching dither dithered ditherer ditherers dithering dithers dithery dithyramb dithyrambic dithyrambs ditsier ditsiest ditsy dittanies dittany ditties ditto dittoed dittoes dittoing dittos ditty diu diuresis diuretic diuretically diuretics diurnal diurnally diurnals diuron diurons diva divagate divagated divagates divagating divagation divagations divalent divan divans divaricate divaricated divaricately divaricates divaricating divarication divarications divas dive dived diver diverge diverged divergence divergences divergencies divergency divergent divergently diverges diverging divers diverse diversely diverseness diversification diversified diversifier diversifiers diversifies diversiform diversify diversifying diversion diversionary diversionist diversionists diversions diversities diversity divert diverted diverter diverters diverticula diverticular diverticulitis diverticulosis diverticulum divertimenti divertimento divertimentos diverting divertingly divertissement divertissements diverts dives divest divested divesting divestiture divestitures divestment divestments divests dividable divide divided dividend dividends divider dividers divides dividing divination divinations divinatory divine divined divinely divineness diviner diviners divines divinest diving divining divinities divinity divisibility divisible divisibleness divisibly division divisional divisionism divisionist divisionists divisions divisive divisively divisiveness divisor divisors divorce divorced divorcee divorcees divorcement divorcements divorces divorcing divorcé divorcée divorcées divorcés divot divots divulge divulged divulgement divulgence divulger divulgers divulges divulging divvied divvies divvy divvying diwali dixie dixiecrat dixiecratic dixiecrats dixieland dixit dixon dizen dizened dizening dizenment dizens dizygotic dizygous dizzied dizzier dizzies dizziest dizzily dizziness dizzy dizzying dizzyingly djakarta djellaba djellabah djibouti djiboutian djiboutians dna dnieper do do's doable dobbies dobbin dobbins dobby doberman dobermans dobra dobras dobro dobson dobsonflies dobsonfly dobsons doc docent docents docetic docetism docetist docetists doch docile docilely docility dock dockage docked docker dockers docket docketed docketing dockets dockhand dockhands docking dockmackie dockmackies dockominium dockominiums docks dockside docksides dockworker dockworkers dockyard dockyards docs doctor doctoral doctorate doctorates doctored doctoring doctorless doctorly doctors doctorship doctrinaire doctrinaires doctrinairism doctrinal doctrinally doctrinarian doctrine doctrines docudrama docudramas docudramatic document documentable documental documentalist documentalists documentarian documentarians documentaries documentarily documentarist documentarists documentary documentation documentational documented documenter documenters documenting documents docutainment docutainments dodder doddered dodderer dodderers doddering dodders doddery dodecagon dodecagonal dodecagons dodecahedra dodecahedral dodecahedron dodecahedrons dodecanese dodecaphonic dodecaphonism dodecaphonist dodecaphonists dodecaphony dodge dodged dodger dodgeries dodgers dodgery dodges dodgier dodgiest dodging dodgy dodo dodoes dodoma dodos doe doer doers does doeskin doeskins doesn doesn't doff doffed doffing doffs dog dogbane dogbanes dogberries dogberry dogcart dogcarts dogcatcher dogcatchers doge doges dogface dogfaces dogfight dogfighter dogfighters dogfighting dogfightings dogfights dogfish dogfishes dogged doggedly doggedness doggerel doggerels doggeries doggery doggie doggier doggies doggiest dogging doggish doggishly doggishness doggo doggone doggoned doggoning doggy doghouse doghouses dogie dogies dogleg doglegged doglegging doglegs doglike dogma dogmas dogmata dogmatic dogmatically dogmaticalness dogmatics dogmatism dogmatist dogmatists dogmatization dogmatize dogmatized dogmatizes dogmatizing dognap dognaped dognaping dognapped dognapper dognappers dognapping dognaps dogrib dogribs dogs dogsbodies dogsbody dogsled dogsledder dogsledders dogsledding dogsleds dogtooth dogtooths dogtrot dogtrots dogtrotted dogtrotting dogwatch dogwatches dogwood dogwoods doilies doily doing doings doister dojo dojos dolabriform dolby dolce doldrums dole doled doleful dolefully dolefulness dolerite doleritic doles dolesome dolichocephalic dolichocephalism dolichocephaly dolichocranial dolichocrany doling doll dollar dollarfish dollarfishes dollars dolled dollhouse dollhouses dollied dollies dolling dollish dollishly dollishness dollop dollops dolls dolly dollying dolma dolmades dolman dolmans dolmas dolmen dolmens dolomite dolomites dolomitic dolomitization dolomitize dolor doloroso dolorous dolorously dolorousness dolors dolphin dolphins dolt doltish doltishly doltishness dolts dom domain domains dome domed domenichino domes domesday domestic domestically domesticate domesticated domesticates domesticating domestication domestications domesticities domesticity domesticize domesticized domesticizes domesticizing domestics domical domically domicile domiciled domiciles domiciliary domiciliate domiciliation domiciling dominance dominant dominantly dominants dominate dominated dominates dominating domination dominations dominative dominator dominators dominatrices dominatrix dominatrixes domineer domineered domineering domineeringly domineeringness domineers doming domingo domini dominic dominica dominical dominican dominicans dominie dominies dominion dominions dominique domino dominoes dominos domitian domo domos doms don don't don'ts donald donate donated donatello donates donating donation donations donatism donatist donatists donative donatives donator donators done donee donees doneness dong dongs donjon donjons donkey donkeys donkeywork donkeyworks donna donnas donne donned donning donnish donnishly donnishness donnybrook donnybrooks donnée donor donors dons donut donuts doodad doodads doodle doodlebug doodlebugs doodled doodler doodlers doodles doodling doohickey doohickeys doom doomed doomful doomfully dooming dooms doomsayer doomsayers doomsday doomster door doorbell doorbells doored doorframe doorframes dooring doorjamb doorjambs doorkeeper doorkeepers doorknob doorknobs doorknocker doorknockers doorless doorman doormat doormats doormen doornail doornails doorplate doorplates doorpost doorposts doors doorsill doorsills doorstep doorsteps doorstop doorstopper doorstoppers doorstops doorway doorways doorwoman doorwomen dooryard doozie doozies doozy dopa dopamine dopant dopants dope doped doper dopers dopes dopester dopesters dopey dopier dopiest dopiness doping doppelganger doppelgangers doppelgänger doppelgängers doppler dorado dorbeetle dorbeetles dorchester dordogne dordrecht dorian dorians doric dories dork dorking dorkings dorks dorm dormancy dormant dormer dormers dormice dormin dormins dormitories dormitory dormouse dorms dormy dornick dornicks doronicum doronicums dorothy dorp dorps dorris dorsa dorsad dorsal dorsally dorset dorsiventral dorsiventrally dorsolateral dorsolaterally dorsoventral dorsum dortmund dory dorée dos dosage dosages dose dosed doser dosers doses dosimeter dosimeters dosimetric dosimetry dosing doss dossal dossals dossed dosses dossier dossiers dossing dostoevski dostoyevskian dostoyevsky dot dotage dotal dotard dotards dote doted doter doters dotes doting dotingly dotless dots dotted dotter dotterel dotters dottier dottiest dottily dottiness dotting dottle dottles dotty double doubled doubleday doubleheader doubleheaders doubleness doubler doublers doubles doublespeak doublet doublethink doublethinks doubleton doubletons doubletree doubletrees doublets doublewide doublewides doubleword doublewords doubling doubloon doubloons doubly doubt doubtable doubted doubter doubters doubtful doubtfully doubtfulness doubting doubtingly doubtless doubtlessly doubtlessness doubts douceur douceurs douche douched douches douching doug dough doughboy doughboys doughface doughfaces doughier doughiest doughiness doughlike doughnut doughnuts doughtier doughtiest doughtily doughtiness doughty doughy douglas doum doums dour dourer dourest dourine dourines dourly dourness douro douse doused douser dousers douses dousing doute dove dovecote dovecotes dovekie dovekies dover doves dovetail dovetailed dovetailing dovetails dovish dovishness dow dowager dowagers dowdier dowdies dowdiest dowdily dowdiness dowdy dowdyish dowel doweled doweling dowels dower dowered dowering dowers dowitcher dowitchers down downbeat downbeats downburst downbursts downcast downcourt downdraft downdrafts downed downer downers downfall downfallen downfalls downfield downgrade downgraded downgrades downgrading downhaul downhauls downhearted downheartedly downheartedness downhill downhills downier downiest downiness downing downlink downlinked downlinking downlinks download downloadable downloaded downloading downloads downplay downplayed downplaying downplays downpour downpours downrange downrigger downriggers downright downrightly downrightness downriver downs downscale downscaled downscales downscaling downshift downshifted downshifting downshifts downside downsides downsize downsized downsizes downsizing downslide downslides downslope downspin downspins downspout downspouts downstage downstairs downstate downstater downstaters downstream downstroke downswing downswings downtick downticks downtime downtimes downtown downtowner downtowners downtowns downtrend downtrended downtrending downtrends downtrodden downturn downturns downward downwardly downwardness downwards downwind downy downzone downzoned downzones downzoning dowries dowry dowse dowsed dowser dowsers dowses dowsing doxies doxological doxologically doxologies doxology doxorubicin doxorubicins doxy doxycycline doxycyclines doyen doyenne doyennes doyens doyle doze dozed dozen dozens dozenth dozer dozers dozes dozier doziest dozily doziness dozing dozy doña dr drab drabbed drabber drabbest drabbing drabble drabbled drabbles drabbling drably drabness drabs dracaena dracaenas drachenfels drachm drachma drachmae drachmas drachms draconian draconic draconically dracula draft draftable drafted draftee draftees drafter drafters draftier draftiest draftily draftiness drafting draftings drafts draftsman draftsmanship draftsmen draftsperson draftspersons draftswoman draftswomen drafty drag dragged dragger draggers draggier draggiest dragging draggingly draggle draggled draggles draggling draggy draglift draglifts dragline draglines dragnet dragnets dragoman dragomans dragomen dragon dragonet dragonets dragonflies dragonfly dragonhead dragonheads dragonish dragonroot dragonroots dragons dragoon dragooned dragooning dragoons drags dragster dragsters dragée drain drainable drainage drained drainer drainers draining drainpipe drainpipes drains drake drakes dram drama dramamine dramas dramatic dramatically dramatics dramatis dramatist dramatists dramatization dramatizations dramatize dramatized dramatizes dramatizing dramaturge dramaturges dramaturgic dramaturgical dramaturgically dramaturgy drams drang drank drapability drapable drape draped draper draperies drapers drapery drapes draping drastic drastically drat dratted dratting draught draughts dravidian dravidians dravidic draw drawable drawback drawbacks drawbar drawbars drawbridge drawbridges drawdown drawdowns drawee drawees drawer drawerful drawers drawing drawings drawknife drawknives drawl drawled drawler drawlers drawling drawlingly drawls drawly drawn drawnwork drawplate drawplates draws drawshave drawshaves drawstring drawstrings drawtube drawtubes dray drayage drayed draying drayman draymen drays drayton dread dreaded dreadful dreadfully dreadfulness dreading dreadlocked dreadlocks dreadnought dreadnoughts dreads dream dreamboat dreamboats dreamed dreamer dreamers dreamful dreamfully dreamfulness dreamier dreamiest dreamily dreaminess dreaming dreamland dreamlands dreamless dreamlessly dreamlessness dreamlike dreams dreamscape dreamscapes dreamt dreamtime dreamtimes dreamworld dreamworlds dreamy drear drearier dreariest drearily dreariness dreary dreck drecks drecky dredge dredged dredger dredgers dredges dredging dreg dregs dreidel dreidels drench drenched drencher drenchers drenches drenching dresden dress dressage dressed dresser dressers dresses dressier dressiest dressily dressiness dressing dressings dressmaker dressmakers dressmaking dressy drew dreyfus drib dribble dribbled dribbler dribblers dribbles dribbling driblet driblets dribs dried drier driers dries driest drift driftage driftages drifted drifter drifters drifting driftingly drifts driftwood drifty drill drillability drillable drilled driller drillers drilling drillings drillmaster drillmasters drills drillstock drillstocks drily drink drinkability drinkable drinkables drinker drinkers drinking drinks drip dripless dripped dripper drippier drippiest drippily drippiness dripping drippings drippy drips dripstone dripstones drivability drivable drive drivel driveled driveler drivelers driveline drivelines driveling drivelled drivelling drivels driven drivenness driver driverless drivers drives drivetrain drivetrains driveway driveways driving drivingly drizzle drizzled drizzles drizzling drizzly drogue drogues droit droits droll droller drolleries drollery drollest drollness drolls drolly dromedaries dromedary dromond dromonds drone droned droner droners drones droning droningly drool drooled drooling drools droop drooped droopier droopiest droopily droopiness drooping droopingly droops droopy drop dropforge dropforged dropforges dropforging drophead dropkick dropkicked dropkicker dropkickers dropkickes dropkicking dropkicks droplet droplets droplight droplights dropout dropouts dropped dropper dropperful droppers dropping droppings drops dropsical dropsically dropsy dropwort dropworts drosera droseras droshkies droshky drosophila dross drossy drought droughtiness droughts droughty drove drover drovers droves drown drowned drowning drownings drowns drowse drowsed drowses drowsier drowsiest drowsily drowsiness drowsing drowsy drub drubbed drubber drubbers drubbing drubbings drubs drudge drudged drudger drudgeries drudgers drudgery drudges drudgework drudgeworks drudging drudgingly drug drugged drugget druggets druggie druggier druggies druggiest drugging druggist druggists druggy drugless drugmaker drugmakers drugola drugolas drugs drugstore drugstores druid druidic druidical druidically druidism druids drum drumbeat drumbeater drumbeaters drumbeating drumbeats drumette drumettes drumfire drumfires drumhead drumheads drumlike drumlin drumlins drummed drummer drummers drumming drumroll drumrolls drums drumstick drumsticks drunk drunkard drunkards drunken drunkenly drunkenness drunker drunkest drunks drupaceous drupe drupelet drupelets drupes druse druses druthers dry dryable dryad dryadic dryads dryasdust dryasdusts dryden dryer dryers dryest drying dryings drylands drylot drylots dryly dryness dryopithecine dryopithecines drypoint drypoints drys drysalter drysalters drysaltery drywall drywalls duad duads dual dualism dualist dualistic dualistically dualists dualities duality dualize dualized dualizes dualizing dually dub dubai dubbed dubber dubbers dubbin dubbing dubbins dubieties dubiety dubious dubiously dubiousness dubitable dubitably dublin dubliner dubliners dubnium dubrovnik dubs dubuque ducal ducally ducat ducats duce duces duchess duchesses duchies duchy duck duckbill duckbilled duckbills duckboard ducked ducker duckers duckier duckiest ducking duckling ducklings duckpin duckpins ducks ducktail ducktails duckweed duckweeds ducky duct ductal ducted ductile ductilibility ductility ducting ductings ductless ducts ductule ductules ductwork ductworks dud dude duded dudeen dudeens dudes dudgeon dudgeons duding dudish dudishly duds due duel dueled dueler duelers dueling duelist duelists duelled duelling duels duende duendes dueness duenna duennas duennaship dues duet duets duetted duetting duff duffel duffels duffer duffers duffle duffles duffs dug dugong dugongs dugout dugouts dugs duiker duikers duke duked dukedom dukedoms dukes dukhobor dukhobors duking dulcet dulcetly dulcification dulcified dulcifies dulcify dulcifying dulcimer dulcimers dulcimore dulcimores dulcinea dull dullard dullards dulled duller dulles dullest dulling dullish dullishly dullness dulls dullsville dullsvilles dully dulness dulse dulses duluth duly duma dumas dumb dumbbell dumbbells dumbed dumber dumbest dumbfound dumbfounded dumbfounding dumbfounds dumbing dumbly dumbness dumbo dumbos dumbs dumbstruck dumbwaiter dumbwaiters dumdum dumdums dumfound dumfounded dumfounding dumfounds dumfries dumka dumky dummied dummies dummkopf dummkopfs dummy dummying dumortierite dumortierites dump dumpcart dumpcarts dumped dumper dumpers dumpier dumpiest dumpily dumpiness dumping dumpish dumpling dumplings dumps dumpsite dumpsites dumpster dumpsters dumpties dumpty dumpy dun duncan dunce dunces dunderhead dunderheaded dunderheads dundrearies dune dunedin duneland dunelike dunes dung dungaree dungarees dunged dungeon dungeons dunghill dunghills dunging dungs dungy dunite dunites dunitic dunk dunked dunker dunkers dunking dunkirk dunks dunlin dunlins dunlop dunlops dunnage dunnages dunned dunning duns duo duodecimal duodecimally duodecimals duodecimo duodecimos duodena duodenal duodenary duodenum duodenums duologue duologues duomo duomos duopolies duopoly duopsonies duopsony duos duotone dupability dupable dupe duped duper duperies dupers dupery dupes duping duple duplex duplexer duplexers duplexes duplexity duplicable duplicatable duplicate duplicated duplicately duplicates duplicating duplication duplications duplicative duplicator duplicators duplicatory duplicities duplicitous duplicitously duplicitousness duplicity dupont dura durability durable durableness durables durably dural duralumin duralumins duramen duramens durance duration durations durban durbar durbars duress durga durham durian durians during durkheim durkheimian durmast durmasts duro duroc durocs durometer durometers duros durra durras durum dusk dusked duskier duskiest duskily duskiness dusking dusks dusky dust dustbin dustbins dustcover dustcovers dusted duster dusters dustheap dustheaps dustier dustiest dustily dustiness dusting dustings dustless dustlike dustman dustmen dustpan dustpans dusts dustsheet dustsheets dustup dustups dusty dutch dutchman dutchmen dutchwoman dutchwomen duteous duteously dutiable duties dutiful dutifully dutifulness duty duumvir duumvirate duumvirates duumvirs duvet duvets duvetyn duvetyns dvorak dvorák dwarf dwarfed dwarfing dwarfish dwarfishly dwarfishness dwarfism dwarflike dwarfness dwarfs dwarves dweeb dweebs dwell dwelled dweller dwellers dwelling dwellings dwells dwelt dwindle dwindled dwindles dwindling dyad dyadic dyadically dyadics dyads dyak dyaks dyarchies dyarchy dybbuk dybbukim dybbuks dye dyeability dyeable dyed dyeing dyer dyer's dyers dyes dyestuff dyestuffs dyewood dyewoods dyfed dying dyke dykes dynamic dynamical dynamically dynamicist dynamicists dynamics dynamism dynamist dynamistic dynamists dynamite dynamited dynamiter dynamiters dynamites dynamitic dynamiting dynamo dynamoelectric dynamoelectrical dynamometer dynamometers dynamometric dynamometrical dynamometry dynamos dynamotor dynamotors dynast dynastic dynastically dynasties dynasts dynasty dynatron dynatrons dyne dynes dynode dynodes dyscalculia dyscalculias dyscrasia dyscrasias dysenteric dysentery dysfunction dysfunctional dysgenesis dysgenic dysgenics dysgraphia dysgraphias dysgraphic dyskinesia dyskinesias dyslectic dyslexia dyslexic dyslexics dyslogistic dyslogistically dysmenorrhea dysmenorrheal dysmenorrheic dyspepsia dyspeptic dyspeptically dyspeptics dysphagia dysphagias dysphagic dysphasia dysphasic dysphasics dysphonia dysphonias dysphonic dysphoria dysphorias dysphoric dysplasia dysplastic dyspnea dyspneas dyspneic dysprosium dysrhythmia dysrhythmias dysteleological dysteleologist dysteleologists dysteleology dystopia dystopian dystopias dystrophic dystrophication dystrophy dysuria dysurias dysuric dáil débouché débride débrided débridement débrides débriding début débutant débutante débutantes débutants débuts débâcle débâcles déclassé décolletage décolletages décolleté décor décors dégagé déjà démarche démodé dénouement dénouements déshabillé détente détentes détentist détentists développé dürer düsseldorf e e'er each eager eagerer eagerest eagerly eagerness eagle eagled eagles eaglet eaglets eagling eagre eagres ealdorman ealdormen ear earache earaches eardrop eardrops eardrum eardrums eared earflap earflaps earful earfuls earing earings earl earlap earlaps earldom earldoms earless earlier earliest earliness earlobe earlobes earlock earlocks earls early earmark earmarked earmarking earmarkings earmarks earmuff earmuffs earn earned earner earners earnest earnestly earnestness earnests earning earnings earns earp earphone earphones earpiece earpieces earplug earplugs earring earrings ears earshot earshots earsplitting earth earthborn earthbound earthed earthen earthenware earthier earthiest earthily earthiness earthing earthlight earthlights earthlike earthliness earthling earthlings earthly earthman earthmen earthmover earthmovers earthmoving earthnut earthnuts earthquake earthquakes earthrise earthrises earths earthshaker earthshakers earthshaking earthshakingly earthshine earthshines earthstar earthstars earthward earthwards earthwork earthworks earthworm earthworms earthy earwax earwaxes earwig earwigged earwigging earwigs earwitness earwitnesses earworm earworms ease eased easeful easefully easefulness easel easels easement easements eases easier easiest easily easiness easing east eastbound easter easterlies easterly eastern easterner easterners easternmost easternness easters eastertide eastertides easthampton easting eastings eastward eastwardly eastwards easy easygoing easygoingness eat eatable eatables eaten eater eateries eaters eatery eating eats eau eaux eaves eavesdrop eavesdropped eavesdropper eavesdroppers eavesdropping eavesdrops ebb ebbed ebbing ebbs ebola eboli ebon ebonics ebonies ebonite ebonites ebonize ebonized ebonizes ebonizing ebons ebony ebracteate ebro ebullience ebulliencies ebulliency ebullient ebulliently ebullition ebullitions eburnation eburnations ecce eccentric eccentrically eccentricities eccentricity eccentrics ecchymoses ecchymosis ecchymotic ecclesia ecclesiae ecclesial ecclesiastes ecclesiastic ecclesiastical ecclesiastically ecclesiasticism ecclesiasticisms ecclesiastics ecclesiasticus ecclesiological ecclesiology eccrine ecdyses ecdysiast ecdysiasts ecdysis ecdysone ecdysones ecesis ecesises echard echards echelon echeloned echeloning echelons echeveria echeverias echidna echidnas echinate echini echinococci echinococcoses echinococcosis echinococcus echinoderm echinodermal echinodermatous echinoderms echinoid echinoids echinus echo echocardiogram echocardiograms echocardiograph echocardiographic echocardiographs echocardiography echoed echoencephalogram echoencephalograms echoencephalograph echoencephalographic echoencephalographs echoencephalography echoer echoers echoes echoey echogram echograms echography echoic echoing echolalia echolalias echolalic echolocate echolocated echolocates echolocating echolocation echovirus echoviruses eclair eclairs eclampsia eclampsias eclamptic eclectic eclectically eclecticism eclectics eclipse eclipsed eclipses eclipsing ecliptic ecliptics eclogue eclogues eclosion eclosions ecocatastrophe ecocatastrophes ecocide ecofreak ecofreaks ecologic ecological ecologically ecologies ecologist ecologists ecology econometric econometrical econometrically econometrician econometricians econometrics econometrist econometrists economic economical economically economics economies economist economists economize economized economizer economizers economizes economizing economy ecophysiological ecophysiology ecospecies ecosphere ecospheres ecosystem ecosystems ecoterrorism ecoterrorist ecoterrorists ecotone ecotones ecotype ecotypes ecotypic ecru ecrus ecstasies ecstasy ecstatic ecstatically ectocommensal ectocommensals ectoderm ectodermal ectodermic ectogenous ectomere ectomeres ectomeric ectomorph ectomorphic ectomorphs ectomorphy ectoparasite ectoparasites ectoparasitic ectoparasitism ectopia ectopias ectopic ectoplasm ectoplasmic ectosarc ectosarcs ectotherm ectothermic ectotherms ectotrophic ecuador ecuadorean ecuadoreans ecuadorian ecuadorians ecumenical ecumenicalism ecumenically ecumenicism ecumenicisms ecumenicist ecumenicists ecumenicity ecumenics ecumenism ecumenist ecumenists eczema eczemas eczematous edacious edacities edacity edam edaphic edaphically edda eddic eddied eddies eddo eddoes eddy eddying edelweiss edelweisses edema edemas edemata edematous eden edenic edentate edentates edentulous edgar edge edged edgeless edger edgers edges edgeways edgewise edgier edgiest edgily edginess edging edgings edgy edh edhs edibility edible edibleness edibles edict edictal edicts edification edifice edifices edified edifier edifiers edifies edify edifying edifyingly edinburgh edison edit editable edited edith editing edition editions editor editorial editorialist editorialists editorialization editorializations editorialize editorialized editorializer editorializers editorializes editorializing editorially editorials editors editorship editorships editress editresses edits edmund edom edomite edomites edomitish educability educable educate educated educatedness educates educating education educational educationalist educationalists educationally educationist educationists educations educative educator educators educe educed educes educible educing eduction eductions eductor eductors edulcorate edulcorated edulcorates edulcorating edward edwardian eel eelgrass eelgrasses eellike eelpout eelpouts eels eelskin eelworm eelworms eely eerie eerier eeriest eerily eeriness eery ef efate efface effaceable effaced effacement effacer effacers effaces effacing effect effected effecter effecters effectible effecting effective effectively effectiveness effectives effectivity effector effectors effects effectual effectuality effectually effectualness effectuate effectuated effectuates effectuating effectuation effeminacy effeminate effeminately effeminateness effeminates effeminize effeminized effeminizes effeminizing effendi effendis efferent efferentia efferently efferents effervesce effervesced effervescence effervescency effervescent effervescently effervesces effervescing effete effetely effeteness efficacies efficacious efficaciously efficaciousness efficacity efficacy efficiencies efficiency efficient efficiently effigies effigy effloresce effloresced efflorescence efflorescent effloresces efflorescing effluence effluences effluent effluents effluvia effluvial effluvium effluviums efflux effluxes effluxion effluxions effort effortful effortfully effortless effortlessly effortlessness efforts effronteries effrontery effulgence effulgences effulgent effuse effused effuses effusing effusion effusions effusive effusively effusiveness efik efiks eft efts eftsoons egad egads egalitarian egalitarianism egalitarians egalite egalites egeria egerias egest egesta egested egesting egestion egestions egestive egests egg eggbeater eggbeaters eggcup eggcups egged egger eggers eggfruit eggfruits egghead eggheaded eggheadedness eggheads egging eggless eggnog eggnogs eggplant eggplants eggs eggshell eggshells eglantine eglantines ego egocentric egocentrically egocentricities egocentricity egocentrics egocentrism egoism egoisms egoist egoistic egoistical egoistically egoists egomania egomaniac egomaniacal egomaniacally egomaniacs egomanias egos egotism egotisms egotist egotistic egotistical egotistically egotists egregious egregiously egregiousness egress egressed egresses egressing egression egressions egret egrets egypt egyptian egyptians egyptological egyptologist egyptologists egyptology eh eider eiderdown eiderdowns eiders eidetic eidetically eidola eidolon eidolons eiffel eigenfunction eigenspace eigenstate eigenvalue eigenvalues eigenvector eigenvectors eight eighteen eighteenfold eighteenmo eighteenmos eighteens eighteenth eighteenths eightfold eighth eighthly eighths eighties eightieth eightieths eightpenny eights eightvo eightvos eighty eightyfold eilat eileen eindhoven einkorn einkorns einstein einsteinian einsteinium eire eisenach eisenhower eisteddfod eisteddfodau eisteddfods either ejaculate ejaculated ejaculates ejaculating ejaculation ejaculations ejaculator ejaculators ejaculatory eject ejecta ejectable ejected ejecting ejection ejections ejective ejectment ejectments ejector ejectors ejects eke eked ekes eking ekistic ekistical ekistician ekisticians ekistics ekpwele el elaborate elaborated elaborately elaborateness elaborates elaborating elaboration elaborations elaborative elaborator elaborators elagabalus elaine elam elamite elamites eland elands elapid elapids elapse elapsed elapses elapsing elara elasmobranch elasmobranchs elastase elastases elastic elastically elasticities elasticity elasticized elastics elastin elastins elastomer elastomeric elastomers elate elated elatedly elatedness elater elaterid elaterids elaterite elaterites elaters elates elating elation elations elavil elba elbe elbow elbowed elbowing elbowroom elbows elder elderberries elderberry eldercare elderlies elderliness elderly elders eldership eldest eldritch eleanor eleatic eleaticism eleatics elecampane elecampanes elect electability electable elected electing election electioneer electioneered electioneerer electioneerers electioneering electioneers elections elective electively electiveness electives elector electoral electorally electorate electorates electors electra electress electresses electret electrets electric electrical electrically electrician electricians electricities electricity electrics electrifiable electrification electrified electrifier electrifiers electrifies electrify electrifying electrifyingly electroacoustic electroacoustically electroacoustics electroanalyses electroanalysis electroanalytic electroanalytical electrocardiogram electrocardiograms electrocardiograph electrocardiographic electrocardiographically electrocardiographs electrocardiography electrochemical electrochemically electrochemist electrochemistry electrochemists electrocoagulation electrocoagulations electroconvulsive electrocorticogram electrocorticograms electrocute electrocuted electrocutes electrocuting electrocution electrocutions electrode electrodeposit electrodeposited electrodepositing electrodeposition electrodepositions electrodeposits electrodermal electrodes electrodialyses electrodialysis electrodialytic electrodynamic electrodynamics electrodynamometer electrodynamometers electroencephalogram electroencephalograms electroencephalograph electroencephalographic electroencephalographs electroencephalography electroform electroformed electroforming electroforms electrogasdynamic electrogasdynamics electrogenesis electrogenic electrogram electrograms electrograph electrographs electrohydraulic electrohydraulically electrojet electrokinetic electrokinetics electroless electrologist electrologists electroluminescence electroluminescences electroluminescent electrolyses electrolysis electrolyte electrolytes electrolytic electrolytically electrolyze electrolyzed electrolyzes electrolyzing electromagnet electromagnetic electromagnetically electromagnetism electromagnetisms electromagnets electromechanical electromechanically electrometallurgical electrometallurgy electrometer electrometers electromotive electromyogram electromyograms electromyograph electromyographic electromyographically electromyographs electromyography electron electronegative electronegativity electronic electronically electronics electrons electrooculogram electrooculograms electrophile electrophiles electrophilic electrophilicity electrophorese electrophoresed electrophoreses electrophoresing electrophoresis electrophoretic electrophoretically electrophoretogram electrophoretograms electrophori electrophorus electrophotographic electrophotography electrophysiologic electrophysiological electrophysiologically electrophysiologist electrophysiologists electrophysiology electroplate electroplated electroplates electroplating electropositive electroreception electroreceptor electroreceptors electroretinogram electroretinograms electroretinograph electroretinographic electroretinography electroscope electroscopes electroscopic electroshock electroshocked electroshocking electroshocks electrostatic electrostatically electrostatics electrosurgeries electrosurgery electrosurgical electrosurgically electrotherapeutics electrotherapies electrotherapist electrotherapists electrotherapy electrothermal electrothermally electrotonic electrotonically electrotonus electrotonuses electrotype electrotyped electrotyper electrotypers electrotypes electrotypic electrotyping electrovalence electrovalencies electrovalency electrovalent electrowinning electrum electrums elects electuaries electuary eleemosynary elegance elegances elegancies elegancy elegant elegantly elegiac elegiacal elegiacally elegiacs elegies elegist elegists elegit elegits elegize elegized elegizes elegizing elegy eleison element elemental elementally elementals elementarily elementariness elementary elements elemi elemis elephant elephantiasis elephantine elephants eleusinian eleusinians eleusis elevate elevated elevateds elevates elevating elevation elevations elevator elevators eleven elevenfold elevens elevenses eleventh elevenths elevon elevons elf elfin elfish elfishly elfishness elflock elflocks elgar elhi eli elicit elicitation elicitations elicited eliciting elicitor elicitors elicits elide elided elides eliding eligibilities eligibility eligible eligibles eligibly elijah eliminate eliminated eliminates eliminating elimination eliminations eliminative eliminator eliminators eliminatory eliot elisha elision elisions elite elites elitism elitisms elitist elitists elixir elixirs elizabeth elizabethan elizabethans elk elkhound elkhounds elks ell ellagic ellen ellesmere ellington elliot elliott ellipse ellipses ellipsis ellipsoid ellipsoidal ellipsoids elliptic elliptical elliptically ellipticity ells elm elmo elms elocution elocutionary elocutionist elocutionists elodea elodeas eloign eloigned eloigning eloigns elongate elongated elongates elongating elongation elongations elope eloped elopement elopements eloper elopers elopes eloping eloquence eloquent eloquently eloquentness els else elsewhere eluant eluants eluate eluates elucidate elucidated elucidates elucidating elucidation elucidations elucidative elucidator elucidators elucidatory elucubrate elucubrated elucubrates elucubrating elucubration elucubrations elude eluded eludes eluding elusion elusions elusive elusively elusiveness elusory elute eluted elutes eluting elution elutions elutriate elutriated elutriates elutriating elutriation elutriations elutriator elutriators eluvial eluviate eluviated eluviates eluviating eluviation eluviations eluvium eluviums elver elvers elves elvis elvish elysian elysium elytra elytroid elytron em emaciate emaciated emaciates emaciating emaciation emaciations email emailed emailing emails emalangeni emanate emanated emanates emanating emanation emanational emanations emanative emancipate emancipated emancipates emancipating emancipation emancipationist emancipationists emancipations emancipative emancipator emancipators emancipatory emarginate emargination emarginations emasculate emasculated emasculates emasculating emasculation emasculations emasculative emasculator emasculators emasculatory embalm embalmed embalmer embalmers embalming embalmment embalmments embalms embank embanked embanking embankment embankments embanks embarcadero embarcaderos embargo embargoed embargoes embargoing embargos embark embarkation embarkations embarked embarking embarkment embarkments embarks embarrass embarrassable embarrassed embarrassedly embarrasses embarrassing embarrassingly embarrassment embarrassments embassage embassages embassies embassy embattle embattled embattlement embattlements embattles embattling embay embayed embaying embayment embayments embays embed embeddable embedded embedding embedment embedments embeds embellish embellished embellisher embellishers embellishes embellishing embellishment embellishments ember embers embezzle embezzled embezzlement embezzlements embezzler embezzlers embezzles embezzling embitter embittered embittering embitterment embitterments embitters emblaze emblazed emblazes emblazing emblazon emblazoned emblazoner emblazoners emblazoning emblazonment emblazonments emblazonries emblazonry emblazons emblem emblematic emblematical emblematically emblematize emblematized emblematizes emblematizing emblemed emblements embleming emblemize emblemized emblemizes emblemizing emblems embodied embodier embodiers embodies embodiment embodiments embody embodying embolden emboldened emboldening emboldens embolectomies embolectomy emboli embolic embolies embolism embolismic embolisms embolization embolus emboly embonpoint embonpoints embosom embosomed embosoming embosoms emboss embossable embossed embosser embossers embosses embossing embossment embossments embouchement embouchure embouchures embourgeoisement embourgeoisements embowed embowel emboweled emboweling embowelled embowelling embowels embower embowered embowering embowers embrace embraceable embraced embracement embracements embraceor embraceors embracer embraceries embracers embracery embraces embracing embracingly embracive embranchment embranchments embrangle embrangled embranglement embranglements embrangles embrangling embrasure embrasured embrasures embrittle embrittled embrittlement embrittlements embrittles embrittling embrocate embrocated embrocates embrocating embrocation embrocations embroider embroidered embroiderer embroiderers embroideries embroidering embroiders embroidery embroil embroiled embroiling embroilment embroilments embroils embrown embrowned embrowning embrowns embrue embrued embrues embruing embryectomies embryectomy embryo embryogenesis embryogenetic embryogenic embryogeny embryoid embryoids embryologic embryological embryologically embryologies embryologist embryologists embryology embryonal embryonated embryonic embryonically embryopathies embryopathy embryos embryotic emcee emceed emceeing emcees emend emendable emendate emendated emendates emendating emendation emendations emendator emendators emendatory emended emender emenders emending emends emerald emeralds emerge emerged emergence emergences emergencies emergency emergent emergents emerges emerging emeries emerita emeritae emeritas emeriti emeritus emersed emersion emersions emerson emery emeses emesis emetic emetically emetics emetine emetines emigrant emigrants emigrate emigrated emigrates emigrating emigration emigrations emigratory emilia emilion eminence eminences eminencies eminency eminent eminently emir emirate emirates emirs emissaries emissary emission emissions emissive emissivity emit emits emittance emitted emitter emitters emitting emma emmanuel emmaus emmenagogue emmenagogues emmer emmers emmet emmetropia emmetropias emmetropic emmets emmy emmys emodin emodins emollient emollients emolument emoluments emote emoted emoter emoters emotes emoting emotion emotional emotionalism emotionalist emotionalistic emotionalists emotionality emotionalize emotionalized emotionalizes emotionalizing emotionally emotionless emotionlessly emotionlessness emotions emotive emotively emotiveness emotivity empale empaled empales empaling empanada empanel empaneled empaneling empanelled empanelling empanels empathetic empathetically empathic empathize empathized empathizer empathizers empathizes empathizing empathy empedocles empennage empennages emperies emperor emperors emperorship emperorships empery emphases emphasis emphasize emphasized emphasizes emphasizing emphatic emphatically emphysema emphysematous emphysemic emphysemics empire empires empiric empirical empirically empiricism empiricist empiricists empirics emplace emplaced emplacement emplacements emplaces emplacing emplane emplaned emplanes emplaning employ employability employable employe employed employee employees employer employers employes employing employment employments employs empoison empoisoned empoisoning empoisonment empoisons emporia emporium emporiums empower empowered empowering empowerment empowerments empowers empress empressement empressements empresses emprise emprises emptied emptier empties emptiest emptily emptiness emptor empty emptying empurple empurpled empurples empurpling empyema empyemas empyemata empyemic empyreal empyrean empyreans ems emu emulate emulated emulates emulating emulation emulations emulative emulatively emulator emulators emulous emulously emulousness emulsible emulsifiable emulsification emulsifications emulsified emulsifier emulsifiers emulsifies emulsify emulsifying emulsion emulsions emulsive emulsoid emulsoidal emulsoids emunctories emunctory emus en enable enabled enabler enablers enables enabling enact enactable enacted enacting enactment enactments enactor enactors enacts enamel enameled enameler enamelers enameling enamelist enamelists enamelled enamelling enamels enamelware enamine enamines enamoenantiomeric enamor enamored enamoring enamors enamour enamoured enamouring enamours enantiomer enantiomers enantiomorph enantiomorphic enantiomorphism enantiomorphous enantiomorphs enarthroses enarthrosis enate enates enatic enation enations encaenia encage encaged encages encaging encamp encamped encamping encampment encampments encamps encapsulant encapsulants encapsulate encapsulated encapsulates encapsulating encapsulation encapsulations encapsulator encapsulators encapsule encapsuled encapsules encapsuling encase encased encasement encasements encases encash encashable encashed encashes encashing encashment encasing encaustic encaustics enceinte enceintes enceladus encephala encephalic encephalitic encephalitis encephalitogen encephalitogenic encephalitogens encephalogram encephalograms encephalograph encephalographic encephalographically encephalographies encephalographs encephalography encephaloma encephalomas encephalomata encephalomyelitis encephalon encephalopathic encephalopathies encephalopathy encephalous enchain enchained enchaining enchainment enchainments enchains enchant enchanted enchanter enchanters enchanting enchantingly enchantment enchantments enchantress enchantresses enchants enchase enchased enchases enchasing enchilada enchiladas enchiridia enchiridion enchiridions encina encinas encipher enciphered encipherer encipherers enciphering encipherment encipherments enciphers encircle encircled encirclement encirclements encircles encircling enclasp enclasped enclasping enclasps enclave enclaves enclitic enclitics enclose enclosed encloses enclosing enclosure enclosures encode encoded encoder encoders encodes encoding encodings encomia encomiast encomiastic encomiastical encomiasts encomium encomiums encompass encompassed encompasses encompassing encompassment encompassments encore encored encores encoring encounter encountered encountering encounters encourage encouraged encouragement encouragements encourager encouragers encourages encouraging encouragingly encrimson encrimsoned encrimsoning encrimsons encroach encroached encroacher encroachers encroaches encroaching encroachment encroachments encrust encrustation encrustations encrusted encrusting encrusts encrypt encrypted encrypting encryption encryptions encrypts encumber encumbered encumbering encumbers encumbrance encumbrancer encumbrancers encumbrances encyclical encyclicals encyclopaedia encyclopaedias encyclopedia encyclopedias encyclopedic encyclopedically encyclopedism encyclopedisms encyclopedist encyclopedists encyst encystation encystations encysted encysting encystment encystments encysts end endamage endamaged endamages endamaging endameba endamebae endamebas endamoeba endanger endangered endangering endangerment endangerments endangers endarch endarterectomies endarterectomy endarteritis endbrain endbrains endear endeared endearing endearingly endearment endearments endears endeavor endeavored endeavorer endeavorers endeavoring endeavors ended endemic endemically endemicity endemics endemism endemisms ender endergonic endermic endermically enders endexine endexines endgame endgames ending endings endive endives endleaf endleaves endless endlessly endlessness endlong endmost endnote endnotes endobiotic endoblast endoblasts endocardia endocardial endocarditic endocarditis endocardium endocarp endocarpal endocarps endochondral endocrania endocranium endocrine endocrinologic endocrinological endocrinologist endocrinologists endocrinology endocytic endocytose endocytosed endocytoses endocytosing endocytosis endocytotic endoderm endodermal endodermis endoderms endodontia endodontic endodontically endodontics endodontist endodontists endoenzyme endoenzymes endoergic endogamous endogamy endogenic endogenous endogenously endogeny endolymph endolymphatic endolymphs endometria endometrial endometrioses endometriosis endometrium endomitosis endomitotic endomorph endomorphic endomorphism endomorphs endomorphy endonuclease endonucleases endoparasite endoparasites endoparasitic endoparasitism endopeptidase endopeptidases endophyte endophytes endophytic endoplasm endoplasmic endorphin endorphins endorsable endorse endorsed endorsee endorsees endorsement endorsements endorser endorsers endorses endorsing endorsor endorsors endoscope endoscopes endoscopic endoscopically endoscopies endoscopy endoskeletal endoskeleton endoskeletons endosmosis endosmotic endosmotically endosperm endospore endospores endosporia endosporium endostea endosteal endosteally endosteum endostyle endosulfan endosulfans endosymbiont endosymbiosis endosymbiotic endothecia endothecium endothelia endothelial endothelioid endothelioma endotheliomas endotheliomata endothelium endotherm endothermal endothermic endotherms endothermy endotoxic endotoxin endotoxins endotracheal endotrophic endow endowed endowing endowment endowments endows endpaper endpapers endpin endpins endplate endplates endplay endplayed endplaying endplays endpoint endpoints endrin endrins ends endsville endsvilles endue endued endues enduing endurable endurably endurance endure endured endures enduring enduringly enduringness enduro enduros endways endwise endymion enema enemas enemies enemy energetic energetically energetics energies energize energized energizer energizers energizes energizing energy enervate enervated enervates enervating enervation enervations enervative enervator enervators enface enfaced enfacement enfacements enfaces enfacing enfant enfants enfeeble enfeebled enfeeblement enfeeblements enfeebler enfeeblers enfeebles enfeebling enfeoff enfeoffed enfeoffing enfeoffment enfeoffments enfeoffs enfetter enfettered enfettering enfetters enfever enfevered enfevering enfevers enfield enfilade enfiladed enfilades enfilading enfin enflame enflamed enflames enflaming enfleurage enfleurages enflurane enfluranes enfold enfolded enfolder enfolders enfolding enfolds enforce enforceability enforceable enforced enforcement enforcements enforcer enforcers enforces enforcing enframe enframed enframement enframes enframing enfranchise enfranchised enfranchisement enfranchisements enfranchises enfranchising engage engaged engagement engagements engager engagers engages engaging engagingly engagé engarland engarlanded engarlanding engarlands engels engender engendered engenderer engenderers engendering engenders engild engilded engilding engilds engine engined engineer engineered engineering engineerings engineers enginery engines engining engird engirded engirding engirdle engirdled engirdles engirdling engirds engirt englacial england englander englanders english englished englishes englishing englishman englishmen englishness englishwoman englishwomen englut engluts englutted englutting engorge engorged engorgement engorgements engorges engorging engraft engrafted engrafting engraftment engraftments engrafts engrailed engrain engrained engraining engrains engram engrams engrave engraved engraver engravers engraves engraving engravings engross engrossed engrosser engrossers engrosses engrossing engrossingly engrossment engrossments engulf engulfed engulfing engulfment engulfments engulfs enhalo enhaloed enhaloes enhaloing enhance enhanced enhancement enhancements enhancer enhancers enhances enhancing enhancive enharmonic enharmonically enigma enigmas enigmatic enigmatical enigmatically enisle enisled enisles enisling eniwetok enjambement enjambements enjambment enjambments enjoin enjoinder enjoinders enjoined enjoiner enjoiners enjoining enjoinment enjoinments enjoins enjoy enjoyable enjoyableness enjoyably enjoyed enjoyer enjoyers enjoying enjoyment enjoyments enjoys enkephalin enkephalins enkindle enkindled enkindler enkindlers enkindles enkindling enlace enlaced enlacement enlacements enlaces enlacing enlarge enlargeable enlarged enlargement enlargements enlarger enlargers enlarges enlarging enlighten enlightened enlightener enlighteners enlightening enlightenment enlightenments enlightens enlist enlisted enlistee enlistees enlisting enlistment enlistments enlists enliven enlivened enlivener enliveners enlivening enlivenment enlivenments enlivens enmesh enmeshed enmeshes enmeshing enmeshment enmeshments enmities enmity ennead enneads ennoble ennobled ennoblement ennoblements ennobler ennoblers ennobles ennobling ennui enoch enoki enokidake enokidakes enokis enol enolase enolases enolic enological enologist enologists enology enols enormities enormity enormous enormously enormousness enosis enough enounce enounced enouncement enouncements enounces enouncing enow enphytotic enphytotics enplane enplaned enplanes enplaning enqueue enqueued enqueueing enqueues enqueuing enquire enquired enquires enquiries enquiring enquiry enrage enraged enragement enragements enrages enraging enrapt enrapture enraptured enrapturement enrapturements enraptures enrapturing enrich enriched enricher enrichers enriches enriching enrichment enrichments enrobe enrobed enrobes enrobing enroll enrolled enrollee enrollees enrolling enrollment enrollments enrolls enroot enrooted enrooting enroots ens ensample ensamples ensanguine ensanguined ensanguines ensanguining ensconce ensconced ensconces ensconcing ensemble ensembles enserf enserfed enserfing enserfment enserfs enshrine enshrined enshrinement enshrinements enshrines enshrining enshroud enshrouded enshrouding enshrouds ensiform ensign ensigns ensilage ensilaged ensilages ensilaging ensile ensiled ensiles ensiling enskied enskies ensky enskying enslave enslaved enslavement enslavements enslaver enslavers enslaves enslaving ensnare ensnared ensnarement ensnarements ensnarer ensnarers ensnares ensnaring ensnarl ensnarled ensnarling ensnarls ensorcel ensorceled ensorceling ensorcell ensorcelled ensorcelling ensorcellment ensorcells ensorcels ensoul ensouled ensouling ensouls ensphere ensphered enspheres ensphering enstatite enstatites ensue ensued ensues ensuing ensure ensured ensures ensuring enswathe enswathed enswathes enswathing entablature entablatures entablement entablements entail entailed entailer entailers entailing entailment entailments entails entameba entamebae entamebas entamoeba entamoebae entamoebas entangle entangled entanglement entanglements entangler entanglers entangles entangling entases entasis entebbe entelechies entelechy entendre entendres entente ententes enter enterable enteral enterally entered enteric entering enteritis enterobacteria enterobacterium enterobiasis enterococcal enterococci enterococcus enterocoele enterocoeles enterocolitis enterogastrone enterogastrones enterohepatitis enterokinase enterokinases enteron enterons enteropathies enteropathogen enteropathogenic enteropathogens enteropathy enterostomal enterostomies enterostomy enterotomies enterotomy enterotoxin enterotoxins enteroviral enterovirus enteroviruses enterprise enterpriser enterprisers enterprises enterprising enterprisingly enters entertain entertained entertainer entertainers entertaining entertainingly entertainment entertainments entertains enthalpies enthalpy enthrall enthralled enthralling enthrallingly enthrallment enthrallments enthralls enthrone enthroned enthronement enthronements enthrones enthroning enthuse enthused enthuses enthusiasm enthusiasms enthusiast enthusiastic enthusiastically enthusiasts enthusing enthymeme enthymemes entice enticed enticement enticements enticer enticers entices enticing enticingly entire entirely entireness entires entireties entirety entities entitle entitled entitlement entitlements entitles entitling entity entoblast entoblasts entoderm entodermal entodermic entoderms entoil entoiled entoiling entoils entomb entombed entombing entombment entombments entombs entomologic entomological entomologically entomologist entomologists entomology entomophagous entomophilous entomophily entomostracan entomostracans entourage entourages entozoa entozoan entozoic entr entr'acte entr'actes entrails entrain entrained entrainer entrainers entraining entrainment entrainments entrains entrance entranced entrancement entrancements entrances entranceway entranceways entrancing entrancingly entrant entrants entrap entrapment entrapments entrapped entrapping entraps entreat entreated entreaties entreating entreatingly entreatment entreatments entreats entreaty entrechat entrechats entrecôte entree entrees entremets entrench entrenched entrenches entrenching entrenchment entrenchments entrepreneur entrepreneurial entrepreneurialism entrepreneurism entrepreneurs entrepreneurship entrepreneurships entrepôt entresol entresols entries entropic entropically entropies entropy entrust entrusted entrusting entrustment entrusts entry entryway entryways entrée entrées entwine entwined entwinement entwinements entwines entwining entwist entwisted entwisting entwists enucleate enucleated enucleates enucleating enucleation enucleations enucleator enucleators enumerable enumerate enumerated enumerates enumerating enumeration enumerations enumerative enumerator enumerators enunciable enunciate enunciated enunciates enunciating enunciation enunciations enunciative enunciatively enunciator enunciators enure enured enures enuresis enuretic enuring envelop envelope enveloped enveloper envelopers envelopes enveloping envelopment envelopments envelops envenom envenomed envenoming envenoms enviable enviableness enviably envied envier enviers envies envious enviously enviousness environ environed environing environment environmental environmentalism environmentalist environmentalists environmentally environments environs envisage envisaged envisages envisaging envision envisioned envisioning envisions envoi envois envoy envoys envy envying envyingly enwheel enwheeled enwheeling enwheels enwind enwinding enwinds enwomb enwombed enwombing enwombs enwound enwrap enwrapped enwrapping enwraps enwreathe enwreathed enwreathes enwreathing enzootic enzootics enzymatic enzymatically enzyme enzymes enzymic enzymically enzymologist enzymologists enzymology eocene eohippus eolian eolith eolithic eoliths eon eonian eons eos eosin eosinophil eosinophilia eosinophilias eosinophilic eosinophilous eosinophils eosins epact epacts epaminondas eparchies eparchy epaulet epaulets epaulette epaulettes epee epees epeirogenic epeirogenically epeirogenies epeirogeny epentheses epenthesis epenthetic epergne epergnes epernay epexegesis epexegetic epexegetical epexegetically ephah ephahs ephebe ephebes ephebic ephedrine ephemera ephemerae ephemeral ephemerality ephemerally ephemeralness ephemerals ephemeras ephemerid ephemerides ephemerids ephemeris ephemeron ephemerons ephesian ephesians ephesus ephod ephods ephor ephori ephors ephraim epiblast epiblastic epiblasts epibolic epiboly epic epical epically epicalyces epicalyx epicalyxes epicanthi epicanthic epicanthus epicardia epicardial epicardium epicarp epicarps epicene epicenes epicenism epicenter epicenters epicentral epichlorohydrin epichlorohydrins epicondyle epicondyles epicotyl epicotyls epicritic epics epictetus epicure epicurean epicureanism epicureanisms epicureans epicures epicurism epicurisms epicurus epicuticle epicuticles epicycle epicycles epicyclic epicyclical epicyclically epicycloid epicycloidal epicycloids epidaurus epidemic epidemical epidemically epidemicity epidemics epidemiologic epidemiological epidemiologically epidemiologist epidemiologists epidemiology epidermal epidermic epidermis epidermoid epidiascope epidiascopes epididymal epididymides epididymis epidote epidotes epidotic epidural epidurals epifauna epifaunae epifaunal epifaunas epigastria epigastric epigastrium epigeal epigean epigene epigenesis epigenetic epigenous epigeous epiglottal epiglottic epiglottides epiglottis epiglottises epigone epigones epigonic epigonism epigram epigrammatic epigrammatically epigrammatism epigrammatisms epigrammatist epigrammatists epigrammatize epigrammatized epigrammatizer epigrammatizers epigrammatizes epigrammatizing epigrams epigraph epigrapher epigraphers epigraphic epigraphical epigraphically epigraphist epigraphists epigraphs epigraphy epigynies epigynous epigyny epilepsies epilepsy epileptic epileptics epileptogenic epileptoid epilog epilogs epilogue epilogues epimer epimeric epimers epimetheus epimysia epimysium epinastic epinasties epinasty epinephrine epineuria epineurial epineurium epipelagic epipetalous epiphanic epiphanies epiphanous epiphany epiphenomena epiphenomenal epiphenomenalism epiphenomenally epiphenomenon epiphyseal epiphyses epiphysial epiphysis epiphyte epiphytes epiphytic epiphytical epiphytically epiphytotic epiphytotics episcia episcias episcopacies episcopacy episcopal episcopalian episcopalians episcopally episcopate episcopates episcope episcopes episiotomies episiotomy episode episodes episodic episodically episomal episomally episome episomes epistases epistasis epistatic epistaxes epistaxis epistemic epistemically epistemological epistemologically epistemologist epistemologists epistemology epistle epistler epistlers epistles epistolary epistoler epistolers epistrophe epistyle epistyles epitaph epitaphial epitaphic epitaphs epitases epitasis epitaxial epitaxially epitaxies epitaxy epithalamia epithalamion epithalamium epithalamiums epithelia epithelial epithelialization epithelializations epithelialize epithelialized epithelializes epithelializing epithelioid epithelioma epitheliomas epitheliomata epitheliomatous epithelium epitheliums epithelization epithelizations epithelize epithelized epithelizes epithelizing epithet epithetic epithetical epithets epitome epitomes epitomic epitomical epitomize epitomized epitomizes epitomizing epizoa epizoic epizoism epizoisms epizoite epizoites epizoon epizootic epizootically epizootics epoch epochal epochally epochs epode epodes eponym eponymic eponymies eponymous eponyms eponymy epopee epopees epos eposes epoxide epoxides epoxied epoxies epoxy epoxying epsilon epsilons epsom epstein equability equable equableness equably equal equaled equaling equalitarian equalitarianism equalities equality equalization equalizations equalize equalized equalizer equalizers equalizes equalizing equalled equalling equally equals equanimities equanimity equate equated equates equating equation equational equationally equations equator equatorial equatorially equatorials equators equatorward equerries equerry equestrian equestrianism equestrians equestrianship equestrienne equestriennes equiangular equicaloric equid equidistance equidistant equidistantly equids equilateral equilateralism equilateralist equilateralists equilaterally equilaterals equilibrate equilibrated equilibrates equilibrating equilibration equilibrations equilibrator equilibrators equilibratory equilibria equilibrist equilibristic equilibrists equilibrium equilibriums equimolar equine equinely equines equinoctial equinoctials equinox equinoxes equip equipage equipages equipment equipoise equipoised equipoises equipoising equipollence equipollences equipollent equipollently equipollents equiponderance equiponderances equiponderant equiponderate equiponderated equiponderates equiponderating equipotent equipotential equipped equipping equiprobable equips equiseta equisetum equisetums equitability equitable equitableness equitably equitant equitation equities equity equivalence equivalences equivalencies equivalency equivalent equivalently equivalents equivocal equivocalities equivocality equivocally equivocalness equivocate equivocated equivocates equivocating equivocation equivocations equivocator equivocators equivoque equivoques er era eradicable eradicate eradicated eradicates eradicating eradication eradications eradicative eradicator eradicators eras erasabilities erasability erasable erase erased eraser erasers erases erasing erasmus erastian erastianism erastians erastus erasure erasures erat erato eratosthenes erbium ere erebus erect erectable erected erectile erectilities erectility erecting erection erections erectly erectness erector erectors erects erelong eremite eremites eremitic eremitical eremurus erenow erepsin erepsins erethism erethismic erethisms erewhile erfurt erg ergastic ergative ergo ergocalciferol ergocalciferols ergodic ergodicity ergograph ergographic ergographs ergometer ergometers ergometric ergonometric ergonomic ergonomically ergonomics ergonomist ergonomists ergonovine ergosterol ergosterols ergot ergotamine ergotamines ergotic ergotism ergotisms ergots ergs eric ericoid ericsson eridanus erie eries erigeron erigerons erin eristic eristics eritrea eritrean eritreans erlangen erlenmeyer ermine ermines erne ernes erode eroded erodes erodibility erodible eroding erogenous eroica eros erose erosely erosion erosional erosionally erosions erosive erosiveness erosivity erotic erotica erotically eroticism eroticist eroticists eroticization eroticizations eroticize eroticized eroticizes eroticizing erotics erotism erotisms erotize erotized erotizes erotizing erotogenic erotomania erotomanias err errancies errancy errand errands errant errantly errantries errantry errants errata erratas erratic erratical erratically erraticism erratics erratum erred errhine errhines erring erroneous erroneously erroneousness error errorless errors errs ersatz ersatzes erse erst erstwhile erucic eruct eructate eructated eructates eructating eructation eructations eructative eructed eructing eructs erudite eruditely eruditeness erudition erumpent erupt erupted eruptible erupting eruption eruptions eruptive eruptively erupts erymanthian erymanthos erymanthus eryngo eryngoes eryngos erysipelas erysipelatous erysipeloid erysipeloids erythema erythematic erythematous erythemic erythorbic erythrism erythrismal erythrisms erythrite erythrites erythroblast erythroblastic erythroblastoses erythroblastosis erythroblasts erythrocyte erythrocytes erythrocytic erythrocytometer erythrocytometers erythromycin erythropoiesis erythropoietic erythropoietin erythropoietins erzgebirge esau escadrille escadrilles escalade escaladed escalader escaladers escalades escalading escalate escalated escalates escalating escalation escalations escalator escalators escalatory escallop escalloped escalloping escallops escambia escapable escapade escapades escape escaped escapee escapees escapement escapements escaper escapers escapes escaping escapism escapisms escapist escapists escapologist escapologists escapology escargot escargots escarole escaroles escarp escarped escarping escarpment escarpments escarps eschalot eschalots eschar escharotic escharotics eschars eschatological eschatologically eschatologist eschatologists eschatology escheat escheatable escheatage escheatages escheated escheating escheats escher escherichia eschew eschewal eschewals eschewed eschewing eschews escolar escolars escort escorted escorting escorts escot escoted escoting escots escritoire escritoires escrow escrowed escrowing escrows escudo escudos esculent esculents escutcheon escutcheoned escutcheons esdraelon esdras esemplastic eserine eserines esfahan esker eskers eskimo eskimoan eskimos esophageal esophagi esophagus esoteric esoterica esoterically esotericism esotericisms espadrille espadrilles espalier espaliered espaliering espaliers esparto espartos español especial especially esperance esperances esperantist esperantists esperanto espial espials espied espiegle espies espionage esplanade esplanades espousal espousals espouse espoused espouser espousers espouses espousing espresso espressos esprit espy espying espíritu esquiline esquimau esquimaux esquire esquires ess essay essayed essayer essayers essaying essayist essayistic essayists essays essen essence essences essene essenes essenian essenic essenism essential essentialism essentialist essentialists essentiality essentially essentialness essentials essequibo essex essoin essoins essonite essonites est establish establishable established establisher establishers establishes establishing establishment establishmentarian establishmentarianism establishmentarians establishments estaminet estaminets estancia estancias estate estates esteem esteemed esteeming esteems ester esterase esterases esterification esterifications esterified esterifies esterify esterifying esters esther esthesia esthesias esthesiometer esthesiometers esthete esthetes esthetic esthetically esthetician estheticians estheticism esthetics estimable estimableness estimably estimate estimated estimates estimating estimation estimations estimative estimator estimators estival estivate estivated estivates estivating estivation estivations estonia estonian estonians estop estoppage estoppages estopped estoppel estoppels estopping estops estradiol estradiols estragon estragons estral estrange estranged estrangement estrangements estranger estrangers estranges estranging estray estrayed estraying estrays estremadura estremaduran estremadurans estriol estriols estrogen estrogenic estrogenically estrogens estrone estrones estrous estrual estrum estrums estrus estruses estuarial estuaries estuarine estuary esurience esuriency esurient esuriently et eta etagere etageres etamine etamines etatism etatisms etatist etc etcetera etceteras etch etched etcher etchers etches etching etchings eternal eternality eternalize eternalized eternalizes eternalizing eternally eternalness eternals eterne eternities eternity eternization eternizations eternize eternized eternizes eternizing etesian eth ethacrynic ethambutol ethambutols ethamine ethamines ethane ethanes ethanol ethanolamine ethanolamines ethanols ethelbert ethelred ethene ethenes ether ethereal ethereality etherealization etherealizations etherealize etherealized etherealizes etherealizing ethereally etherealness etheric etherification etherifications etherified etherifies etherify etherifying etherization etherizations etherize etherized etherizer etherizers etherizes etherizing ethernet ethernets ethers ethic ethical ethicalities ethicality ethically ethicalness ethicals ethician ethicians ethicist ethicists ethics ethinyl ethinyls ethion ethions ethiopia ethiopian ethiopians ethiopic ethiopics ethmoid ethmoidal ethmoids ethnarch ethnarchs ethnarchy ethnic ethnical ethnically ethnicities ethnicity ethnics ethnobotanical ethnobotanically ethnobotanist ethnobotanists ethnobotany ethnocentric ethnocentrically ethnocentricity ethnocentrism ethnographer ethnographers ethnographic ethnographical ethnographically ethnography ethnohistorian ethnohistorians ethnohistoric ethnohistorical ethnohistory ethnologic ethnological ethnologically ethnologist ethnologists ethnology ethnomethodologist ethnomethodologists ethnomethodology ethnomusicological ethnomusicologist ethnomusicologists ethnomusicology ethogram ethograms ethological ethologies ethologist ethologists ethology ethos ethoxy ethoxyl ethoxyls eths ethyl ethylamine ethylamines ethylate ethylated ethylates ethylating ethylation ethylations ethylene ethylenes ethylenic ethylic ethyls ethyne ethynes ethynyl ethynyls etiolate etiolated etiolates etiolating etiolation etiolations etiologic etiological etiologically etiologies etiologist etiologists etiology etiquette etiquettes etna eton etonian etonians etruria etrurian etrurians etruscan etruscans etude etudes etyma etymological etymologically etymologies etymologist etymologists etymologize etymologized etymologizes etymologizing etymology etymon etymons euboea eucaine eucaines eucalypt eucalypti eucalyptol eucalyptols eucalypts eucalyptus eucalyptuses eucharist eucharistic eucharistical eucharists euchre euchred euchres euchring euchromatic euchromatin euchromatins euclase euclases euclid euclidean eucrite eucrites eucritic eudaemonist eudaemonists eudemon eudemonism eudemonist eudemonistic eudemonistical eudemonists eudemons eugene eugenic eugenically eugenicist eugenicists eugenics eugenist eugenists eugenol eugenols euglena euglenas euglobulin euglobulins eugénie euhemerism euhemerisms euhemerist euhemeristic euhemeristically euhemerists euhemerize euhemerized euhemerizes euhemerizing eukaryote eukaryotes eukaryotic eulachon eulachons euler eulerian eulogia eulogies eulogist eulogistic eulogistically eulogists eulogium eulogiums eulogize eulogized eulogizer eulogizers eulogizes eulogizing eulogy eumenides eunuch eunuchism eunuchoid eunuchoids eunuchs euonymus euonymuses eupatrid eupatridae eupatrids eupepsia eupepsias eupeptic eupeptically euphemism euphemisms euphemist euphemistic euphemistically euphemists euphemize euphemized euphemizer euphemizers euphemizes euphemizing euphenic euphenics euphonic euphonically euphonies euphonious euphoniously euphoniousness euphonium euphoniums euphonize euphonized euphonizes euphonizing euphony euphorbia euphorbias euphoria euphoriant euphoriants euphorias euphoric euphorically euphotic euphrates euphrosyne euphuism euphuisms euphuist euphuistic euphuistical euphuistically euphuists euplastic euploid euploidies euploids euploidy eupnea eupneas eupneic eupneically eurasia eurasian eurasians eureka eurhythmic eurhythmics eurhythmy euripedes euripi euripidean euripides euripus euro eurobond eurobonds eurocentric eurocentrism eurocommunism eurocommunist eurocommunists eurocrat eurocratic eurocrats eurocurrencies eurocurrency eurodollar eurodollars euromarket euromarkets europa europe european europeanism europeanization europeanize europeanized europeanizes europeanizing europeans europium euros eurus euryale euryales eurybath eurybathic eurybaths eurydice euryhaline euryphagous eurypterid eurypterids eurytherm eurythermal eurytherms eurythmic eurythmics eurythmies eurythmy eurytopic eurytopicity eusebius eustachian eustasies eustasy eustatic eustele eusteles eutectic eutectics euterpe euthanasia euthanasic euthanize euthanized euthanizes euthanizing euthenics euthenist euthenists eutherian eutherians euthyroid eutrophic eutrophication eutrophications eutrophies eutrophy euxenite euxenites evacuant evacuants evacuate evacuated evacuates evacuating evacuation evacuations evacuative evacuator evacuators evacuee evacuees evadable evade evaded evader evaders evades evadible evading evaginate evaginated evaginates evaginating evagination evaginations evaluate evaluated evaluates evaluating evaluation evaluations evaluative evaluator evaluators evanesce evanesced evanescence evanescent evanescently evanesces evanescing evangel evangelic evangelical evangelicalism evangelically evangelicals evangelism evangelist evangelistic evangelistically evangelists evangelization evangelizations evangelize evangelized evangelizer evangelizers evangelizes evangelizing evangels evanton evaporability evaporable evaporate evaporated evaporates evaporating evaporation evaporations evaporative evaporatively evaporativity evaporator evaporators evaporite evaporites evaporitic evapotranspiration evasion evasions evasive evasively evasiveness eve evection evectional evections evelyn even evened evener eveners evenfall evenfalls evenhanded evenhandedly evenhandedness evening evenings eveningwear eveningwears evenki evenkis evenly evenness evens evensong evensongs event eventful eventfully eventfulness eventide eventides eventless events eventual eventualities eventuality eventually eventuate eventuated eventuates eventuating ever everbearing everblooming everest everglade everglades evergreen evergreens everlasting everlastingly everlastingness evermore eversible eversion eversions evert everted everting everts every everybody everybody's everyday everydayness everyman everymen everyone everyone's everyplace everything everywhere everywoman everywomen eves evict evicted evictee evictees evicting eviction evictions evictor evictors evicts evidence evidenced evidences evidencing evident evidential evidentially evidentiary evidently evil evildoer evildoers evildoing evildoings eviler evilest evilly evilness evils evince evinced evinces evincible evincing eviscerate eviscerated eviscerates eviscerating evisceration eviscerations evitable evocable evocation evocations evocative evocatively evocativeness evocator evocators evoke evoked evokes evoking evolute evolutes evolution evolutional evolutionarily evolutionary evolutionism evolutionist evolutionists evolutions evolvable evolve evolved evolvement evolvements evolves evolving evulsion evulsions evzone evzones ewe ewer ewers ewes ex exaampere exaamperes exabecquerel exabecquerels exabit exabits exabyte exabytes exacandela exacandelas exacerbate exacerbated exacerbates exacerbating exacerbation exacerbations exacoulomb exacoulombs exact exacta exactable exactas exacted exacter exacters exacting exactingly exactingness exaction exactions exactitude exactly exactness exactor exactors exacts exafarad exafarads exaggerate exaggerated exaggeratedly exaggeratedness exaggerates exaggerating exaggeration exaggerations exaggerative exaggerator exaggerators exaggeratory exagram exagrams exahenries exahenry exahenrys exahertz exajoule exajoules exakelvin exakelvins exalt exaltation exaltations exalted exaltedly exaltedness exalter exalters exalting exalts exalumen exalumens exalux exam examen examens exameter exameters examinable examinant examinants examination examinational examinations examine examined examinee examinees examiner examiners examines examining examole examoles example exampled examples exampling exams exanewton exanewtons exanimate exanthem exanthema exanthemas exanthemata exanthematic exanthematous exanthems exaohm exaohms exapascal exapascals exaradian exaradians exarch exarchal exarchate exarchates exarchies exarchs exarchy exasecond exaseconds exasiemens exasievert exasieverts exasperate exasperated exasperatedly exasperater exasperaters exasperates exasperating exasperatingly exasperation exasteradian exasteradians exatesla exateslas exavolt exavolts exawatt exawatts exaweber exawebers excalibur excaliburs excaudate excavate excavated excavates excavating excavation excavational excavations excavator excavators exceed exceeded exceeding exceedingly exceeds excel excelled excellence excellences excellencies excellency excellent excellently excelling excels excelsior except excepted excepting exception exceptionability exceptionable exceptionably exceptional exceptionality exceptionally exceptionalness exceptions exceptive excepts excerpt excerpted excerpter excerpters excerpting excerption excerptions excerptor excerptors excerpts excess excessed excesses excessing excessive excessively excessiveness exchange exchangeability exchangeable exchanged exchanger exchangers exchanges exchanging exchequer exchequers excimer excimers excipient excipients exciple exciples excisable excise excised exciseman excisemen excises excising excision excisions excitabilities excitability excitable excitableness excitably excitant excitants excitation excitations excitative excitatory excite excited excitedly excitement excitements exciter exciters excites exciting excitingly exciton excitonics excitons excitor excitors exclaim exclaimed exclaimer exclaimers exclaiming exclaims exclamation exclamations exclamatory exclave exclaves excludability excludable exclude excluded excluder excluders excludes excludible excluding exclusion exclusionary exclusionism exclusionist exclusionistic exclusionists exclusions exclusive exclusively exclusiveness exclusives exclusivity excogitate excogitated excogitates excogitating excogitation excogitations excogitative excommunicable excommunicate excommunicated excommunicates excommunicating excommunication excommunications excommunicative excommunicator excommunicators excommunicatory excoriate excoriated excoriates excoriating excoriation excoriations excoriator excoriators excrement excremental excrementitious excrements excrescence excrescences excrescencies excrescency excrescent excrescently excreta excretal excrete excreted excreter excreters excretes excreting excretion excretions excretory excruciate excruciated excruciates excruciating excruciatingly excruciation excruciations exculpable exculpate exculpated exculpates exculpating exculpation exculpations exculpatory excurrent excursion excursionist excursionists excursions excursive excursively excursiveness excursus excursuses excusable excusableness excusably excusatory excuse excused excuser excusers excuses excusing exec execrable execrableness execrably execrate execrated execrates execrating execration execrations execrative execrator execrators execratory execs executable executables executant executants execute executed executer executers executes executing execution executioner executioners executions executive executives executor executorial executors executorship executorships executory executrices executrix executrixes exedra exedrae exedras exegeses exegesis exegete exegetes exegetic exegetical exegetically exegetist exegetists exempla exemplar exemplarily exemplariness exemplarity exemplars exemplary exempli exemplifiable exemplification exemplifications exemplified exemplifier exemplifiers exemplifies exemplify exemplifying exemplum exempt exempted exemptible exempting exemption exemptions exempts exenterate exenterated exenterates exenterating exenteration exenterations exercisable exercise exercised exerciser exercisers exercises exercising exercitation exercitations exercycle exergonic exergue exergues exert exerted exerting exertion exertions exerts exes exeter exeunt exfoliate exfoliated exfoliates exfoliating exfoliation exfoliations exfoliative exfoliator exfoliators exhalant exhalants exhalation exhalations exhale exhaled exhalent exhalents exhales exhaling exhaust exhausted exhaustedly exhauster exhausters exhaustibility exhaustible exhausting exhaustingly exhaustion exhaustive exhaustively exhaustiveness exhaustivity exhaustless exhaustlessly exhaustlessness exhausts exhibit exhibited exhibiter exhibiters exhibiting exhibition exhibitioner exhibitioners exhibitionism exhibitionist exhibitionistic exhibitionists exhibitions exhibitive exhibitively exhibitor exhibitors exhibitory exhibits exhilarant exhilarants exhilarate exhilarated exhilarates exhilarating exhilaratingly exhilaration exhilarative exhilarator exhilarators exhort exhortation exhortations exhortative exhortatory exhorted exhorter exhorters exhorting exhorts exhumation exhumations exhume exhumed exhumer exhumers exhumes exhuming exigence exigences exigencies exigency exigent exigently exiguities exiguity exiguous exiguously exiguousness exile exiled exiles exilian exilic exiling eximious exine exines exist existed existence existences existent existential existentialism existentialist existentialistic existentialistically existentialists existentially existents existing exists exit exited exiting exits exobiological exobiologist exobiologists exobiology exocarp exocarps exocet exocets exocrine exocyclic exocytose exocytosed exocytoses exocytosing exocytosis exocytotic exodermis exodontia exodontias exodontics exodontist exodontists exodus exoduses exoenzyme exoenzymes exoergic exogamic exogamies exogamous exogamy exogenous exogenously exon exonerate exonerated exonerates exonerating exoneration exonerations exonerative exonic exons exonuclease exonucleases exopeptidase exopeptidases exophthalmic exophthalmos exorbitance exorbitances exorbitant exorbitantly exorcise exorcised exorciser exorcisers exorcises exorcising exorcism exorcisms exorcist exorcistic exorcistical exorcists exorcize exorcized exorcizes exorcizing exordia exordial exordium exordiums exoskeletal exoskeleton exoskeletons exosmosis exosmotic exosphere exospheres exospheric exospore exospores exosporia exosporium exostoses exostosis exoteric exoterically exothermal exothermally exothermic exothermically exotic exotica exotically exoticism exoticisms exoticness exotics exotism exotisms exotoxin exotoxins expand expandable expanded expander expanders expanding expandor expandors expands expanse expanses expansibility expansible expansile expansion expansional expansionary expansionism expansionist expansionistic expansionists expansions expansive expansively expansiveness expansivity expatiate expatiated expatiates expatiating expatiation expatiations expatiatory expatriate expatriated expatriates expatriating expatriation expatriations expect expectable expectably expectance expectances expectancies expectancy expectant expectantly expectants expectation expectational expectations expectative expected expectedly expectedness expecting expectorant expectorants expectorate expectorated expectorates expectorating expectoration expectorations expectorator expectorators expects expedience expediences expediencies expediency expedient expediential expedientially expediently expedients expedite expedited expediter expediters expedites expediting expedition expeditionary expeditions expeditious expeditiously expeditiousness expeditor expeditors expel expellable expellant expelled expellee expellees expeller expellers expelling expels expend expendability expendable expendables expendably expended expender expenders expending expenditure expenditures expends expense expensed expenses expensing expensive expensively expensiveness experience experienced experiencer experiencers experiences experiencing experiential experientialism experientially experiment experimental experimentalism experimentalist experimentalists experimentally experimentation experimentations experimented experimenter experimenters experimenting experiments expert experted experting expertise expertism expertly expertness experts expiable expiate expiated expiates expiating expiation expiations expiator expiators expiatory expiration expirations expiratory expire expired expires expiries expiring expiry explain explainable explained explainer explainers explaining explains explanation explanations explanative explanatively explanatorily explanatory explant explantation explantations explanted explanting explants expletive expletives expletory explicable explicably explicate explicated explicates explicating explication explications explicative explicatively explicatives explicator explicators explicatory explicit explicitly explicitness explode exploded exploder exploders explodes exploding exploit exploitability exploitable exploitation exploitations exploitative exploitatively exploited exploiter exploiters exploiting exploitive exploitively exploits exploration explorational explorations explorative exploratively exploratory explore explored explorer explorers explores exploring explosion explosions explosive explosively explosiveness explosives expo exponent exponential exponentially exponentiate exponentiated exponentiates exponentiating exponentiation exponentiations exponents export exportability exportable exportation exportations exported exporter exporters exporting exports expos expose exposed exposer exposers exposes exposing exposit exposited expositing exposition expositional expositions expositive expositor expositors expository exposits expostulate expostulated expostulates expostulating expostulation expostulations expostulative expostulator expostulators expostulatory exposure exposures exposé exposés expound expounded expounder expounders expounding expounds express expressage expressed expresser expressers expresses expressible expressing expression expressional expressionism expressionist expressionistic expressionistically expressionists expressionless expressionlessly expressionlessness expressions expressive expressively expressiveness expressivities expressivity expressly expressway expressways expropriate expropriated expropriates expropriating expropriation expropriations expropriator expropriators expropriatory expulse expulsed expulses expulsing expulsion expulsions expulsive expunction expunctions expunge expunged expunger expungers expunges expunging expurgate expurgated expurgates expurgating expurgation expurgations expurgator expurgatorial expurgators expurgatory exquisite exquisitely exquisiteness exsanguinate exsanguinated exsanguinates exsanguinating exsanguination exsanguinations exsanguine exscind exscinded exscinding exscinds exsert exserted exsertile exserting exsertion exsertions exserts exsiccate exsiccated exsiccates exsiccating exsiccation exsiccations exsiccative exsiccator exsiccators exstipulate extant extemporal extemporally extemporaneity extemporaneous extemporaneously extemporaneousness extemporarily extemporary extempore extemporization extemporizations extemporize extemporized extemporizer extemporizers extemporizes extemporizing extend extendability extendable extended extendedly extendedness extender extenders extendibility extendible extending extends extensibility extensible extensile extension extensional extensionality extensionally extensions extensities extensity extensive extensively extensiveness extenso extensometer extensometers extensor extensors extent extents extenuate extenuated extenuates extenuating extenuatingly extenuation extenuations extenuative extenuatives extenuator extenuators extenuatory exterior exteriority exteriorization exteriorizations exteriorize exteriorized exteriorizes exteriorizing exteriorly exteriors exterminate exterminated exterminates exterminating extermination exterminations exterminative exterminator exterminators exterminatory extermine extermined extermines extermining extern external externalism externalisms externalist externalists externalities externality externalization externalizations externalize externalized externalizes externalizing externally externals externe externes externs externship externships exteroceptive exteroceptor exteroceptors exterritorial exterritoriality exterritorially extinct extinction extinctions extinctive extinguish extinguishable extinguished extinguisher extinguishers extinguishes extinguishing extinguishment extinguishments extirpate extirpated extirpates extirpating extirpation extirpations extirpative extirpator extirpators extol extolled extoller extollers extolling extolment extols extort extorted extorter extorters extorting extortion extortionary extortionate extortionately extortioner extortioners extortionist extortionists extortions extortive extorts extra extracellular extracellularly extrachromosomal extracode extracodes extraconstitutional extracorporeal extracorporeally extracranial extract extractability extractable extracted extractible extracting extraction extractions extractive extractively extractives extractor extractors extracts extracurricular extraditable extradite extradited extradites extraditing extradition extraditions extrados extradoses extragalactic extrahepatic extrajudicial extrajudicially extralegal extralegally extralimital extralinguistic extralinguistically extralities extrality extramarital extramundane extramural extramurally extramusical extraneous extraneously extraneousness extranuclear extraocular extraordinaire extraordinarily extraordinariness extraordinary extrapolate extrapolated extrapolates extrapolating extrapolation extrapolations extrapolative extrapolator extrapolators extrapyramidal extras extrasensory extrasolar extrasystole extrasystoles extraterrestrial extraterrestrials extraterritorial extraterritorialities extraterritoriality extraterritorially extrauterine extravagance extravagances extravagancies extravagancy extravagant extravagantly extravagantness extravaganza extravaganzas extravagate extravagated extravagates extravagating extravagation extravagations extravasate extravasated extravasates extravasating extravasation extravasations extravascular extravehicular extraversion extravert extraverted extraverting extraverts extrema extreme extremely extremeness extremes extremis extremism extremist extremists extremities extremity extremum extricable extricate extricated extricates extricating extrication extrications extrinsic extrinsically extrorse extroversion extroversive extroversively extrovert extroverted extroverts extrudability extrudable extrude extruded extruder extruders extrudes extruding extrusion extrusions extrusive exuberance exuberant exuberantly exuberate exuberated exuberates exuberating exudate exudates exudation exudations exudative exude exuded exudes exuding exult exultance exultancy exultant exultantly exultation exulted exulting exultingly exults exurb exurban exurbanite exurbanites exurbia exurbias exurbs exuviae exuvial exuviate exuviated exuviates exuviating exuviation exuviations exxon eyas eyases eye eyeball eyeballed eyeballing eyeballs eyebolt eyebolts eyebright eyebrights eyebrow eyebrows eyecup eyecups eyed eyedness eyednesses eyedropper eyedropperful eyedroppers eyeful eyefuls eyeglass eyeglasses eyehole eyeholes eyehook eyehooks eyeing eyelash eyelashes eyeless eyelet eyelets eyelid eyelids eyelift eyelifts eyelike eyeliner eyeliners eyepiece eyepieces eyepopper eyepoppers eyepopping eyer eyers eyes eyeshade eyeshades eyeshot eyeshots eyesight eyesights eyesore eyesores eyespot eyespots eyestalk eyestalks eyestrain eyestrings eyeteeth eyetooth eyewash eyewashes eyewear eyewink eyewinks eyewitness eyewitnesses eying eyra eyras eyre eyres eyrir ezekias ezekiel ezra f fa fab fabergé fabian fabianism fabianist fabianists fabians fabius fable fabled fabler fablers fables fabliau fabliaux fabling fabre fabric fabricability fabricable fabricant fabricants fabricate fabricated fabricates fabricating fabrication fabrications fabricator fabricators fabrics fabular fabulate fabulated fabulates fabulating fabulation fabulations fabulator fabulators fabulist fabulists fabulous fabulously fabulousness facade facades face faceable facecloth facecloths faced facedown facedowns faceless facelessness facelift facelifts facemask facemasks faceplate faceplates facer facers faces facet facete faceted facetiae facetious facetiously facetiousness facets facetted faceup facia facial facially facials facias facie facies facile facilely facileness facilitate facilitated facilitates facilitating facilitation facilitative facilitator facilitators facilitatory facilities facility facing facings facsimile facsimiles fact facticity faction factional factionalism factionalize factionalized factionalizes factionalizing factionally factions factious factiously factiousness factitious factitiously factitiousness factitive factitively facto factoid factoidal factoids factor factorability factorable factorage factorages factored factorial factorials factories factoring factorings factorization factorizations factorize factorized factorizes factorizing factors factorship factory factotum factotums facts factual factualism factualist factualists factuality factually factualness facture factures facula faculae facultative facultatively faculties faculty fad faddish faddishly faddishness faddism faddisms faddist faddists faddy fade fadeaway fadeaways faded fadeless fadelessly fadeout fadeouts fader faders fades fading fadings fado fados fads faecal faeces faena faenas faerie faeries faeroe faeroes faeroese faery fafnir fag fagged fagging faggot faggoted faggoting faggots fagin fagins fagot fagoted fagoting fagotings fagots fags fahrenheit faience faiences fail failed failing failingly failings faille failles fails failsafe failure failures fain faint fainted fainter fainters faintest fainthearted faintheartedly faintheartedness fainting faintish faintishness faintly faintness faints fainéant fainéants fair fairbanks faire faired fairer fairest fairfax fairgoer fairgoers fairground fairgrounds fairhaven fairies fairing fairings fairish fairishly fairlead fairleader fairleaders fairleads fairly fairness fairs fairwater fairwaters fairway fairways fairy fairyism fairyisms fairyland fairylands fairylike fairytale fairytales faisalabad fait faith faithful faithfully faithfulness faithfuls faithless faithlessly faithlessness faiths faitour faitours faits fajita fajitas fake faked faker fakeries fakers fakery fakes faking fakir fakirs falafel falange falangism falangist falangists falasha falashas falcate falcated falces falchion falchions falciform falciparum falcon falconer falconers falconet falconets falconoid falconry falcons falderal falderals faldstool faldstools faliscan faliscans falkland falklands fall fallacies fallacious fallaciously fallaciousness fallacy fallal fallalery fallals fallback fallbacks fallboard fallboards fallen faller fallers fallfish fallfishes fallibility fallible fallibleness fallibly falling fallings falloff falloffs fallopian fallout fallouts fallow fallowed fallowing fallowness fallows falls falmouth false falsehood falsehoods falsely falseness falser falsest falsetto falsettos falsie falsies falsifiability falsifiable falsification falsifications falsified falsifier falsifiers falsifies falsify falsifying falsities falsity falstaff falstaffian falster faltboat faltboats falter faltered falterer falterers faltering falteringly falters falx famagusta fame famed fames familial familiar familiarities familiarity familiarization familiarizations familiarize familiarized familiarizer familiarizers familiarizes familiarizing familiarly familiarness familiars families familism familistic famille family famine famines faming famish famished famishes famishing famishment famishments famous famously famousness famuli famulus fan fanac fanacs fanatic fanatical fanatically fanaticalness fanaticism fanaticize fanaticized fanaticizes fanaticizing fanatics fancied fancier fanciers fancies fanciest fanciful fancifully fancifulness fancily fanciness fancy fancying fancywork fandangle fandangles fandango fandangos fandom fandoms fane fanes fanfare fanfares fanfaronade fanfaronades fanfold fanfolds fang fanged fangs fanion fanions fanjet fanjets fanlight fanlights fanlike fanned fanner fanners fannies fanning fanny fanout fans fantabulous fantail fantailed fantails fantasia fantasias fantasie fantasied fantasies fantasist fantasists fantasize fantasized fantasizer fantasizes fantasizing fantasm fantasms fantast fantastic fantastical fantasticality fantastically fantasticalness fantasticate fantasticated fantasticates fantasticating fantastication fantastications fantastico fantasticoes fantasts fantasy fantasying fantasyland fantasylands fante fanti fantoccini fantod fantods fantom fantoms fanwise fanwort fanworts fanzine fanzines far farad faradaic faraday faradays faradic faradism faradisms faradization faradizations faradize faradized faradizes faradizing farads farandole farandoles faraway farce farced farces farceur farceurs farci farcical farcicality farcically farcicalness farcie farcing farcy fard farded fardel fardels farding fards fare farebeat farebeaten farebeater farebeaters farebeating farebeats fared farer farers fares farewell farewelled farewelling farewells farfal farfals farfel farfels farfetched farfetchedness faridabad farina farinaceous farinas faring farinha farinhas farinose farkleberries farkleberry farl farls farm farmability farmable farmed farmer farmers farmhand farmhands farmhouse farmhouses farming farmington farmland farmlands farms farmstead farmsteads farmwoman farmwomen farmworker farmworkers farmyard farmyards farnese faro faroe faroes faroese farolito farolitos faros farouche farraginous farrago farragoes farrier farrieries farriers farriery farrow farrowed farrowing farrows farseeing farsi farsighted farsightedly farsightedness farsistan fart farted farther farthermost farthest farthing farthingale farthingales farthings farting farts fasces fascia fasciae fascial fascias fasciate fasciated fasciation fasciations fascicle fascicled fascicles fascicular fascicularly fasciculate fasciculated fasciculately fasciculation fasciculations fascicule fascicules fasciculi fasciculus fascinate fascinated fascinates fascinating fascinatingly fascination fascinations fascinator fascinators fascine fascines fascioliases fascioliasis fascism fascist fascisti fascistic fascistically fascists fash fashed fashes fashing fashion fashionability fashionable fashionableness fashionables fashionably fashioned fashioner fashioners fashioning fashionmonger fashionmongers fashions fast fastback fastbacks fastball fastballs fasted fasten fastened fastener fasteners fastening fastenings fastens faster fastest fastidious fastidiously fastidiousness fastigiate fastigiated fastigiately fastigium fastigiums fasting fastness fastnesses fasts fastuous fat fata fatal fatale fatales fatalism fatalist fatalistic fatalistically fatalists fatalities fatality fatally fatback fate fated fateful fatefully fatefulness fates fathead fatheaded fatheadedly fatheadedness fatheads father fathered fatherhood fathering fatherland fatherlands fatherless fatherlessness fatherlike fatherliness fatherly fathers fathom fathomable fathomed fathometer fathoming fathomless fathomlessly fathomlessness fathoms fatidic fatidical fatigabilities fatigability fatigable fatigue fatigued fatigues fatiguing fatiguingly fatima fatimid fatimids fatimite fatimites fating fatless fatling fatlings fatly fatness fats fatso fatsoes fatstock fatted fatten fattened fattener fatteners fattening fattens fatter fattest fattier fatties fattiest fattily fattiness fatting fattish fattishness fatty fatuities fatuity fatuous fatuously fatuousness fatuus fatwood fatwoods faubourg faubourgs faucal fauces faucet faucets faucial faugh faulkner faulknerian fault faulted faultfinder faultfinders faultfinding faultfindings faultier faultiest faultily faultiness faulting faultless faultlessly faultlessness faults faulty faun fauna faunae faunal faunally faunas faunistic faunistically fauns faunus faust faustian faustus faut faute fauteuil fauteuils fauve fauves fauvism fauvist fauvists faux favela favelas faveolate favonian favor favorable favorableness favorably favored favoredness favorer favorers favoring favoringly favorite favorites favoritism favors favus favuses fawkes fawn fawned fawner fawners fawning fawningly fawns fawny fax faxed faxes faxing fay fayalite fayalites fayed fayetteville faying fays faze fazed fazes fazing façade façades façadism faïence faïences fealties fealty fear feared fearer fearers fearful fearfully fearfulness fearing fearless fearlessly fearlessness fears fearsome fearsomely fearsomeness feasibility feasible feasiblefeasters feasibleness feasibly feast feasted feaster feasters feasting feasts feat feater featest feather featherbed featherbedded featherbedding featherbeddings featherbeds featherbone featherbones featherbrain featherbrained featherbrains feathered featheredge featheredged featheredges featherhead featherheaded featherheads featheriness feathering featherings featherless feathers featherstitch featherstitched featherstitches featherstitching featherweight featherweights feathery featly feats feature featured featureless features featuring feaze feazed feazes feazing febricity febrifacient febrifacients febrific febrifuge febrifuges febrile februaries february februarys fecal feces feckless fecklessly fecklessness feckly feculence feculent fecund fecundate fecundated fecundates fecundating fecundation fecundations fecundity fed fedayee fedayeen federacies federacy federal federalism federalist federalists federalization federalizations federalize federalized federalizes federalizing federally federate federated federates federating federation federations federative federatively fedora fedoras feds fee feeble feebleminded feeblemindedly feeblemindedness feebleness feebler feeblest feeblish feebly feed feedback feedbag feedbags feedbox feedboxes feeder feeders feedhole feedholes feeding feedings feedlot feedlots feeds feedstock feedstuff feedthrough feedthroughs feeing feel feeler feelers feeling feelingly feelingness feelings feels fees feet feetfirst feeze feezes fehling feign feigned feigner feigners feigning feigns feijoada feint feinted feinting feints feirie feist feistier feistiest feistiness feists feisty felafel feldspar feldspars feldspathic felicific felicitate felicitated felicitates felicitating felicitation felicitations felicitator felicitators felicities felicitous felicitously felicitousness felicity felid felids feline felinely felineness felines felinities felinity felix fell fellable fellah fellaheen fellahin fellate fellated fellates fellating fellatio fellation fellations fellatios fellator fellators felled feller fellers fellies felling fellness felloe felloes fellow fellowly fellowman fellowmen fellows fellowship fellowships fells felly felon felones felonies felonious feloniously feloniousness felonries felonry felons felony felsic felsite felsites felsitic felspar felspars felt felted felting feltings felts felty felucca feluccas felwort felworts female femaleness females feme femes feminine femininely feminineness feminines femininities femininity feminism feminist feministic feminists feminity feminization feminizations feminize feminized feminizes feminizing femme femmes femora femoral femtoampere femtoamperes femtobecquerel femtobecquerels femtocandela femtocandelas femtocoulomb femtocoulombs femtofarad femtofarads femtogram femtograms femtohenries femtohenry femtohenrys femtohertz femtojoule femtojoules femtokelvin femtokelvins femtolumen femtolumens femtolux femtometer femtometers femtomole femtomoles femtonewton femtonewtons femtoohm femtoohms femtopascal femtopascals femtoradian femtoradians femtosecond femtoseconds femtosiemens femtosievert femtosieverts femtosteradian femtosteradians femtotesla femtoteslas femtovolt femtovolts femtowatt femtowatts femtoweber femtowebers femur femurs fen fence fenced fenceless fencelessness fencer fencerow fencerows fencers fences fencing fend fended fender fenders fending fends fenestra fenestrae fenestral fenestrate fenestrated fenestration fenestrations fenfluramine feng fenian fenianism fenians fennec fennecs fennel fenny fens fentanyl fentanyls fenugreek fenuron fenurons feoffee feoffees feoffer feoffers feoffment feoffments feoffor feoffors fer feral ferbam ferbams ferdinand fere feres feretories feretory feria feriae ferial ferias ferine ferity fermanagh fermat fermata fermatas ferment fermentability fermentable fermentation fermentations fermentative fermented fermenter fermenters fermenting ferments fermi fermion fermions fermis fermium fern ferneries fernery fernier ferniest fernlike ferns ferny ferocious ferociously ferociousness ferocity ferrara ferrate ferrates ferredoxin ferredoxins ferret ferreted ferreter ferreters ferreting ferretings ferrets ferrety ferriage ferriages ferric ferricyanide ferricyanides ferried ferries ferriferous ferris ferrite ferrites ferritic ferritin ferritins ferroalloy ferroalloys ferroconcrete ferrocyanide ferrocyanides ferroelectric ferroelectricity ferroelectrics ferromagnesian ferromagnet ferromagnetic ferromagnetism ferromagnets ferromanganese ferrosilicon ferrosilicons ferrotype ferrotypes ferrous ferruginous ferrule ferruled ferrules ferruling ferry ferryboat ferryboats ferrying ferryman ferrymen fertile fertilely fertileness fertilities fertility fertilizable fertilization fertilizational fertilizations fertilize fertilized fertilizer fertilizers fertilizes fertilizing ferula ferulas ferule feruled ferules ferulic feruling fervencies fervency fervent fervently ferventness fervid fervidity fervidly fervidness fervor fervors fescennine fescue fescues fess fesse fessed fesses fessing fest festal festally fester festered festering festers festinate festinated festinately festinates festinating festival festivalgoer festivalgoers festivals festive festively festiveness festivities festivity festoon festooned festooneries festoonery festooning festoons fests festschrift festschriften festschrifts feta fetal fetch fetched fetcher fetchers fetches fetching fetchingly fete feted feterita feteritas fetes fetich fetiches fetichism feticidal feticide feticides fetid fetidly fetidness feting fetish fetishes fetishism fetishist fetishistic fetishistically fetishists fetishize fetishized fetishizes fetishizing fetlock fetlocks fetologist fetologists fetology fetoprotein fetoproteins fetor fetors fetoscope fetoscopes fetoscopy fetter fetterbush fetterbushes fettered fettering fetters fettle fettled fettles fettling fettlings fettuccine fetus fetuses feu feud feudal feudalism feudalist feudalistic feudalists feudalities feudality feudalization feudalizations feudalize feudalized feudalizes feudalizing feudally feudatories feudatory feuded feuding feudist feudists feuds feuilleton feuilletonism feuilletonist feuilletonistic feuilletonists feuilletons fever fevered feverfew feverfews fevering feverish feverishly feverishness feverous fevers feverweed feverweeds feverwort feverworts few fewer fewest fewness fewtrils fey feyly feyness feynman fez fezzes fiacre fiacres fiancee fiancees fianchetti fianchetto fianchettoed fianchettoing fianchettos fiancé fiancée fiancées fiancés fiaschi fiasco fiascoes fiascos fiat fiats fib fibbed fibber fibbers fibbing fiber fiberboard fibered fiberfill fiberglass fiberization fiberizations fiberize fiberized fiberizes fiberizing fibers fiberscope fiberscopes fibonacci fibranne fibrannes fibril fibrillar fibrillary fibrillate fibrillated fibrillates fibrillating fibrillation fibrillations fibrillose fibrils fibrin fibrinogen fibrinogenic fibrinogenically fibrinogenous fibrinogens fibrinoid fibrinoids fibrinolyses fibrinolysin fibrinolysins fibrinolysis fibrinolytic fibrinous fibroblast fibroblastic fibroblasts fibrocartilage fibrocartilages fibrocystic fibroid fibroids fibroin fibroins fibroma fibromas fibromata fibromatous fibronectin fibroplasia fibroplastic fibroses fibrosis fibrositis fibrositises fibrotic fibrous fibrously fibrousness fibrovascular fibs fibula fibulae fibular fibulas fiche fiches fichtelgebirge fichu fichus ficin fickle fickleness fickler ficklest fickly fico ficoes fictile fiction fictional fictionality fictionalization fictionalizations fictionalize fictionalized fictionalizes fictionalizing fictionally fictioneer fictioneering fictioneers fictionist fictionists fictionization fictionizations fictionize fictionized fictionizes fictionizing fictions fictitious fictitiously fictitiousness fictive fictively fictiveness ficus ficuses fid fiddle fiddleback fiddled fiddlehead fiddleheads fiddler fiddlers fiddles fiddlestick fiddlesticks fiddling fide fideism fideist fideistic fideists fidelis fidelities fidelity fides fidge fidged fidges fidget fidgeted fidgetiness fidgeting fidgets fidgety fidging fido fidos fids fiducial fiducially fiduciaries fiduciary fidus fie fief fiefdom fiefdoms fiefs field fielded fielder fielders fieldfare fieldfares fielding fieldpiece fieldpieces fields fieldsman fieldsmen fieldstone fieldstrip fieldstripped fieldstripping fieldstrips fieldwork fieldworker fieldworkers fiend fiendish fiendishly fiendishness fiends fierce fiercely fierceness fiercer fiercest fierier fieriest fierily fieriness fiery fiesole fiesta fiestas fife fifer fifers fifes fifo fifteen fifteenfold fifteens fifteenth fifteenths fifth fifthly fifths fifties fiftieth fiftieths fifty fiftyfold fiftyish fig figaro fight fightability fightable fighter fighters fighting fightingly fights figment figments figs figural figurant figurants figuration figurations figurative figuratively figurativeness figure figured figurehead figureheads figurer figurers figures figurine figurines figuring figwort figworts fiji fijian fijians fila filament filamentary filamentous filaments filar filaree filarees filaria filariae filarial filarian filariases filariasis filariid filariids filature filatures filbert filberts filch filched filcher filchers filches filching filchner file filed filefish filefishes filename filenames filer filers files filet filets filial filially filiate filiated filiates filiating filiation filiations filibuster filibustered filibusterer filibusterers filibustering filibusters filiform filigree filigreed filigreeing filigrees filing filings filiopietistic filipina filipinas filipino filipinos filippo fill fille filled filler fillers fillet filleted filleting fillets fillies filling fillings fillip filliped filliping fillips fills filly fillér fillérs film filmcard filmcards filmdom filmed filmgoer filmgoers filmgoing filmic filmically filmier filmiest filmily filminess filming filmland filmmaker filmmakers filmmaking filmographer filmographers filmographies filmography films filmset filmsets filmsetter filmsetters filmsetting filmsettings filmstrip filmstrips filmy filoplume filoplumes filose filovirus filoviruses fils filter filterability filterable filtered filterer filterers filtering filterless filters filth filthier filthiest filthily filthiness filthy filtrable filtrate filtrated filtrates filtrating filtration filtrations filum filé fimbria fimbriae fimbrial fimbriate fimbriated fimbriation fimbriations fin finable finagle finagled finagler finaglers finagles finagling final finale finales finalist finalists finalities finality finalization finalizations finalize finalized finalizer finalizers finalizes finalizing finally finals finance financeable financed finances financial financially financials financier financiers financing finback finbacks finca fincas finch finches find findable finder finders finding findings finds fine fineable fined finely fineness finer fineries finery fines finespun finesse finessed finesses finessing finest finfish finfishes fingal finger fingerboard fingerboards fingerbreadth fingerbreadths fingered fingerer fingerers fingering fingerings fingerless fingerlike fingerling fingerlings fingernail fingernails fingerpick fingerpicked fingerpicker fingerpickers fingerpicking fingerpicks fingerpost fingerposts fingerprint fingerprinted fingerprinting fingerprints fingers fingerspell fingerspelled fingerspelling fingerspells fingertip fingertips finial finials finical finically finicalness finickier finickiest finickiness finicking finicky fining finis finish finished finisher finishers finishes finishing finisterre finite finitely finiteness finites finitude finitudes fink finked finking finks finland finlander finlanders finlandization finlandize finlandized finlandizes finlandizing finlike finn finnan finnbogadóttir finned finnic finnier finniest finning finnish finns finny finocchio finochio finochios fins finsteraarhorn fiord fiords fipple fipples fir firdausi firdusi fire fireable firearm firearms fireball fireballs firebase firebases firebird firebirds fireboard fireboards fireboat fireboats firebomb firebombed firebomber firebombers firebombing firebombs firebox fireboxes firebrand firebrands firebrat firebrats firebreak firebreaks firebrick firebricks firebug firebugs fireclay fireclays firecracker firecrackers fired firedamp firedog firedogs firedrake firedrakes firefighter firefighters firefighting firefights fireflies fireflood fireflooding firefloodings firefloods firefly fireguard fireguards firehouse firehouses fireless firelight firelock firelocks fireman firemen firenze fireplace fireplaces fireplug fireplugs firepower fireproof fireproofed fireproofing fireproofs firer firers fires fireside firesides firestone firestones firestorm firestorms firetrap firetraps firewall firewalled firewalling firewalls firewater fireweed fireweeds firewood firework fireworks firing firings firkin firkins firm firma firmament firmamental firmaments firmed firmer firmest firming firmly firmness firms firmware firn firns firozabad firry firs first firstborn firstborns firstfruits firsthand firstling firstlings firstly firsts firth firths fisc fiscal fiscally fiscs fish fishability fishable fishbone fishbones fishbowl fishbowls fishcake fishcakes fished fisher fisheries fisherman fishermen fishers fishery fishes fisheye fisheyes fishgig fishgigs fishhook fishhooks fishier fishiest fishily fishiness fishing fishings fishless fishlike fishmeal fishmonger fishmongers fishnet fishnets fishplate fishplates fishpond fishponds fishtail fishtailed fishtailing fishtails fishway fishways fishwife fishwives fishy fissile fissility fission fissionability fissionable fissional fissioned fissioning fissions fissipalmate fissiparous fissiparously fissiparousness fissiped fissipeds fissure fissured fissures fissuring fist fisted fistfight fistfights fistful fistfuls fistic fisticuffer fisticuffers fisticuffs fisting fistnote fistnotes fists fistula fistulae fistular fistulas fistulous fit fitch fitches fitchet fitchets fitchew fitchews fitful fitfully fitfulness fitly fitment fitments fitness fits fitted fitter fitters fittest fitting fittingly fittingness fittings fitzgerald five fivefold fiver fivers fives fix fixable fixate fixated fixates fixating fixation fixations fixative fixatives fixe fixed fixedly fixedness fixer fixers fixes fixing fixings fixities fixity fixture fixtures fizz fizzed fizzes fizzier fizziest fizzing fizzle fizzled fizzles fizzling fizzy fjeld fjelds fjord fjords flab flabbergast flabbergasted flabbergasting flabbergastingly flabbergasts flabbier flabbiest flabbily flabbiness flabby flabella flabellate flabelliform flabellum flaccid flaccidity flaccidly flaccidness flack flacked flackery flacking flacks flacon flacons flag flagella flagellant flagellantism flagellants flagellar flagellate flagellated flagellates flagellating flagellation flagellations flagellator flagellators flagelliform flagellin flagellins flagellum flagellums flageolet flageolets flagged flagger flaggers flagging flaggingly flagitious flagitiously flagitiousness flagman flagmen flagon flagons flagpole flagpoles flagrance flagrancy flagrant flagrante flagrantly flags flagship flagships flagstaff flagstaffs flagstick flagsticks flagstone flagstones flail flailed flailing flails flair flairs flak flake flaked flaker flakers flakes flakey flakier flakiest flakily flakiness flaking flaky flam flambeau flambeaus flambeaux flamboyance flamboyancy flamboyant flamboyantly flamboyants flambé flambéed flambéing flambés flame flamed flamen flamenco flamencos flamens flameout flameouts flameproof flameproofed flameproofer flameproofers flameproofing flameproofs flamer flamers flames flamethrower flamethrowers flamier flamiest flamines flaming flamingly flamingo flamingoes flamingos flaminian flammability flammable flammables flams flamy flan flanders flange flanged flanges flanging flank flanked flanken flankens flanker flankerback flankerbacks flankers flanking flanks flannel flannelette flannelettes flannelly flannels flans flap flapdoodle flapdoodles flapjack flapjacks flappable flapped flapper flappers flapping flappy flaps flare flareback flarebacks flared flares flaring flaringly flash flashback flashbacks flashboard flashboards flashbulb flashbulbs flashcube flashcubes flashed flasher flashers flashes flashflood flashfloods flashgun flashguns flashier flashiest flashily flashiness flashing flashings flashlamp flashlamps flashlight flashlights flashover flashovers flashpoint flashpoints flashtube flashtubes flashy flask flasks flat flatbed flatbeds flatboat flatboats flatbottom flatbottomed flatbread flatbreads flatcar flatcars flatfeet flatfish flatfishes flatfoot flatfooted flatfooting flatfoots flathead flatheads flatiron flatirons flatland flatlander flatlanders flatlands flatlet flatlets flatling flatlings flatly flatness flats flatted flatten flattened flattener flatteners flattening flattens flatter flattered flatterer flatterers flatteries flattering flatteringly flatters flattery flattest flatting flattish flattop flattops flatulence flatulencies flatulency flatulent flatulently flatus flatware flatways flatwise flatwork flatworks flatworm flatworms flaubert flaunt flaunted flaunter flaunters flauntier flauntiest flauntily flauntiness flaunting flauntingly flaunts flaunty flauta flautas flautist flautists flavanone flavanones flavescent flavian flavin flavine flavines flavins flavius flavone flavones flavonoid flavonoids flavonol flavonols flavoprotein flavoproteins flavor flavored flavorer flavorers flavorful flavorfully flavoring flavorings flavorist flavorists flavorless flavorous flavors flavorsome flavory flaw flawed flawing flawless flawlessly flawlessness flaws flawy flax flaxen flaxes flaxier flaxiest flaxseed flaxseeds flaxy flay flayed flayer flayers flaying flays flea fleabag fleabags fleabane fleabanes fleabite fleabites fleapit fleapits fleas fleawort fleaworts fleck flecked flecking flecks flection flectional flections fled fledermaus fledge fledged fledgeling fledgelings fledges fledging fledgling fledglings flee fleece fleeced fleecer fleecers fleeces fleech fleeched fleeches fleeching fleecier fleeciest fleecily fleeciness fleecing fleecy fleeing fleer fleered fleering fleeringly fleers flees fleet fleeted fleeter fleetest fleeting fleetingly fleetingness fleetly fleetness fleets fleishig fleming flemings flemish flense flensed flenser flensers flenses flensing flesh fleshed fleshes fleshier fleshiest fleshiness fleshing fleshless fleshlier fleshliest fleshliness fleshly fleshment fleshpot fleshpots fleshy fletch fletched fletcher fletchers fletches fletching fletschhorn fleur fleurs fleury flew flews flex flexagon flexagons flexed flexes flexibilities flexibility flexible flexibleness flexibly flexile flexing flexion flexions flexitime flexitimes flexographer flexographers flexographic flexographically flexography flexor flexors flextime flexuosity flexuous flexuously flexural flexure flexures fley fleyed fleying fleys flibbertigibbet flibbertigibbets flibbertigibbety flic flick flickable flicked flicker flickered flickering flickeringly flickerings flickers flickertail flickertails flickery flicking flicks flics flied flier fliers flies flight flighted flightier flightiest flightily flightiness flighting flightless flights flightworthiness flightworthy flighty flimflam flimflammed flimflammer flimflammers flimflammery flimflamming flimflams flimsier flimsies flimsiest flimsily flimsiness flimsy flinch flinched flincher flinchers flinches flinching flinchingly flinders fling flinger flingers flinging flings flint flinthead flintheads flintier flintiest flintily flintiness flintlike flintlock flintlocks flints flinty flip flipbook flipbooks flippancies flippancy flippant flippantly flipped flipper flippers flippest flipping flips flirt flirtation flirtations flirtatious flirtatiously flirtatiousness flirted flirter flirters flirting flirts flirty flit flitch flitches flits flitted flitter flittered flittering flitters flitting flivver flivvers float floatable floatage floatages floatation floated floater floaters floating floatplane floatplanes floats floaty floc floccose flocculate flocculated flocculates flocculating flocculation flocculations floccule flocculence flocculences flocculent flocculently floccules flocculi flocculus flock flocked flocking flocks flocs floe floes flog flogged flogger floggers flogging floggings flogs flood flooded flooder flooders floodgate floodgates flooding floodlight floodlighted floodlighting floodlights floodlit floodplain floodplains floods floodtide floodtides floodwall floodwalls floodwater floodwaters floodway floodways flooey floor floorage floorages floorboard floorboards floored floorer floorers flooring floorings floors floorshow floorshows floorwalker floorwalkers floozie floozies floozy flop flophouse flophouses flopped flopper floppers floppier floppies floppiest floppily floppiness flopping floppy flops flora florae floral florally floras floreated florence florentine florentines flores florescence florescent floret florets floriated floriation floriations floribunda floribundas floricane floricanes floricultural floriculturally floriculture floriculturist floriculturists florid florida floridan floridans floridean floridian floridians floridity floridly floridness floriferous floriferously floriferousness florigen florigenic florigens florilegia florilegium florin florins florist floristic floristically floristics floristry florists floruit floruits floss flossed flosser flossers flosses flossier flossiest flossily flossiness flossing flossy flota flotage flotages flotas flotation flotilla flotillas flotsam flotta flounce flounced flounces flouncing flouncings flouncy flounder floundered floundering flounders flour floured flouring flourish flourished flourisher flourishers flourishes flourishing flourishingly flours floury flout flouted flouter flouters flouting floutingly flouts flow flowage flowages flowchart flowcharted flowcharting flowcharts flowed flower flowerage flowerages flowerbed flowerbeds flowered flowerer flowerers floweret flowerets flowerful flowerier floweriest floweriness flowering flowerless flowerlike flowerpot flowerpots flowers flowery flowing flowingly flowmeter flowmeters flown flows flowstone flowstones flu flub flubbed flubber flubbers flubbing flubdub flubdubs flubs fluctuant fluctuate fluctuated fluctuates fluctuating fluctuation fluctuational fluctuations flue fluegelhorn fluegelhorns fluency fluent fluently flueric fluerics flues fluff fluffed fluffier fluffiest fluffily fluffiness fluffing fluffs fluffy fluid fluidal fluidally fluidextract fluidextracts fluidic fluidics fluidified fluidifies fluidify fluidifying fluidities fluidity fluidization fluidizations fluidize fluidized fluidizer fluidizers fluidizes fluidizing fluidly fluidness fluidram fluidrams fluids fluke flukes flukey flukier flukiest flukily flukiness fluky flulike flume flumes flummeries flummery flummox flummoxed flummoxes flummoxing flump flumped flumping flumps flung flunk flunked flunker flunkers flunkey flunkeys flunkies flunking flunkout flunkouts flunks flunky flunkyism fluor fluoresce fluoresced fluorescein fluoresceins fluorescence fluorescent fluorescents fluorescer fluorescers fluoresces fluorescing fluoridate fluoridated fluoridates fluoridating fluoridation fluoridations fluoride fluorides fluorimeter fluorimeters fluorimetric fluorimetry fluorinate fluorinated fluorinates fluorinating fluorination fluorinations fluorine fluorite fluorites fluorocarbon fluorocarbons fluorochemical fluorochemicals fluorochrome fluorochromes fluorography fluorometer fluorometers fluorometry fluoroscope fluoroscoped fluoroscopes fluoroscopic fluoroscopically fluoroscopies fluoroscoping fluoroscopist fluoroscopists fluoroscopy fluorosis fluorotic fluorouracil fluorouracils fluors fluorspar fluorspars fluphenazine fluphenazines flurazepam flurazepams flurried flurries flurry flurrying flush flushable flushed flusher flushers flushes flushest flushing flushless flushness flushometer flushometers fluster flustered flustering flusters flute fluted flutelike fluter fluters flutes flutey fluting flutings flutist flutists flutter flutterboard flutterboards fluttered flutterer flutterers fluttering flutters fluttery fluty fluvial fluviatile fluviomarine flux fluxed fluxes fluxing fluxion fluxional fluxionally fluxionary fluxions fly flyable flyaway flyaways flyblew flyblow flyblowing flyblown flyblows flyboat flyboats flyboy flyboys flyby flybys flycatcher flycatchers flyer flyers flying flyings flyleaf flyleaves flyman flymen flyover flyovers flypaper flypapers flypast flypasts flysch flysches flysheet flysheets flyspeck flyspecked flyspecking flyspecks flyswatter flyswatters flytrap flytraps flyway flyways flyweight flyweights flywheel flywheels flywhisk flywhisks flânerie flâneur flâneurs fléchette flèche flèches flügelhorn flügelhornist flügelhornists flügelhorns fo fo'c fo'c'sle fo'c'sles foal foaled foaling foals foam foamed foamer foamers foamflower foamflowers foamier foamiest foamily foaminess foaming foamless foams foamy fob fobbed fobbing fobs focal focalization focalizations focalize focalized focalizes focalizing focally fochabers foci focus focusable focused focuser focusers focuses focusing focusless focussed focusses focussing fodder foddered foddering fodders fodgel foe foehn foehns foeman foemen foes foetal foetid foetidus foetor foetors foetus fog fogbound fogbow fogbows fogdog fogdogs fogey fogeys foggage foggages fogged fogger foggers foggier foggiest foggily fogginess fogging foggy foghorn foghorns fogies fogless fogs fogy fogyish fogyism fogyisms foible foibles foil foiled foiling foils foilsman foilsmen foin foined foining foins foison foisons foist foisted foisting foists fokker folacin folacins folate folates fold foldable foldaway foldaways foldboat foldboats folded folder folderol folderols folders folding foldout foldouts folds foldup foldups folia foliaceous foliage foliaged foliages foliar foliate foliated foliates foliating foliation foliations folic folie foliicolous folio folioed folioing folios foliose folium folk folkie folkier folkies folkiest folkish folkishly folkishness folklike folklore folkloric folklorish folklorist folkloristic folkloristics folklorists folkmoot folkmoots folkmote folkmotes folks folksier folksiest folksily folksiness folksinger folksingers folksinging folksong folksongs folksy folktale folktales folkway folkways folky follicle follicles follicular folliculate folliculated folliculitis follies follow followed follower followers followership followerships following followings follows followup followups folly folsom fomalhaut foment fomentation fomentations fomented fomenter fomenters fomenting foments fomite fomites fon fond fondant fondants fonder fondest fondle fondled fondler fondlers fondles fondling fondly fondness fondnesses fonds fondu fondue fondued fondues fonduing fondus fongafale fons fonseca font fontainebleau fontal fontanel fontanelle fontanelles fontanels fontenoy fonteyn fontina fontinas fonts food foodie foodies foodless foodlessness foods foodservices foodstuff foodstuffs foodways foofaraw foofaraws fool fooled fooleries foolery foolhardier foolhardiest foolhardily foolhardiness foolhardy fooling foolings foolish foolishly foolishness foolproof fools foolscap foolscaps foon foons foot footage footages football footballer footballers footballs footbath footbaths footboard footboards footboy footboys footbridge footbridges footcloth footcloths footed footedly footer footers footfall footfalls footgear foothill foothills foothold footholds footing footings footle footled footler footlers footles footless footlessly footlessness footlight footlights footling footlocker footlockers footlong footloose footman footmark footmarks footmen footnote footnoted footnotes footnoting footpace footpaces footpad footpads footpath footpaths footprint footprinting footprints footrace footraces footracing footrest footrests footrope footropes foots footsie footslog footslogged footslogger footsloggers footslogging footslogs footsore footsoreness footstalk footstalks footstall footstalls footstep footsteps footstone footstones footstool footstools footsy footwall footwalls footway footways footwear footwork foozle foozled foozler foozlers foozles foozling fop fopped fopperies foppery fopping foppish foppishly foppishness fops for fora forage foraged forager foragers forages foraging foraker foram foramen foramens foramina foraminal foraminifer foraminifera foraminiferal foraminiferan foraminiferous foraminifers foraminous forams forasmuch foray forayed forayer forayers foraying forays forb forbad forbade forbear forbearance forbearer forbearers forbearing forbears forbid forbiddance forbidden forbidder forbidders forbidding forbiddingly forbiddingness forbids forbore forborne forbs forby forbye force forceable forced forcedly forceful forcefully forcefulness forceless forcemeat forceps forcepslike forcer forcers forces forcible forcibleness forcibly forcing forcipate forcipes ford fordable forded fordid fording fordo fordoes fordoing fordone fords fore forearm forearmed forearming forearms forebay forebays forebear forebears forebode foreboded foreboder foreboders forebodes foreboding forebodingly forebodingness forebodings forebrain forebrains forecaddie forecaddies forecast forecastable forecasted forecaster forecasters forecasting forecastle forecastles forecasts foreclosable foreclose foreclosed forecloses foreclosing foreclosure foreclosures forecourt forecourts foredeck foredecks foredid foredo foredoes foredoing foredone foredoom foredoomed foredooming foredooms foreface forefaces forefather forefathers forefeel forefeeling forefeels forefeet forefelt forefend forefended forefending forefends forefinger forefingers forefoot forefront foregather foregathered foregathering foregathers forego foregoer foregoers foregoes foregoing foregone foreground foregrounds foregut foreguts forehand forehanded forehandedly forehandedness forehands forehead foreheads forehoof foreign foreigner foreigners foreignism foreignisms foreignness forejudge forejudged forejudges forejudging forejudgment forejudgments foreknew foreknow foreknowing foreknowledge foreknown foreknows foreladies forelady foreland forelands foreleg forelegs forelimb forelimbs forelock forelocks foreman foremanship foremast foremasts foremen foremilk foremost foremother foremothers forename forenamed forenames forenoon forenoons forensic forensically forensics foreordain foreordained foreordaining foreordainment foreordainments foreordains foreordination foreordinations forepart foreparts forepassed forepast forepaw forepaws forepeak forepeaks foreperson forepersons foreplay forequarter forequarters foreran forereach forereached forereaches forereaching forerun forerunner forerunners forerunning foreruns foresaid foresail foresails foresaw foresee foreseeability foreseeable foreseeing foreseen foreseer foreseers foresees foreshadow foreshadowed foreshadower foreshadowers foreshadowing foreshadows foreshank foresheet foresheets foreshock foreshocks foreshore foreshores foreshorten foreshortened foreshortening foreshortens foreshow foreshowed foreshowing foreshown foreshows foreside foresides foresight foresighted foresightedly foresightedness foresightful foreskin foreskins forespeak forespeaking forespeaks forespoke forespoken forest forestage forestages forestal forestall forestalled forestaller forestallers forestalling forestallment forestalls forestation forestations forestay forestays forestaysail forestaysails forested forester foresters forestial foresting forestland forestlands forestry forests foretaste foretasted foretastes foretasting foretell foreteller foretellers foretelling foretells forethought forethoughtful forethoughtfully forethoughtfulness forethoughts foretime foretimes foretoken foretokened foretokening foretokens foretold foretop foretopgallant foretopmast foretopmasts foretops foretopsail foretopsails forever forevermore foreverness forewarn forewarned forewarning forewarnings forewarns forewent forewing forewings forewoman forewomen foreword forewords foreworn foreyard foreyards forfeit forfeitable forfeited forfeiter forfeiters forfeiting forfeits forfeiture forfeitures forfend forfended forfending forfends forficate forgather forgathered forgathering forgathers forgave forge forgeability forgeable forged forger forgeries forgers forgery forges forget forgetful forgetfully forgetfulness forgetive forgets forgettable forgetter forgetters forgetting forging forgings forgivable forgivably forgive forgiven forgiveness forgiver forgivers forgives forgiving forgivingly forgivingness forgo forgoer forgoers forgoes forgoing forgone forgot forgotten forint forints fork forkball forkballer forkballers forkballs forked forker forkers forkful forkfuls forkier forkiest forking forklift forklifted forklifting forklifts forks forky forlorn forlornly forlornness form forma formability formable formal formaldehyde formalin formalins formalism formalisms formalist formalistic formalistically formalists formalities formality formalizable formalization formalizations formalize formalized formalizer formalizers formalizes formalizing formally formalness formals formalwear formant formants format formate formates formation formational formations formative formatively formativeness formatives formats formatted formatter formatters formatting forme formed formee former formerly formers formes formfeed formfeeds formfitting formful formic formica formicaries formicary formicivorous formidability formidable formidableness formidably forming formless formlessly formlessness formosa forms formula formulae formulaic formulaically formularies formularization formularizations formularize formularized formularizer formularizers formularizes formularizing formulary formulas formulate formulated formulates formulating formulation formulations formulator formulators formulization formulizations formulize formulized formulizer formulizers formulizes formulizing formwork formworks formyl formyls fornax fornicate fornicated fornicates fornicating fornication fornications fornicator fornicators fornices fornix forrader forrarder forsake forsaken forsakes forsaking forsook forsooth forspent forswear forswearer forswearers forswearing forswears forswore forsworn forsythia forsythias fort fortalice fortalices forte fortes forth forthcoming forthcomings forthright forthrightly forthrightness forthwith forties fortieth fortieths fortifiable fortification fortifications fortified fortifier fortifiers fortifies fortify fortifying fortifyingly fortiori fortis fortises fortissimo fortissimos fortississimo fortitude fortitudinous fortnight fortnightlies fortnightly fortnights fortran fortress fortresses fortresslike forts fortuities fortuitous fortuitously fortuitousness fortuity fortuna fortunate fortunately fortunateness fortunates fortune fortuned fortunes fortuneteller fortunetellers fortunetelling fortuning forty fortyfold fortyish forum forums forward forwarded forwarder forwarders forwarding forwardly forwardness forwards forwent forworn forzando forzandos foss fossa fossae fossate fosse fosses fossick fossicked fossicker fossickers fossicking fossicks fossil fossiliferous fossilization fossilizations fossilize fossilized fossilizes fossilizing fossils fossorial foster fosterage fostered fosterer fosterers fostering fosterling fosterlings fosters fou foucault foudroyant fought foul foulard foulards foulbrood foulbroods fouled fouler foulest fouling foully foulmouthed foulness fouls found foundation foundational foundationally foundationless foundations founded founder foundered foundering founders founding foundling foundlings foundries foundry founds fount fountain fountained fountainhead fountainheads fountaining fountains founts four fourchee fourchette fourchettes fourdrinier fourdriniers fourfold fourgon fourgons fourhanded fourier fourierism fourierist fourierists fourierite fourierites fourpenny fourragère fours fourscore foursome foursomes foursquare foursquarely fourteen fourteenfold fourteens fourteenth fourteenths fourth fourthly fourths fovea foveae foveal foveate foveiform foveola foveolae foveolas fowl fowled fowler fowlers fowling fowls fox foxed foxes foxfire foxfires foxglove foxgloves foxhole foxholes foxhound foxhounds foxhunt foxhunted foxhunter foxhunters foxhunting foxhunts foxier foxiest foxily foxiness foxing foxtail foxtails foxtrot foxtrots foxtrotted foxtrotting foxy foy foyer foyers foyle foys fra fracas fracases fractal fractals fracted fraction fractional fractionalization fractionalizations fractionalize fractionalized fractionalizes fractionalizing fractionally fractionate fractionated fractionates fractionating fractionation fractionations fractionator fractionators fractionization fractionizations fractionize fractionized fractionizes fractionizing fractions fractious fractiously fractiousness fractur fracture fractured fractures fracturing fracturs frae frag fragged fragger fraggers fragging fragile fragilely fragileness fragilities fragility fragment fragmental fragmentally fragmentarily fragmentariness fragmentary fragmentate fragmentated fragmentates fragmentating fragmentation fragmentations fragmented fragmenting fragmentize fragmentized fragmentizer fragmentizers fragmentizes fragmentizing fragments fragonard fragrance fragrances fragrancy fragrant fragrantly frags fraidy frail frailer frailest frailly frailness frailties frailty fraise fraises fraktur frakturs framable frambesia frambesias frame frameable framed framer framers frames frameshift framework frameworks framing framingham framings franc franca francas france franchise franchised franchisee franchisees franchiser franchisers franchises franchising franchisor franchisors francis franciscan franciscans francisco francium franco francolin francolins franconia franconian franconians francophile francophiles francophilia francophobe francophobes francophobia francophobic francophone francophones francophonic francs frangibility frangible frangibleness frangipane frangipani frangipanis franglais frank franked frankenstein frankenstein's frankensteinian frankensteins franker frankers frankest frankfort frankforter frankforters frankfurt frankfurter frankfurters frankincense franking frankish franklin franklinite franklinites franklins frankly frankness frankpledge frankpledges franks franseria franserias frantic frantically franticly franticness française frap frappe frapped frappes frapping frappé frappés fraps fraser frat fraternal fraternalism fraternally fraternities fraternity fraternization fraternizations fraternize fraternized fraternizer fraternizers fraternizes fraternizing fratricidal fratricide fratricides frats frau fraud frauds fraudulence fraudulent fraudulently fraudulentness frauen fraught fraughted fraughting fraughts fraunhofer fraxinella fraxinellas fray frayed fraying frays frazzle frazzled frazzles frazzling freak freaked freakier freakiest freakily freakiness freaking freakish freakishly freakishness freaks freaky freckle freckled freckles freckling freckly frederick fredericton free freebase freebased freebaser freebasers freebases freebasing freebee freebees freebie freebies freeboard freeboards freeboot freebooted freebooter freebooters freebooting freeboots freeborn freed freedman freedmen freedom freedoms freedwoman freedwomen freeform freehand freehanded freehandedly freehandedness freehearted freeheartedly freeheartedness freehold freeholder freeholders freeholds freeing freelance freelanced freelancer freelancers freelances freelancing freeload freeloaded freeloader freeloaders freeloading freeloads freely freeman freemartin freemartins freemason freemasonry freemasons freemen freeness freeport freer freers frees freesia freesias freest freestanding freestone freestones freestyle freestyles freethinker freethinkers freethinking freetown freeware freeway freeways freewheel freewheeled freewheeler freewheelers freewheeling freewheelingly freewheels freewill freezable freeze freezer freezers freezes freezing freiberg freiburg freight freightage freighted freighter freighters freighting freightliner freightliners freights fremantle fremitus fremontia fremontias frena french frenched frenches frenchification frenchified frenchifies frenchify frenchifying frenching frenchman frenchmen frenchness frenchwoman frenchwomen frenetic frenetical frenetically freneticism frenula frenulum frenum frenums frenzied frenziedly frenzies frenzy frenzying freon frequence frequences frequencies frequency frequent frequentation frequentations frequentative frequentatives frequented frequenter frequenters frequenting frequently frequentness frequents fresco frescoed frescoer frescoers frescoes frescoing frescoist frescoists frescos fresh freshen freshened freshener fresheners freshening freshens fresher freshest freshet freshets freshly freshman freshmen freshness freshwater fresnel fresno fret fretful fretfully fretfulness fretless frets fretsaw fretsaws fretted fretter fretters fretting fretwork freud freudian freudianism freudians frey freya freyr friability friable friableness friar friarbird friarbirds friaries friarly friars friary fribble fribbled fribbler fribblers fribbles fribbling fribourg fricandeau fricandeaus fricassee fricasseed fricasseeing fricassees fricative fricatives friction frictional frictionally frictionless frictionlessly frictions friday fridays fridge fridges fried friedland friedrichshafen friend friended friending friendless friendlessness friendlier friendlies friendliest friendlily friendliness friendly friends friendship friendships frier friers fries friesian friesians friesland frieze friezes frig frigate frigates frigg frigga frigged frigging fright frighted frighten frightened frightener frighteners frightening frighteningly frightens frightful frightfully frightfulness frighting frights frigid frigidaire frigidities frigidity frigidly frigidness frigorific frigorifical frigs frijol frijole frijoles frill frilled frillier frilliest frilliness frilling frills frilly fringe fringed fringes fringing fringy fripperies frippery frisbee frisbees frisch frisette frisettes friseur friseurs frisian frisians frisk frisked frisker friskers frisket friskets friskier friskiest friskily friskiness frisking frisks frisky frisson frissons frisé frisée frit frith friths fritillaries fritillary frits frittata frittatas fritted fritter frittered fritterer fritterers frittering fritters fritting fritz fritzes friuli frivol frivoled frivoler frivolers frivoling frivolities frivolity frivolled frivoller frivollers frivolling frivolous frivolously frivolousness frivols frizette frizettes frizz frizzed frizzer frizzers frizzes frizzier frizziest frizzily frizziness frizzing frizzle frizzled frizzles frizzlier frizzliest frizzling frizzly frizzy fro frobenius frobisher frock frocked frocking frocks froe froebel froes frog frogeye frogeyes frogfish frogfishes froghopper froghoppers frogman frogmen frogmouth frogmouths frogs froissart frolic frolicked frolicker frolickers frolicking frolics frolicsome from frond fronded frondescence frondescent frondeur frondeurs frondose frondosely fronds frons front frontage frontages frontal frontality frontally frontals frontcourt frontcourts fronted frontenis frontes frontier frontiers frontiersman frontiersmen frontierswoman frontierswomen fronting frontispiece frontispieces frontless frontlet frontlets frontline frontogeneses frontogenesis frontolyses frontolysis fronton frontons frontrunner frontrunners fronts frontward frontwards frore frosh froshes frost frostbelt frostbit frostbite frostbites frostbiting frostbitten frosted frostfish frostfishes frostier frostiest frostily frostiness frosting frostings frosts frostwork frostworks frosty froth frothed frothier frothiest frothily frothiness frothing froths frothy frottage frottages froufrou froufrous frow froward frowardly frowardness frown frowned frowner frowners frowning frowningly frowns frows frowsier frowsiest frowstier frowstiest frowsty frowsy frowzier frowziest frowziness frowzy froze frozen frozenly frozenness fructiferous fructification fructifications fructified fructifies fructify fructifying fructose fructuous frugal frugalities frugality frugally frugalness frugivore frugivores frugivorous fruit fruitage fruitages fruitarian fruitarians fruitcake fruitcakes fruited fruiterer fruiterers fruitful fruitfully fruitfulness fruitier fruitiest fruitiness fruiting fruition fruitions fruitless fruitlessly fruitlessness fruitlet fruitlets fruits fruitwood fruitwoods fruity frumentaceous frumenties frumenty frump frumpier frumpiest frumpily frumpiness frumpish frumpishly frumpishness frumps frumpy frusta frustrate frustrated frustrater frustraters frustrates frustrating frustratingly frustration frustrations frustule frustules frustum frustums frutescence frutescent fruticose fry fryer fryers frying fräulein fräuleins ftp fu fubsier fubsiest fubsy fuchsia fuchsias fuchsin fuchsine fuchsines fuchsins fuck fucked fucker fuckers fucking fucks fuckup fuckups fucoid fucoids fucose fucoses fucoxanthin fucoxanthins fucus fucuses fud fuddle fuddled fuddles fuddling fudge fudged fudges fudging fuds fuego fuehrer fuehrers fuel fueled fueler fuelers fueling fuelled fuelling fuels fuertaventura fuerteventura fug fugacious fugaciously fugaciousness fugacities fugacity fugal fugally fugged fugging fuggy fugit fugitive fugitively fugitiveness fugitives fugle fugled fugleman fuglemen fugles fugling fugs fugu fugue fugued fugues fuguing fuguist fuguists fugus fuissé fujairah fuji fujian fujinoyama fujis fujisan fujisawa fukien fula fulani fulanis fulas fulbright fulcra fulcrum fulcrums fulfil fulfill fulfilled fulfiller fulfillers fulfilling fulfillment fulfillments fulfills fulfilment fulfils fulgent fulgently fulgurant fulgurate fulgurated fulgurates fulgurating fulguration fulgurations fulgurite fulgurites fulgurous fulham fulhams fuliginous fuliginously full fullback fullbacks fulled fuller fullerene fullerenes fullers fullest fulling fullmouthed fullness fulls fulltime fully fulmar fulmars fulminant fulminate fulminated fulminates fulminating fulmination fulminations fulminator fulminators fulminatory fulmine fulmined fulmines fulminic fulmining fulness fulsome fulsomely fulsomeness fulvous fumarase fumarases fumarate fumarates fumaric fumarole fumaroles fumarolic fumatoria fumatories fumatorium fumatoriums fumatory fumble fumbled fumbler fumblers fumbles fumbling fumblingly fume fumed fumes fumet fumets fumier fumiest fumigant fumigants fumigate fumigated fumigates fumigating fumigation fumigations fumigator fumigators fuming fumitories fumitory fumy fun funafuti funambulism funambulist funambulists funchal function functional functionalism functionalist functionalistic functionalists functionalities functionality functionally functionaries functionary functioned functioning functionless functions functor functors fund fundable fundament fundamental fundamentalism fundamentalist fundamentalistic fundamentalists fundamentally fundamentals fundaments funded fundi fundic funding fundraise fundraised fundraiser fundraisers fundraises fundraising funds fundus funeral funerals funerary funereal funereally funfair funfairs funfest funfests fungal fungi fungibility fungible fungibles fungicidal fungicidally fungicide fungicides fungiform fungistat fungistats fungivorous fungo fungoes fungoid fungoids fungous fungus funguses funicle funicles funicular funiculars funiculi funiculus funk funked funkia funkias funkier funkiest funkiness funking funks funky funned funnel funneled funnelform funneling funnelled funnelling funnels funnier funnies funniest funnily funniness funning funny funnyman funnymen funs fur furan furane furanes furanose furanoses furans furbearer furbearers furbearing furbelow furbelowed furbelowing furbelows furbish furbished furbisher furbishers furbishes furbishing furcate furcated furcately furcates furcating furcation furcations furcula furculae furcular furfur furfuraceous furfural furfurals furfuran furfurans furfures furies furioso furious furiously furl furled furless furling furlong furlongs furlough furloughed furloughing furloughs furls furmities furmity furnace furnaces furnish furnished furnisher furnishers furnishes furnishing furnishings furniture furor furore furores furors furosemide furosemides furred furrier furrieries furriers furriery furriest furriner furriners furriness furring furrings furrow furrowed furrowing furrows furry furs further furtherance furthered furtherer furtherers furthering furthermore furthermost furthers furthest furtive furtively furtiveness furuncle furuncles furuncular furunculosis furunculous fury furze furzes furzy fusain fusains fusaria fusarium fuscous fuse fused fusee fusees fusel fuselage fuselages fusels fuser fusers fuses fusibility fusible fusibleness fusiform fusil fusile fusileer fusileers fusilier fusiliers fusillade fusilladed fusillades fusillading fusils fusing fusion fusionism fusionist fusionists fusions fuss fussbudget fussbudgets fussbudgety fussed fusser fussers fusses fussier fussiest fussily fussiness fussing fusspot fusspots fussy fustian fustians fustic fustics fustier fustiest fustigate fustigated fustigates fustigating fustigation fustigations fustily fustiness fusty fusuma futhark futharks futhorc futhork futile futilely futileness futilitarian futilitarianism futilitarians futilities futility futon futons futtock futtocks futuna future futureless futurelessness futures futurism futurisms futurist futuristic futuristically futuristics futurists futurities futurity futurological futurologist futurologists futurology futz futzed futzes futzing fuze fuzed fuzee fuzees fuzes fuzing fuzz fuzzed fuzzes fuzzier fuzziest fuzzily fuzziness fuzzing fuzzy fuzzyheaded fuzzyheadedness fyce fyces fyke fykes fylfot fylfots fyn fátima fès fête fêted fêtes fêting föhn föhns führer führers g gab gabardine gabardines gabbed gabber gabbers gabbier gabbiest gabbiness gabbing gabble gabbled gabbler gabblers gabbles gabbling gabbro gabbroic gabbroid gabbros gabby gabelle gabelles gaberdine gaberdines gabfest gabfests gabies gabion gabions gable gabled gabler gables gabon gabonese gaboon gaboons gaborone gabriel gabs gaby gad gadabout gadabouts gadara gadarene gadarenes gaddafi gadded gadder gadders gadding gadflies gadfly gadget gadgeteer gadgeteers gadgetry gadgets gadgety gadid gadids gadoid gadoids gadolinite gadolinites gadolinium gadoliniums gadroon gadrooned gadrooning gadroonings gadroons gads gadwall gadwalls gadzooks gaea gael gaeldom gaelic gaels gaff gaffe gaffed gaffer gaffers gaffes gaffing gaffs gag gaga gage gaged gager gagers gages gagged gagger gaggers gagging gaggle gaggles gaging gagman gagmen gags gagster gagsters gahnite gahnites gaia gaieties gaiety gaillardia gaillardias gaily gain gained gainer gainers gainesville gainful gainfully gainfulness gaingiving gaining gains gainsaid gainsay gainsayer gainsayers gainsaying gainsays gainsborough gainst gaiseric gait gaited gaiter gaiters gaithersburg gaiting gaits gaius gal gala galabia galabias galactic galactopoiesis galactopoietic galactorrhea galactosamine galactosamines galactose galactosemia galactosemias galactosemic galactosidase galactosidases galactoside galactosides galago galagos galah galahad galahads galahs galangal galangals galantine galantines galanty galapagos galas galatea galateas galatia galatian galatians galavant galavanted galavanting galavants galax galaxes galaxies galaxy galbanum galbanums gale galea galeae galeate galeated galen galena galenas galenical galenicals galenism galenist galenists galere galeres galerius gales galibi galibis galicia galician galicians galilean galileans galilee galilees galileo galimatias galimatiases galingale galingales galiot galiots galipot galipots galivant galivanted galivanting galivants gall galla gallamine gallant gallanted gallanting gallantly gallantries gallantry gallants gallas gallate gallates gallbladder gallbladders galleass galleasses galled gallein galleins galleon galleons galleria gallerias galleried galleries gallery galleta galletas galley galleys gallflies gallfly gallia galliard galliards gallic gallican gallicanism gallicans gallicism gallicisms gallicization gallicizations gallicize gallicized gallicizes gallicizing gallied gallies galligaskins gallimaufries gallimaufry gallinacean gallinaceans gallinaceous gallinas galling gallingly gallinipper gallinippers gallinule gallinules galliot galliots gallipoli gallipot gallipots gallium gallivant gallivanted gallivanting gallivants galliwasp galliwasps gallnut gallnuts gallo galloglass galloglasses gallomania gallomanias gallon gallonage gallonages gallons galloon gallooned galloons gallop gallopade galloped galloper gallopers galloping gallops galloway gallowglass gallowglasses gallows gallowses galls gallstone gallstones gallus galluses gally gallying galois galoot galoots galop galops galore galosh galoshed galoshes gals galsworthy galumph galumphed galumphing galumphs galvanic galvanically galvanism galvanisms galvanization galvanizations galvanize galvanized galvanizer galvanizers galvanizes galvanizing galvanomagnetic galvanometer galvanometers galvanometric galvanometrical galvanometry galvanoscope galvanoscopes galvanoscopic galvanoscopy galveston galway galwegian galwegians galyak galyaks galápagos galère gam gama gamage gamay gamays gamba gambado gambadoes gambados gambas gambia gambian gambians gambier gambiers gambir gambirs gambit gambits gamble gambled gambler gamblers gambles gambling gamboge gamboges gambol gamboled gamboling gambolled gambolling gambols gambrel gambrels gambusia gambusias game gamecock gamecocks gamed gamekeeper gamekeepers gamelan gamelans gamelike gamely gameness gamer games gamesman gamesmanship gamesmen gamesome gamesomely gamesomeness gamest gamester gamesters gametangia gametangial gametangium gamete gametes gametic gametically gametocyte gametocytes gametogenesis gametogenic gametogenous gametophore gametophores gametophoric gametophyte gametophytes gametophytic gamey gamic gamier gamiest gamily gamin gamine gamines gaminess gaming gamings gamins gamma gammas gammed gammer gammers gamming gammon gammoned gammoner gammoners gammoning gammons gamogenesis gamogenetic gamogenetically gamopetalous gamophyllous gamosepalous gamow gamp gamps gams gamut gamuts gamy gan ganciclovir gander ganders gandhi gandhian ganef ganefs ganesha gang ganga gangbang gangbanged gangbanging gangbangs gangbuster gangbusters ganged ganger gangers ganges ganging gangland ganglia gangliate gangliated ganglier gangliest gangling ganglion ganglionated ganglionic ganglions ganglioside gangliosides gangly gangplank gangplanks gangplow gangplows gangpunch gangpunched gangpunches gangpunching gangrel gangrels gangrene gangrened gangrenes gangrening gangrenous gangs gangster gangsterdom gangsterism gangsters gangue gangues gangway gangways ganister ganisters ganja ganjas gannet gannets gannister gannisters ganof ganofs ganoid ganoids gansu gantlet gantleted gantleting gantlets gantline gantlines gantlope gantlopes gantries gantry gantt ganymede gaol gaoled gaoler gaolers gaoling gaols gap gape gaped gaper gapers gapes gapeworm gapeworms gaping gapingly gapped gapping gappy gaps gar garage garageable garaged garageman garagemen garages garaging garamond garb garbage garbanzo garbanzos garbed garbing garble garbled garbler garblers garbles garbling garbo garboard garboards garboil garboils garbologist garbologists garbology garbs garcía garda gardant garde garden gardened gardener gardeners gardenful gardenia gardenias gardening gardens garderobe garderobes gardiners gardyloo garfield garfish garfishes garganey garganeys gargantua gargantuan gargantuas garget gargets gargle gargled gargles gargling gargoyle gargoyles garibaldi garibaldis garish garishly garishness garland garlanded garlanding garlands garlic garlicked garlicking garlicks garlicky garment garmented garmenting garments garner garnered garnering garners garnet garnetiferous garnets garni garnierite garnierites garnis garnish garnished garnishee garnisheed garnisheeing garnishees garnishes garnishing garnishment garnishments garniture garnitures garonne garotte garotted garotter garotters garottes garotting garpike garpikes garred garret garrets garrick garring garrison garrisoned garrisoning garrisons garron garrons garrote garroted garroter garroters garrotes garroting garrotte garrotted garrottes garrotting garrulity garrulous garrulously garrulousness gars garter gartered gartering garters garth garths garve garvey garveys garçon garçons gas gasbag gasbags gascon gasconade gasconaded gasconader gasconaders gasconades gasconading gascons gascony gasdynamic gasdynamicist gasdynamicists gasdynamics gaseous gaseousness gases gash gashed gasherbrum gashes gashing gasholder gasholders gashouse gashouses gasifiable gasification gasifications gasified gasifier gasifiers gasifies gasiform gasify gasifying gaskell gasket gaskets gaskin gaskins gaslight gaslights gaslit gasogene gasogenes gasohol gasolene gasolenes gasolier gasoliers gasoline gasolines gasolinic gasometer gasometers gasp gaspar gasped gasper gaspers gasping gaspingly gasps gaspé gassed gasser gassers gasses gassier gassiest gassily gassiness gassing gassings gassy gast gasted gastight gastightness gasting gastness gastraea gastraeas gastrea gastreas gastrectomies gastrectomy gastric gastrin gastrins gastritis gastrocnemii gastrocnemius gastroenteric gastroenteritis gastroenterologic gastroenterological gastroenterologist gastroenterologists gastroenterology gastrointestinal gastrolith gastroliths gastrologic gastrological gastrologically gastrologist gastrologists gastrology gastronome gastronomer gastronomers gastronomes gastronomic gastronomical gastronomically gastronomies gastronomist gastronomists gastronomy gastropod gastropodan gastropodous gastropods gastroscope gastroscopes gastroscopic gastroscopist gastroscopists gastroscopy gastrostomies gastrostomy gastrotomies gastrotomy gastrotrich gastrotriches gastrovascular gastrula gastrulae gastrular gastrulas gastrulate gastrulated gastrulates gastrulating gastrulation gastrulations gasts gasworks gat gate gateau gateaux gatecrash gatecrashed gatecrasher gatecrashers gatecrashes gatecrashing gated gatefold gatefolds gatehouse gatehouses gatekeeper gatekeepers gatepost gateposts gater gaters gates gateway gatewayed gatewaying gateways gather gathered gatherer gatherers gathering gatherings gathers gatherum gatherums gatineau gating gatling gatlings gator gatorade gators gats gatún gauche gauchely gaucheness gaucher gaucherie gaucheries gauchest gaucho gauchos gaud gaudeamus gauderies gaudery gaudier gaudies gaudiest gaudily gaudiness gauds gaudy gaufer gaufers gauffer gauffered gauffering gauffers gaugamela gauge gaugeable gauged gauger gaugers gauges gauging gauguin gaul gaulish gaulle gaullism gaullist gaullists gauls gault gaults gaum gaumed gauming gaumont gaums gaunt gaunter gauntest gauntlet gauntleted gauntlets gauntly gauntness gaur gaurs gauss gausses gaussian gautama gauze gauzelike gauzes gauzier gauziest gauzily gauziness gauzy gavage gavages gavarnie gave gavel gaveled gaveling gavelkind gavelled gavelling gavels gavial gavials gavotte gavotted gavottes gavotting gawain gawk gawked gawker gawkers gawkier gawkiest gawkily gawking gawkish gawkishly gawkishness gawks gawky gawp gawped gawper gawpers gawping gawps gay gayal gayals gayer gayest gayety gayly gayness gays gaza gazar gazars gaze gazebo gazeboes gazebos gazed gazehound gazehounds gazelle gazelles gazer gazers gazes gazette gazetted gazetteer gazetteers gazettes gazetting gaziantep gazillion gazillionaire gazillionaires gazillions gazing gazogene gazogenes gazpacho gazpachos gdansk geanticlinal geanticline geanticlines gear gearbox gearboxes geared gearing gearings gearless gears gearshift gearshifts gearwheel gearwheels geat geats gebel geber gecko geckoes geckos gedankenexperiment gedankenexperiments gee geechee geechees geed geegaw geegaws geeing geek geekish geeks geeky geelong gees geese geezer geezers gefilte gegenschein gegenscheins gehenna gehennas gehrig geiger geisha geishas gel gelable gelada gelate gelated gelates gelati gelatin gelatine gelatines gelating gelatinization gelatinizations gelatinize gelatinized gelatinizes gelatinizing gelatinous gelatinously gelatinousness gelatins gelation gelations gelato geld gelded gelderland gelding geldings gelds gelee gelees gelid gelidities gelidity gelidly gelidness gelignite gelignites gellant gellants gelled gelling gels gelsenkirchen gelt gelts geländesprung geländesprungs gem gemara gemaric gemarist gemarists geminal geminally geminate geminated geminates geminating gemination geminations gemini geminian geminians geminis gemlike gemma gemmae gemmate gemmated gemmates gemmating gemmation gemmations gemmed gemming gemmiparous gemmiparously gemmologist gemmologists gemmology gemmulation gemmulations gemmule gemmules gemmuliferous gemmy gemological gemologist gemologists gemology gemot gemote gemotes gemots gems gemsbok gemsboks gemstone gemstones gemütlich gemütlichkeit gendarme gendarmerie gendarmeries gendarmes gender gendered gendering genderless genders gene genealogical genealogically genealogies genealogist genealogists genealogize genealogized genealogizes genealogizing genealogy genera generable general generalcies generalcy generalissimo generalissimos generalist generalists generalities generality generalizability generalizable generalization generalizations generalize generalized generalizer generalizers generalizes generalizing generally generalness generals generalship generalships generate generated generates generating generation generational generations generative generatively generativeness generator generators generatrices generatrix generic generically genericness generics generis generosities generosity generous generously generousness genes genesee geneses genesis genet genetic genetical genetically geneticist geneticists genetics genets geneva genevan genevans genevese genghis genial geniality genially genialness genials genic genically geniculate geniculated geniculately geniculation geniculations genie genies genii genip genipap genipaps genips genital genitalia genitalic genitally genitals genitival genitivally genitive genitives genitor genitors genitourinary geniture genitures genius geniuses genoa genoas genocidal genocidally genocide genocides genoese genoise genoises genom genome genomes genomic genomics genoms genotype genotypes genotypic genotypical genotypically genotypicity genova genre genres genro genros gens genseric gent gentamicin gentamicins genteel genteelism genteelisms genteelly genteelness gentes gentian gentians gentile gentiles gentilesse gentilesses gentilities gentility gentle gentled gentlefolk gentlefolks gentleman gentlemanlike gentlemanlikeness gentlemanliness gentlemanly gentlemen gentleness gentlepeople gentlepeoples gentleperson gentlepersons gentler gentles gentlest gentlewoman gentlewomen gentling gently gentrice gentrices gentries gentrification gentrifications gentrified gentrifier gentrifiers gentrifies gentrify gentrifying gentry gents genuflect genuflected genuflecting genuflection genuflections genuflects genuflexion genuine genuinely genuineness genus geobotanic geobotanical geobotanically geobotanist geobotanists geobotany geocentric geocentrically geocentricism geochemical geochemically geochemist geochemistry geochemists geochronologic geochronological geochronologically geochronologist geochronologists geochronology geochronometric geochronometry geocode geocodes geocorona geocoronas geode geodes geodesic geodesics geodesist geodesists geodesy geodetic geodetical geodetically geoduck geoducks geoeconomic geoeconomically geoeconomics geoeconomist geoeconomists geographer geographers geographic geographical geographically geographies geography geohydrologic geohydrologist geohydrologists geohydrology geoid geoidal geoids geologic geological geologically geologies geologist geologists geologize geologized geologizes geologizing geology geomagnetic geomagnetically geomagnetism geomancer geomancers geomancy geomantic geometer geometers geometric geometrical geometrically geometrician geometricians geometricize geometricized geometricizes geometricizing geometrics geometrid geometrids geometries geometrize geometrized geometrizes geometrizing geometry geomorphic geomorphologic geomorphological geomorphologically geomorphologist geomorphologists geomorphology geophagism geophagist geophagists geophagy geophone geophones geophysical geophysically geophysicist geophysicists geophysics geophyte geophytes geopolitical geopolitically geopolitician geopoliticians geopolitics geoponic geoponics geopressured geopressurized geordie geordies george georges georgetown georgette georgettes georgia georgian georgians georgic georgical georgics geoscience geosciences geoscientist geoscientists geostationary geostrategic geostrategies geostrategist geostrategists geostrategy geostrophic geostrophically geosynchronous geosynchronously geosynclinal geosyncline geosynclines geotactic geotactically geotaxes geotaxis geotectonic geothermal geothermally geothermic geotropic geotropically geotropism gerah gerahs geraint geranial geranials geraniol geraniols geranium geraniums gerardia gerardias gerbera gerberas gerbil gerbille gerbilles gerbils gerent gerents gerenuk gerenuks gerfalcon gerfalcons geriatric geriatrician geriatricians geriatrics geriatrist geriatrists germ german germander germanders germane germanely germaneness germania germanic germanicus germanism germanisms germanist germanists germanium germanization germanizations germanize germanized germanizer germanizers germanizes germanizing germanophile germanophiles germanophobe germanophobes germanophobia germans germantown germany germen germens germfree germicidal germicide germicides germier germiest germinability germinal germinally germinate germinated germinates germinating germination germinations germinative germinator germinators germiness germproof germs germy gerodontic gerodontics gerona geronimo gerontic gerontocracies gerontocracy gerontocrat gerontocratic gerontocrats gerontologic gerontological gerontologist gerontologists gerontology gerontomorphic gerrymander gerrymandered gerrymandering gerrymanders gershwin gertrude gertrudis gerund gerundial gerundive gerundives gerunds geryon gesneriad gesneriads gesso gessoed gessoes gest gestalt gestalten gestaltist gestaltists gestalts gestapo gestapos gestate gestated gestates gestating gestation gestational gestations gestatory geste gestes gestic gesticulate gesticulated gesticulates gesticulating gesticulation gesticulations gesticulative gesticulator gesticulators gesticulatory gests gestural gesturally gesture gestured gesturer gesturers gestures gesturing gesundheit get geta getable getas getatable getaway getaways gethsemane gethsemanes gets gettable getter getters getting getty gettysburg getup getups geum geums gewgaw gewgaws gewürztraminer gewürztraminers gey geyser geyserite geyserites geysers ghaghara ghaghra ghana ghanaian ghanaians gharial gharials gharries gharry ghast ghastful ghastfully ghastlier ghastliest ghastliness ghastly ghat ghats ghaut ghauts ghazi ghaziabad ghazies ghee ghees ghent gherkin gherkins ghetto ghettoed ghettoes ghettoing ghettoization ghettoizations ghettoize ghettoized ghettoizes ghettoizing ghettos ghi ghibelline ghibellines ghibli ghiblis ghillie ghillies ghis ghost ghosted ghosting ghostings ghostlier ghostliest ghostlike ghostliness ghostly ghosts ghostweed ghostweeds ghostwrite ghostwriter ghostwriters ghostwrites ghostwriting ghostwritten ghostwrote ghosty ghoul ghoulish ghoulishly ghoulishness ghouls giant giantess giantesses giantism giantisms giantlike giants giaour giaours giardia giardias giardiasis gib gibbed gibber gibbered gibberellic gibberellin gibberellins gibbering gibberish gibbers gibbet gibbeted gibbeting gibbets gibbetted gibbetting gibbing gibbon gibbons gibbosities gibbosity gibbous gibbously gibbousness gibe gibed gibeon gibeonite gibeonites giber gibers gibes gibing gibingly giblet giblets gibraltar gibraltarian gibraltarians gibs gibson gibsons gid giddap giddied giddier giddies giddiest giddily giddiness giddy giddyap giddying giddyup gideon gids gie gied gieing gies gift giftable giftables gifted giftedly giftedness gifting gifts giftware giftwares gig gigaampere gigaamperes gigabecquerel gigabecquerels gigabit gigabits gigabyte gigabytes gigacandela gigacandelas gigacoulomb gigacoulombs gigacycle gigacycles gigafarad gigafarads gigaflop gigaflops gigagram gigagrams gigahenries gigahenry gigahenrys gigahertz gigajoule gigajoules gigakelvin gigakelvins gigalumen gigalumens gigalux gigameter gigameters gigamole gigamoles giganewton giganewtons gigantesque gigantic gigantically gigantism gigantisms gigaohm gigaohms gigapascal gigapascals gigaradian gigaradians gigas gigasecond gigaseconds gigasiemens gigasievert gigasieverts gigasteradian gigasteradians gigatesla gigateslas gigaton gigatons gigavolt gigavolts gigawatt gigawatts gigaweber gigawebers gigged gigging giggle giggled giggler gigglers giggles giggling gigglingly giggly gigolo gigolos gigot gigots gigs gigue gigues gikuyu gikuyus gila gilbert gilbertian gilberts gilboa gild gildas gilded gilder gilders gilding gildings gilds gilead giles gilgamesh gill gilled giller gillers gillette gillie gillied gillies gilling gillnet gillnets gillnetted gillnetting gills gillyflower gillyflowers gillying gilsonite gilt gilts gimbal gimbaled gimbaling gimballed gimballing gimbals gimcrack gimcrackery gimcracks gimel gimels gimignano gimlet gimleted gimleting gimlets gimmal gimmals gimme gimmes gimmick gimmicked gimmicking gimmickries gimmickry gimmicks gimmicky gimp gimped gimping gimps gimpy gin ginger gingerbread gingerbreaded gingerbreads gingerbready gingered gingering gingerliness gingerly gingerroot gingerroots gingers gingersnap gingersnaps gingery gingham ginghams gingiva gingivae gingival gingivectomies gingivectomy gingivitis gingko gingkoes gink ginkgo ginkgoes ginks ginned ginner ginners ginning ginny gins ginsberg ginseng ginsengs ginzo ginzoes giorgione giotto giovanni gip gipped gipping gips gipsies gipsy giraffe giraffes giraffish girandole girandoles girasol girasole girasoles girasols gird girded girder girders girding girdle girdled girdler girdlers girdles girdling girds girl girlfriend girlfriends girlhood girlie girlies girlish girlishly girlishness girls girly girn girned girning girns giro giroed giroes giroing giron gironde girondin girondins girondist girondists girons giros girosol girosols girt girted girth girthed girthing girths girting girts gisarme gisarmes gismo gismos gist gists git gite gites gittern gitterns giulia giuseppe give giveaway giveaways giveback givebacks given givens giver givers gives giving gizmo gizmos gizzard gizzards glabella glabellae glabellar glabrate glabrescent glabrous glabrousness glacial glacially glaciate glaciated glaciates glaciating glaciation glaciations glacier glaciered glaciers glaciologic glaciological glaciologist glaciologists glaciology glacis glacé glacéed glacéing glacés glad gladded gladden gladdened gladdening gladdens gladder gladdest gladding glade glades gladiate gladiator gladiatorial gladiators gladiola gladiolas gladioli gladiolus gladioluses gladly gladness glads gladsome gladsomely gladsomeness gladstone gladstones glady glagolithic glagolitic glaiket glaikit glair glaire glaires glairier glairiest glairs glairy glaive glaives glamor glamored glamorgan glamoring glamorization glamorizations glamorize glamorized glamorizer glamorizers glamorizes glamorizing glamorless glamorous glamorously glamorousness glamors glamour glamoured glamouring glamourization glamourizations glamourize glamourized glamourizer glamourizers glamourizes glamourizing glamourous glamourously glamourousness glamours glance glanced glances glancing glancingly gland glandered glanderous glanders glandes glandless glands glandular glandularly glans glare glared glares glarier glariest glaring glaringly glaringness glary glasgow glasnost glass glassblower glassblowers glassblowing glassed glasses glassfish glassfishes glassful glassfuls glasshouse glasshouses glassie glassier glassies glassiest glassily glassine glassines glassiness glassing glassless glasslike glassmaker glassmakers glassmaking glassware glasswork glassworker glassworkers glassworks glasswort glassworts glassy glastonbury glaswegian glaswegians glauber glaucoma glaucomatous glauconite glauconites glauconitic glaucous glaucousness glaze glazed glazer glazers glazes glazier glazieries glaziers glaziery glazing glazings gleam gleamed gleamer gleamers gleaming gleams gleamy glean gleanable gleaned gleaner gleaners gleaning gleanings gleans gleba glebae glebe glebes glede gledes glee gleed gleeds gleeful gleefully gleefulness gleek gleeked gleeking gleeks gleeman gleemen glees gleesome gleet gleets gleety gleg glen glenda glendale glengarries glengarry glens gley gleys glia gliadin gliadins glial glias glib glibber glibbest glibly glibness glide glided glider gliders glides gliding glim glimmer glimmered glimmering glimmerings glimmers glimpse glimpsed glimpser glimpsers glimpses glimpsing glims glint glinted glintier glintiest glinting glints glinty glioma gliomas gliomata glissade glissaded glissader glissaders glissades glissading glissandi glissando glissandos glisten glistened glistening glistens glister glistered glistering glisters glitch glitches glitchy glitter glitterati glittered glittering glitteringly glitters glittertinden glittery glitz glitzed glitzes glitziness glitzing glitzy gloam gloaming gloams gloat gloated gloater gloaters gloating gloats glob global globalism globalisms globalist globalists globalization globalizations globalize globalized globalizer globalizers globalizes globalizing globally globals globate globe globed globefish globefishes globeflower globeflowers globes globetrot globetrots globetrotted globetrotter globetrotters globetrotting globin globing globins globoid globoids globose globosely globoseness globosity globous globs globular globularly globularness globule globules globuliferous globulin globulins glochid glochidia glochidiate glochidium glochids glockenspiel glockenspiels glogg gloggs glom glomera glomerate glomerular glomerulate glomerule glomerules glomeruli glomerulus glomma glommed glomming gloms glomus gloom gloomed gloomier gloomiest gloomily gloominess glooming glooms gloomy glop gloped gloping gloppy glops gloria gloriam gloriana glorias gloried glories glorification glorifications glorified glorifier glorifiers glorifies glorify glorifying gloriole glorioles gloriosi gloriosus glorious gloriously gloriousness glory glorying gloss glossa glossae glossal glossarial glossaries glossarist glossarists glossary glossas glossed glosser glossers glosses glossier glossies glossiest glossily glossiness glossing glossitic glossitis glossographer glossographers glossography glossolalia glossolalias glossolalist glossolalists glossopharyngeal glossy glottal glottides glottis glottises glottochronological glottochronology gloucester gloucestershire glout glouted glouting glouts glove gloved glover glovers gloves gloving glow glowed glower glowered glowering gloweringly glowers glowing glowingly glows glowworm glowworms gloxinia gloxinias gloze glozed glozes glozing glucagon gluck glucocorticoid glucocorticoids gluconeogenesis gluconeogenetic glucose glucoside glucosides glucosidic glucosidically glue glued glueing glues gluey gluily gluiness gluing glum glumaceous glume glumes glumly glummer glummest glumness glums gluon gluons glut glutamate glutamates glutamic glutamine glutamines glutaraldehyde glutaraldehydes gluteal glutei gluten glutenous glutens glutethimide glutethimides gluteus glutinosity glutinous glutinously glutinousness gluts glutted glutting glutton gluttonies gluttonize gluttonized gluttonizes gluttonizing gluttonous gluttonously gluttonousness gluttons gluttony glycan glycans glyceraldehyde glyceraldehydes glyceric glyceride glycerides glycerin glycerinate glycerinated glycerinates glycerinating glycerine glycerines glycerins glycerol glycerolize glycerolized glycerolizes glycerolizing glycerols glyceryl glyceryls glycin glycine glycines glycins glycogen glycogenesis glycogenetic glycogenic glycogenolyses glycogenolysis glycogenolytic glycogens glycol glycolic glycolipid glycolipids glycols glycolyses glycolysis glycolytic glycopeptide glycopeptides glycoprotein glycoproteins glycosaminoglycan glycosaminoglycans glycosidase glycosidases glycoside glycosides glycosidic glycosidically glycosuria glycosuric glycosyl glycosylate glycosylated glycosylates glycosylating glycosylation glycosyls glycyl glycyls glyph glyphic glyphs glyptic glyptics glyptograph glyptographer glyptographers glyptographic glyptographical glyptographs glyptography glåma glögg glöggs gmelina gmelinas gnar gnarl gnarled gnarling gnarls gnarly gnarr gnarred gnarring gnarrs gnars gnash gnashed gnashes gnashing gnat gnatcatcher gnatcatchers gnathal gnathic gnathite gnathites gnats gnatty gnaw gnawed gnawer gnawers gnawing gnaws gneiss gneisses gneissic gneissoid gneissose gniezno gnocchi gnome gnomelike gnomes gnomic gnomish gnomon gnomonic gnomonical gnomons gnosis gnostic gnosticism gnostics gnotobiotic gnotobiotically gnu gnus go goa goad goaded goading goads goal goaled goalie goalies goaling goalkeeper goalkeepers goalless goalpost goalposts goals goaltender goaltenders goaltending goaltendings goanese goas goat goatee goateed goatees goatfish goatfishes goatherd goatherds goatish goatlike goats goatsbeard goatskin goatskins goatsucker goatsuckers gob gobbet gobbets gobble gobbled gobbledegook gobbledygook gobbler gobblers gobbles gobbling gobelin gobelins gobi gobies goblet goblets goblin goblins gobo goboes gobos gobs goby god godalmighty godavari godchild godchildren goddam goddamn goddamned goddamning goddamns goddams goddard goddaughter goddaughters godded goddess goddesses godding godfather godfathered godfathering godfathers godforsaken godhead godheads godhood godhoods godiva godless godlessly godlessness godlier godliest godlike godlikeness godliness godling godlings godly godmother godmothered godmothering godmothers godown godowns godoxious godparent godparents gods godsend godsends godson godsons godspeed godspeeds godthåb godunov godwit godwits goebbels goer goering goers goes goethe goethite goethites gofer gofers goffer goffered goffering goffers goggle goggled goggler gogglers goggles goggling goggly gogh gogol gogra goidelic going goings goiter goiters goitre goitres goitrogen goitrogenic goitrogenicity goitrous goiânia golan golconda golcondas gold goldbeater goldbeaters goldbeating goldbeatings goldberg goldbergian goldbrick goldbricked goldbricker goldbrickers goldbricking goldbricks goldbug goldbugs golden goldeneye goldeneyes goldenly goldenness goldenrod goldenrods goldenseal goldenseals goldfield goldfields goldfinch goldfinches goldfish goldfishes goldilocks golds goldsmith goldsmiths goldstone goldstones goldthread goldthreads goldwyn golem golems golf golfed golfer golfers golfing golflinks golfs golgi golgotha golgothas goliard goliardic goliards goliath goliaths gollancz golliwog golliwogg golliwoggs golliwogs golly gombeen gombeens gomorrah gomorrahs gomphoses gomphosis gonad gonadal gonadectomies gonadectomized gonadectomy gonadic gonadotrophic gonadotrophin gonadotrophins gonadotropic gonadotropin gonadotropins gonads gond gondi gondola gondolas gondolier gondoliers gonds gondwana gondwanaland gondwanalands gone goner goneril goners gonfalon gonfalonier gonfaloniers gonfalons gong gonged gonging gongorism gongorisms gongoristic gongs gonidia gonidial gonidium gonif gonifs goniometer goniometers goniometric goniometrical goniometry gonion gonions gonococcal gonococci gonococcic gonococcus gonocyte gonocytes gonophore gonophores gonophoric gonophorous gonopore gonopores gonorrhea gonorrheal gonorrheic gonzo goo goober goobers good goodbye goodbyes gooder gooders goodhearted goodheartedly goodheartedness goodie goodies goodish goodlier goodliest goodliness goodly goodman goodmen goodness goodnight goodnights goods goodwife goodwill goodwills goodwin goodwives goody goodyear gooey goof goofball goofballs goofed goofier goofiest goofily goofiness goofing goofproof goofs goofy googol googolplex googolplexes googols gooier gooiest gook gooks goombah goombahs goon gooney gooneys goonies goons goony goop goops goopy goos goosander goosanders goose gooseberries gooseberry goosed goosefish goosefishes gooseflesh goosefoot goosefoots gooseneck goosenecked goosenecks gooses goosestep goosestepped goosestepping goosesteps goosey goosier goosiest goosing goosy gopher gophers gorbachev gordian gordon gordons gore gored gores gorge gorged gorgeous gorgeously gorgeousness gorger gorgerin gorgerins gorgers gorges gorget gorgets gorging gorgon gorgonian gorgonians gorgonize gorgonized gorgonizes gorgonizing gorgons gorgonzola gorier goriest gorilla gorillas gorily goriness goring gorki gorky gormandize gormandized gormandizer gormandizers gormandizes gormandizing gormless gorp gorps gorse gorses gorsy gory gosh goshawk goshawks goshen gosiute gosiutes gosling goslings gospel gospeler gospelers gospeller gospellers gospels gosport gosports gossamer gossamers gossamery gossan gossans gossip gossiped gossiper gossipers gossiping gossipmonger gossipmongers gossipries gossipry gossips gossipy gossypol gossypols got goth gotha gotham gothamite gothamites gothenburg gothic gothically gothicism gothicisms gothicist gothicists gothicize gothicized gothicizes gothicizing goths gotland gotten gotterdammerung gotterdämmerung gotthard gottwaldov gouache gouaches gouda gouge gouged gouger gougers gouges gouging goulash goulashes gounod gourami gouramis gourd gourde gourdes gourds gourmand gourmandise gourmandises gourmandism gourmandize gourmandized gourmandizes gourmandizing gourmandlike gourmands gourmet gourmets gout goutiness gouts goutweed goutweeds gouty govern governable governance governances governed governess governesses governessy governing government governmental governmentalism governmentalist governmentalists governmentalize governmentalized governmentalizes governmentalizing governmentally governmentese governments governor governorate governorates governors governorship governorships governs gowan gowans gowany gown gowned gowning gowns gownsman gownsmen goy goya goyim goyish goys goût graaff graafian grab grabbed grabber grabbers grabbier grabbiest grabbiness grabbing grabble grabbled grabbler grabblers grabbles grabbling grabby graben grabens grabs grace graced graceful gracefully gracefulness graceless gracelessly gracelessness graces gracile gracileness gracility gracing gracioso graciosos gracious graciously graciousness grackle grackles grad gradable gradate gradated gradates gradating gradation gradational gradationally gradations grade graded gradeless grader graders grades gradient gradients gradin gradine gradines grading gradings gradins gradiometer gradiometers grads gradual gradualism gradualist gradualistic gradualists gradually gradualness graduals graduand graduands graduate graduated graduates graduating graduation graduations graduator graduators graffiti graffitist graffitists graffito graft graftage graftages grafted grafter grafters grafting grafts graham grahams grail grails grain grained grainer grainers grainfield grainfields grainier grainiest graininess graining grains grainy gram grama gramarye gramaryes gramas gramercy gramicidin gramineous gramineousness graminivorous gramma grammar grammarian grammarians grammars grammas grammatical grammaticality grammatically grammaticalness grammatologic grammatological grammatologist grammatologists grammatology gramme grammes grammies grammy gramophone gramophones gramp grampian gramps grampus grampuses grams grana granada granadilla granadillas granaries granary grand grandad grandaddies grandaddy grandads grandam grandame grandames grandams grandaunt grandaunts grandbabies grandbaby grandchild grandchildren granddad granddaddies granddaddy granddads granddaughter granddaughters grande grandee grandees grander grandest grandeur grandeurs grandfather grandfathered grandfathering grandfatherly grandfathers grandiloquence grandiloquent grandiloquently grandiose grandiosely grandioseness grandiosity grandioso grandkid grandkids grandly grandma grandmas grandmaster grandmasters grandmother grandmotherly grandmothers grandnephew grandnephews grandness grandniece grandnieces grandpa grandparent grandparental grandparenthood grandparents grandpas grands grandsir grandsire grandsires grandsirs grandson grandsons grandstand grandstanded grandstander grandstanders grandstanding grandstands granduncle granduncles grange granger grangerism grangers granges granite granites graniteware granitewares granitic granitoid granivorous grannie grannies granny granola granolas granolith granolithic granoliths granophyre granophyres granophyric grant grantable granted grantee grantees granter granters granting grantor grantors grants grantsman grantsmanship grantsmanships grantsmen granular granularity granularly granulate granulated granulates granulating granulation granulations granulative granulator granulators granule granules granulite granulites granulitic granulize granulized granulizes granulizing granulocyte granulocytes granulocytic granulocytopoiesis granuloma granulomas granulomata granulomatous granulose granum grape grapefruit grapefruits grapes grapeshot grapeshots grapevine grapevines grapey graph graphed grapheme graphemes graphemic graphemically graphemics graphic graphical graphically graphicness graphics graphing graphite graphites graphitic graphitizable graphitization graphitize graphitized graphitizes graphitizing graphological graphologies graphologist graphologists graphology graphotype graphotypes graphs grapier grapiest grapiness grapnel grapnels grappa grappas grapple grappled grappler grapplers grapples grappling grapplings graptolite graptolites grapy gras grasp graspable grasped grasper graspers grasping graspingly graspingness grasps grass grassed grasser grassers grasses grassfire grassfires grasshopper grasshoppers grassier grassiest grassing grassland grasslands grasslike grassplot grassplots grassroots grassy grat grata grate grated grateful gratefully gratefulness grater graters grates gratia gratian gratias graticule graticules gratification gratifications gratified gratifier gratifiers gratifies gratify gratifying gratifyingly gratin grating gratingly gratings gratins gratis gratitude gratuities gratuitous gratuitously gratuitousness gratuity gratulate gratulated gratulates gratulating gratulation gratulations gratulatory graupel graupels gravamen gravamens gravamina grave graved gravedigger gravediggers gravel graveled graveless graveling gravelled gravelling gravelly gravels gravely graven graveness graver gravers graves graveside gravesides gravesite gravesites gravest gravestone gravestones graveyard graveyards gravid gravida gravidae gravidas gravidities gravidity gravidly gravidness gravies gravimeter gravimeters gravimetric gravimetrical gravimetrically gravimetry graving gravis gravisphere gravispheres gravitas gravitate gravitated gravitater gravitaters gravitates gravitating gravitation gravitational gravitationally gravitations gravitative gravities graviton gravitons gravity gravlax gravure gravures gravy gray graybeard graybeards grayed grayer grayest grayfish grayfishes graying grayish graylag graylags grayling graylings grayly graymail graymails grayness grays graysbies graysby graywacke graywackes graz grazable graze grazeable grazed grazer grazers grazes grazier graziers grazing grazings grazioso grease greased greaseless greasepaint greasepaints greaseproof greaser greasers greases greasewood greasier greasiest greasily greasiness greasing greasy great greatcoat greatcoats greaten greatened greatening greatens greater greatest greathearted greatheartedly greatheartedness greatly greatness greats greave greaves grebe grebes grecian grecianize grecianized grecianizes grecianizing grecians grecism grecisms grecize grecized grecizes grecizing greco gree greece greed greedier greediest greedily greediness greedy greeing greek greeks green greenback greenbacker greenbackers greenbackism greenbacks greenbelt greenbelts greenbrier greenbriers greenbug greenbugs greene greened greener greeneries greenery greenest greenfinch greenfinches greenflies greenfly greengage greengages greengrocer greengroceries greengrocers greengrocery greenhead greenheads greenheart greenhearts greenhorn greenhorns greenhouse greenhouses greenie greenies greening greenings greenish greenishness greenland greenlander greenlanders greenlandic greenlet greenlets greenling greenlings greenly greenmail greenmailer greenmailers greenmails greenmarket greenmarkets greenness greenockite greenockites greenroom greenrooms greens greensand greensands greenshank greenshanks greensick greensickness greenside greenskeeper greenskeepers greenstick greenstone greenstones greensward greenway greenways greenwich greenwood greenwoods greeny grees greet greeted greeter greeters greeting greetings greets gregarine gregarines gregarinian gregarious gregariously gregariousness gregorian gregory greige greisen greisens gremlin gremlins grenada grenade grenades grenadian grenadians grenadier grenadiers grenadine grenadines grendel grenoble gresham gressorial grew grewsome grex grexs grey greyed greyer greyest greyhen greyhens greyhound greyhounds greying greyish greylag greylags greyness greys gribble gribbles grid gridded gridder gridders griddle griddlecake griddlecakes griddled griddles griddling gridiron gridirons gridlock gridlocked gridlocking gridlocks grids grief griefs grieg grievance grievances grievant grievants grieve grieved griever grievers grieves grieving grievingly grievous grievously grievousness griffin griffins griffon griffons grift grifted grifter grifters grifting grifts grig grigri grigris grigs grill grillage grillages grille grilled griller grilleries grillers grillery grilles grilling grillroom grillrooms grills grillwork grilse grim grimace grimaced grimacer grimacers grimaces grimacing grimalkin grimalkins grime grimed grimes grimier grimiest grimily griminess griming grimly grimm grimmer grimmest grimness grimsel grimy grin grind grinder grinders grinding grindingly grindings grinds grindstone grindstones gringo gringos grinned grinner grinners grinning grinningly grins griot griots grip gripe griped griper gripers gripes griping grippe gripped gripper grippers grippes gripping grippingly grippy grips gripsack gripsacks gris grisaille grisailles grise griselda griseofulvin griseofulvins griseous grises grisette grisettes grislier grisliest grisliness grisly grison grisons grist gristle gristles gristlier gristliest gristliness gristly gristmill gristmills grit grith griths grits gritted grittier grittiest grittily grittiness gritting gritty grivet grivets grizzle grizzled grizzles grizzlier grizzlies grizzliest grizzling grizzly groan groaned groaner groaners groaning groaningly groans groat groats groatss grocer groceries grocers grocery grog groggier groggiest groggily grogginess groggy grogram grograms grogs grogshop grogshops groin groined groining groins grok grokked grokking groks grolier grommet grommets gromwell gromwells groom groomed groomer groomers grooming grooms groomsman groomsmen groove grooved groover groovers grooves groovier grooviest grooviness grooving groovy grope groped groper gropers gropes groping gropingly gropings grosbeak grosbeaks groschen grosgrain grosgrains gross grossed grosser grossers grosses grossest grossglockner grossing grossly grossness grossular grossularite grossularites grossulars grosz groszy grot grotesque grotesquely grotesqueness grotesquerie grotesqueries grotesquery grotesques grots grottier grottiest grottiness grotto grottoes grottos grotty grouch grouched grouches grouchier grouchiest grouchily grouchiness grouching grouchy ground groundbreaker groundbreakers groundbreaking groundbreakings grounded grounder grounders groundhog groundhogs grounding groundkeeper groundkeepers groundless groundlessly groundlessness groundling groundlings groundmass groundmasses groundnut groundnuts groundout groundouts grounds groundsel groundsels groundsheet groundsheets groundside groundsides groundsill groundsills groundskeeper groundskeepers groundskeeping groundsman groundsmen groundstroke groundstrokes groundswell groundswells groundwater groundwork group groupable grouped grouper groupers groupie groupies grouping groupings groups groupthink groupthinks grouse groused grouser grousers grouses grousing grout grouted grouter grouters grouting grouts grove grovel groveled groveler grovelers groveling grovelingly grovelled grovelling grovels groves grow grower growers growing growingly growl growled growler growlers growlier growliest growliness growling growlingly growls growly grown grownup grownups grows growth growths groyne groynes grub grubbed grubber grubbers grubbier grubbiest grubbily grubbiness grubbing grubby grubs grubstake grubstaked grubstaker grubstakers grubstakes grubstaking grudge grudged grudger grudgers grudges grudging grudgingly grudziadz gruel grueling gruelingly gruelling gruesome gruesomely gruesomeness gruff gruffer gruffest gruffly gruffness grumble grumbled grumbler grumblers grumbles grumbling grumblingly grumbly grummet grummets grump grumped grumpier grumpiest grumpily grumpiness grumping grumps grumpy grundy grunge grunges grungier grungiest grungy grunion grunions grunt grunted grunter grunters grunting gruntingly gruntle gruntled gruntles gruntling grunts grus grutten gruyere gruyère gryphon gryphons grâce guacamole guacharo guacharos guadalajara guadalcanal guadalquivir guadalupe guadeloupe guadeloupian guadeloupians guaiac guaiacol guaiacols guaiacs guaiacum guaiacums guam guamanian guamanians guan guanabara guanaco guanacos guanethidine guanethidines guangdong guangxi guangzhou guanidine guanine guanines guano guanos guanosine guanosines guans guantánamo guanylic guaporé guar guarani guaranies guaranis guarantee guaranteed guaranteeing guarantees guarantied guaranties guarantor guarantors guaranty guarantying guard guardant guardants guarded guardedly guardedness guarder guarders guardhouse guardhouses guardian guardians guardianship guardianships guarding guardmember guardmembers guardrail guardrails guardroom guardrooms guards guardsman guardsmen guarneri guarnerius guars guatemala guatemalan guatemalans guava guavas guayaquil guayule guayules gubernator gubernatorial gubernators guck gudgeon gudgeons gudrun guelder guelf guelfs guelph guelphs guenevere guenon guenons guerdon guerdoned guerdoning guerdons gueridon gueridons guerilla guerillas guernica guernsey guernseys guerre guerrilla guerrillas guess guessed guesser guessers guesses guessing guesstimate guesstimated guesstimates guesstimating guesswork guest guested guesthouse guesthouses guesting guestroom guestrooms guests guff guffaw guffawed guffawing guffaws guffs guggenheim guggle guggled guggles guggling guianese guidable guidance guide guideboard guideboards guidebook guidebooks guided guideline guidelines guidepost guideposts guider guiders guides guideway guideways guideword guidewords guiding guidon guidons guienne guignol guild guildenstern guilder guilders guildhall guildhalls guilds guildship guildsman guildsmen guile guiled guileful guilefully guilefulness guileless guilelessly guilelessness guiles guiling guillemot guillemots guilloche guilloches guillotine guillotined guillotines guillotining guilt guiltier guiltiest guiltily guiltiness guiltless guiltlessly guiltlessness guilty guimpe guimpes guinea guinean guineans guineas guinevere guinness guipure guipures guiro guisard guisards guise guises guitar guitarfish guitarfishes guitarist guitarists guitars gujarat gujarati gujaratis gujerati gujeratis gujranwala gul gulag gulags gular gulch gulches gulden guldens gules guleses gulf gulfed gulfing gulfs gulfweed gulfweeds gull gullability gullable gullably gullah gulled gullet gullets gulley gullibility gullible gullibly gullied gullies gulling gulliver gulls gullwing gully gullying gulosities gulosity gulp gulped gulper gulpers gulping gulpingly gulps guls gum gumball gumballs gumbo gumboil gumboils gumbos gumdrop gumdrops gumma gummas gummata gummatous gummed gummer gummers gummier gummiest gumminess gumming gummite gummites gummose gummoses gummosis gummous gummy gumption gums gumshoe gumshoed gumshoeing gumshoes gumwood gumwoods gun gunboat gunboats guncotton gundog gundogs gunfight gunfighter gunfighters gunfights gunfire gunflint gunflints gung gunite gunites gunk gunky gunlock gunlocks gunman gunmen gunmetal gunmetals gunnar gunnbjørn gunned gunnel gunnels gunner gunnera gunneras gunneries gunners gunnery gunnies gunning gunnings gunny gunnysack gunnysacks gunplay gunpoint gunpoints gunpowder gunpowders gunroom gunrooms gunrunner gunrunners gunrunning guns gunsel gunsels gunship gunships gunshot gunshots gunslinger gunslingers gunslinging gunsmith gunsmiths gunstock gunstocks gunther gunwale gunwales guoyu guoyus guppies guppy gurdies gurdy gurgitation gurgitations gurgle gurgled gurgles gurgling gurglingly gurkha gurkhas gurnard gurnards gurney gurneys gurries gurry guru gurus gush gushed gusher gushers gushes gushier gushiest gushily gushiness gushing gushingly gushy gusset gusseted gusseting gussets gussied gussies gussy gussying gust gustation gustations gustative gustatorily gustatory gustavus gusted gustier gustiest gustily gustiness gusting gusto gustoes gusts gusty gut gutbucket gutbuckets gutenberg guthrie guthrun gutless gutlessly gutlessness guts gutsier gutsiest gutsily gutsiness gutsy gutta guttae guttate guttated guttation guttations gutted gutter guttered guttering gutters guttersnipe guttersnipes guttersnipish guttier guttiest gutting guttural gutturalism gutturality gutturalization gutturalizations gutturalize gutturalized gutturalizes gutturalizing gutturally gutturalness gutturals gutty guy guyana guyanese guyed guyenne guying guyot guyots guys guzzle guzzled guzzler guzzlers guzzles guzzling gweduc gweducs gwent gwynedd gybe gybed gybes gybing gym gymkhana gymkhanas gymnasia gymnasium gymnasiums gymnast gymnastic gymnastically gymnastics gymnasts gymnosophist gymnosophists gymnosperm gymnospermous gymnosperms gymnospermy gyms gynandries gynandromorph gynandromorphic gynandromorphism gynandromorphous gynandromorphy gynandrous gynandry gynarchic gynarchies gynarchy gynecocracies gynecocracy gynecocratic gynecoid gynecologic gynecological gynecologist gynecologists gynecology gynecomastia gynecopathies gynecopathy gynocracies gynocracy gynodioecious gynodioecism gynoecia gynoecium gynogenesis gynophore gynophores gynophoric gyoza gyozas gyoár gyp gypped gypper gyppers gypping gyps gypseous gypsied gypsies gypsiferous gypsophila gypsophilas gypsophile gypsophiles gypsum gypsums gypsy gypsying gyral gyrally gyrate gyrated gyrates gyrating gyration gyrational gyrations gyrator gyrators gyratory gyre gyred gyrene gyrenes gyres gyrfalcon gyrfalcons gyri gyring gyro gyrocompass gyrocompasses gyrofrequency gyromagnetic gyron gyrons gyroplane gyroplanes gyros gyroscope gyroscopes gyroscopic gyroscopically gyrostabilizer gyrostabilizers gyrostat gyrostatic gyrostatically gyrostats gyrus gyve gyved gyves gyving gâteau gâteaux gît göta göteborg götterdämmerung götterdämmerungs göttingen gütersloh h ha haakon haarlem haarlemmermeer habakkuk habanera habaneras habdalah habdalahs habeas haber haberdasher haberdasheries haberdashers haberdashery habergeon habergeons habile habiliment habiliments habilitate habilitated habilitates habilitating habilitation habilitations habit habitability habitable habitableness habitably habitan habitans habitant habitants habitat habitation habitations habitats habited habiting habits habitual habitually habitualness habituate habituated habituates habituating habituation habituations habitude habitudes habitus habitué habitués haboob haboobs habsburg habsburgs hacek haceks hachinohe hachioji hachure hachured hachures hachuring hacienda haciendas hack hackable hackamore hackamores hackberries hackberry hackbut hackbuteer hackbuteers hackbuts hackbutter hackbutters hacked hackensack hacker hackers hackie hackies hacking hackle hackleback hacklebacks hackled hackler hacklers hackles hackling hackly hackman hackmatack hackmatacks hackmen hackney hackneyed hackneying hackneys hacks hacksaw hacksawed hacksawing hacksaws hackwork had hadal haddie haddock haddocks hade hadean hades hadith hadj hadjes hadji hadjis hadley hadn hadn't hadrian hadron hadronic hadrons hadrosaur hadrosaurs hadst hae haeckel haed haeing haen haes haet haets hafez haffet haffets hafiz hafizes hafnium haft haftarah hafted hafting haftorah hafts hafun hag hagar hagen hagerstown hagfish hagfishes haggada haggadah haggadic haggadist haggadistic haggadists haggadoth haggai haggard haggardly haggardness haggards haggis haggises haggish haggishly haggishness haggle haggled haggler hagglers haggles haggling hagiarchies hagiarchy hagiocracies hagiocracy hagiographa hagiographer hagiographers hagiographic hagiographical hagiographies hagiography hagiolatries hagiolatry hagiologic hagiological hagiologies hagiologist hagiologists hagiology hagioscope hagioscopes hagioscopic hagridden hagride hagrides hagriding hagrode hags hague hah hahn hahnemann hahnium haick haida haidan haidas haifa haig haighthaicks haik haikou haiks haiku haikus hail haile hailed hailer hailers hailing hails hailstone hailstones hailstorm hailstorms haimish hainan hainault hainaut haiphong hair hairball hairballs hairbreadth hairbreadths hairbrush hairbrushes haircloth haircloths haircut haircuts haircutter haircutters haircutting haircuttings hairdo hairdos hairdresser hairdressers hairdressing hairdressings hairdryer hairdryers haired hairier hairiest hairiness hairless hairlessness hairlike hairline hairlines hairnet hairnets hairpiece hairpieces hairpin hairpins hairs hairsbreadth hairsbreadths hairsplitter hairsplitters hairsplitting hairsplittings hairspray hairsprays hairspring hairsprings hairstreak hairstreaks hairstyle hairstyles hairstyling hairstylings hairstylist hairstylists hairweave hairweaver hairweavers hairweaves hairweaving hairweavings hairworm hairworms hairwove hairwoven hairy haiti haitian haitians haj hajes haji hajis hajj hajjes hajji hajjis haka hakas hake hakeem hakeems hakenkreuz hakenkreuzes hakes hakim hakims hakluyt hakodate haku hakus halacha halachas halakah halakahs halakic halal halala halalas halals halation halations halavah halavahs halberd halberdier halberdiers halberds halbert halberts halcyon halcyons haldane hale haleakala haled haleness haler halers haleru hales halest halethorpe haley half halfback halfbacks halfbeak halfbeaks halfcocked halfhearted halfheartedly halfheartedness halfness halfpence halfpennies halfpenny halfpennyworth halftime halftimes halftone halftones halftoning halfway halfwit halfwits halfword halfwords halibut halibuts halicarnassus halide halides halidom halidome halidomes halidoms halifax haling halite halitosis hall hallah hallahs hallandale hallel hallels hallelujah hallelujahs halley halliard halliards hallmark hallmarked hallmarking hallmarks hallo halloa halloaed halloaing halloas halloed halloo hallooed hallooing halloos hallos hallow hallowe hallowe'en hallowe'ens hallowed halloween halloweens hallowing hallowmas hallowmases hallowmass hallows halls hallstatt halluces hallucinate hallucinated hallucinates hallucinating hallucination hallucinational hallucinations hallucinative hallucinator hallucinators hallucinatory hallucinogen hallucinogenic hallucinogens hallucinosis hallux hallway hallways halma halmahera halo halobiont halobionts halocarbon halocarbons halocline haloclines haloed haloes halogen halogenate halogenated halogenates halogenating halogenation halogenations halogenous halogens haloing halomorphic halon halons haloperidol halophile halophiles halophilic halophilous halophyte halophytes halophytic halos halothane halothanes halsted halt halted haltemprice halter halterbreak halterbreaking halterbreaks halterbroke halterbroken haltere haltered halteres haltering halters halting haltingly halts halva halvah halvahs halvas halve halved halvers halves halving halyard halyards halévy ham hama hamadan hamadryad hamadryades hamadryads hamadryas hamadryases hamah hamal hamals hamamatsu haman hamartia hamartias hamate hamates hamburg hamburger hamburgers hamburgs hamden hame hamelin hameln hames hamilcar hamilton hamiltonian hamiltonians hamite hamites hamitic hamitics hamito hamlet hamlets hamlin hammal hammals hammarskjöld hammed hammer hammered hammerer hammerers hammerfest hammerhead hammerheads hammering hammerkop hammerkops hammerless hammerlock hammerlocks hammers hammerstein hammertoe hammertoes hammier hammiest hammily hamminess hamming hammock hammocks hammond hammurabi hammy hamper hampered hampering hampers hampshire hampton hams hamster hamsters hamstring hamstringing hamstrings hamstrung hamtramck hamuli hamulus hamza hamzah hamzahs hamzas han hanau hancock hand handan handbag handbags handball handballs handbarrow handbarrows handbill handbills handblown handbook handbooks handbrake handbrakes handbreadth handbreadths handcar handcars handcart handcarts handclap handclaps handclasp handclasps handcraft handcrafted handcrafter handcrafters handcrafting handcraftmanship handcrafts handcraftsman handcraftsmanship handcraftsmen handcuff handcuffed handcuffing handcuffs handed handedly handedness handel handelian hander handers handfast handfasts handful handfuls handgrip handgrips handgun handguns handheld handhelds handhold handholding handholdings handholds handicap handicapped handicapper handicappers handicapping handicaps handicraft handicrafter handicrafters handicrafts handicraftsman handicraftsmen handicraftswoman handicraftswomen handier handies handiest handily handiness handing handiwork handkerchief handkerchiefs handkerchieves handle handleable handlebar handlebars handled handleless handler handlers handles handless handlin handling handlings handlist handlists handloom handlooms handmade handmaid handmaiden handmaidens handmaids handoff handoffs handout handouts handpick handpicked handpicking handpicks handpress handpresses handprint handprints handrail handrails hands handsaw handsaws handsbreadth handsel handseled handseling handselled handselling handsels handset handsets handsful handshake handshakes handshaking handsome handsomely handsomeness handsomer handsomest handspike handspikes handspring handsprings handstand handstands handwheel handwheels handwork handworker handworkers handwoven handwringer handwringers handwringing handwringings handwrite handwrites handwriting handwritings handwritten handwrote handwrought handy handyman handymen hang hangable hangar hangars hangchou hangchow hangdog hangdogs hanged hanger hangers hanging hangings hangman hangmen hangnail hangnails hangout hangouts hangover hangovers hangs hangtag hangtags hangzhou hank hanker hankered hankerer hankerers hankering hankerings hankers hankie hankies hanks hanky hannibal hanno hannover hanoi hanover hanoverian hanoverians hans hansa hansard hansards hanse hanseatic hansel hanseled hanseling hanselled hanselling hansels hansen hansen's hanses hansom hansoms hantan hantavirus hanukah hanukkah hanukkahs hanuman hanumans hao haole haoles haos hap hapax haphazard haphazardly haphazardness haphazardry haphtarah haphtaroth haphtoros haphtorot haphtoroth hapless haplessly haplessness haplite haplites haploid haploidies haploids haploidy haplology haplont haplonts haplosis haply happed happen happenchance happenchances happened happening happenings happens happenstance happenstances happi happier happiest happily happiness happinesses happing happy haps hapsburg hapsburgs hapten haptene haptenes haptenic haptens haptic haptoglobin haptoglobins hara haran harangue harangued haranguer haranguers harangues haranguing harappa harare harass harassed harasser harassers harasses harassing harassment harassments harbinger harbingered harbingering harbingers harbor harborage harborages harbored harborer harborers harborful harboring harborless harbormaster harbormasters harbors harbour harboured harbourer harbourers harbouring harbours hard hardback hardbacks hardball hardballs hardboard hardboards hardboiled hardboot hardboots hardbound hardbounds hardcase hardcopies hardcopy hardcore hardcover hardcovers hardecanute hardedge hardedges harden hardened hardener hardeners hardening hardenings hardens harder hardest hardfisted hardhack hardhacks hardhanded hardhandedness hardhat hardhats hardhead hardheaded hardheadedly hardheadedness hardheads hardhearted hardheartedly hardheartedness hardicanute hardier hardies hardiest hardihood hardily hardiment hardiness hardly hardmouthed hardness hardnesses hardpan hardpans hardscrabble hardscrabbles hardship hardships hardstand hardstanding hardstands hardtack hardtacks hardtop hardtops hardware hardwire hardwired hardwires hardwiring hardwood hardwoods hardworking hardy hare harebell harebells harebrain harebrained harebrains hared harelip harelipped harelips harem harems hares haricot haricots harijan harijans haring hark harked harken harkened harkening harkens harking harks harlem harlemite harlemites harlequin harlequinade harlequinades harlequins harlot harlotries harlotry harlots harlow harm harmattan harmattans harmed harmer harmers harmful harmfully harmfulness harming harmless harmlessly harmlessness harmolodic harmonic harmonica harmonically harmonicas harmonics harmonies harmonious harmoniously harmoniousness harmonist harmonistic harmonistically harmonists harmonium harmoniums harmonization harmonizations harmonize harmonized harmonizer harmonizers harmonizes harmonizing harmony harms harness harnessed harnesser harnessers harnesses harnessing harney harold harp harped harper harpers harpies harping harpist harpists harpoon harpooned harpooner harpooners harpooning harpoons harps harpsichord harpsichordist harpsichordists harpsichords harpy harquebus harquebuses harquebusier harquebusiers harran harridan harridans harried harrier harriers harries harriman harrington harris harrisburg harrison harrisonburg harrow harrowed harrower harrowers harrowing harrows harrumph harrumphed harrumphing harrumphs harry harrying harsh harshen harshened harshening harshens harsher harshest harshly harshness harslet harslets hart hartebeest hartebeests hartford harts hartshorn hartshorns harum haruspex haruspication haruspications haruspices harvard harvest harvestability harvestable harvested harvester harvesters harvesting harvestman harvestmen harvests harvesttime harvesttimes harvey haryana harz has hasdrubal hasenpfeffer hasenpfeffers hash hashana hashanah hashed hasheesh hashemite hashemites hasher hashers hashes hashimite hashimites hashing hashish hashishes hashona hashonah hasid hasidic hasidim hasidism haslet haslets hasmonaean hasmonean hasn hasn't hasp hasped hasping hasps hassid hassium hassle hassled hassles hassling hassock hassocks hast hasta hastate hastately haste hasted hasten hastened hastener hasteners hastening hastens hastes hastier hastiest hastily hastiness hasting hastings hasty hat hatband hatbands hatbox hatboxes hatch hatchability hatchable hatchback hatchbacks hatcheck hatchecks hatched hatchel hatcheled hatcheling hatchelled hatchelling hatchels hatcher hatcheries hatchers hatchery hatches hatchet hatchets hatching hatchings hatchling hatchlings hatchment hatchments hatchway hatchways hate hated hateful hatefully hatefulness hater haters hates hath hating hatless hatmaker hatmakers hatpin hatpins hatred hatreds hats hatshepsut hatted hatter hatteras hatters hattiesburg hatting haubergeon haubergeons hauberk hauberks haugh haughs haughtier haughtiest haughtily haughtiness haughty haul haulage haulages hauled hauler haulers hauling haulm haulms hauls haunch haunches haunt haunted haunter haunters haunting hauntingly haunts hauraki hausa hausas hausfrau hausfraus haustella haustellate haustellum haustoria haustorial haustorium haut hautbois hautboy hautboys haute hauteur havana havanan havanans havant havasupai havasupais havdalah havdalahs have haveli havelock havelocks haven haven't havened havening havens haver havered havering havers haversack haversacks haversian haves having havoc havocked havocking havocs havre haw hawaii hawaiian hawaiians hawed hawfinch hawfinches hawing hawk hawked hawker hawkers hawkeye hawkeyes hawking hawkins hawkish hawkishly hawkishness hawkmoth hawkmoths hawks hawksbill hawksbills hawkshaw hawkshaws hawkweed hawkweeds haworthia haworthias haws hawse hawsehole hawseholes hawser hawsers hawses hawthorn hawthorne hawthorns hay haycock haycocks haydn hayed hayer hayers hayes hayfield hayfields hayfork hayforks haying haylage haylages hayloft haylofts haymaker haymakers haymaking haymow haymows hayrack hayracks hayrick hayricks hayride hayrides hays hayseed hayseeds haystack haystacks haywire hazan hazanim hazard hazarded hazarding hazardous hazardously hazardousness hazards haze hazed hazel hazelnut hazelnuts hazels hazer hazers hazes hazier haziest hazily haziness hazing hazings hazleton hazlitt hazy hazzan hazzans he he'd he'll he's head headache headaches headachy headband headbands headboard headboards headcheese headcount headcounter headcounters headcounts headdress headdresses headed headedness header headers headfast headfasts headfirst headforemost headful headfuls headgate headgates headgear headhunt headhunted headhunter headhunters headhunting headhunts headier headiest headily headiness heading headings headlamp headlamps headland headlands headless headlessness headlight headlights headline headlined headliner headliners headlines headlining headlock headlocks headlong headman headmaster headmasters headmastership headmen headmistress headmistresses headmost headnote headnotes headphone headphones headpiece headpieces headpin headpins headquarter headquartered headquartering headquarters headrace headraces headrest headrests headroom heads headsail headsails headscarf headscarfs headscarves headset headsets headshake headshakes headshaking headship headships headshot headshots headshrinker headshrinkers headsman headsmen headspace headspaces headspring headsprings headstall headstalls headstand headstands headstock headstocks headstone headstones headstream headstreams headstrong headwaiter headwaiters headwall headwalls headwater headwaters headway headwear headwears headwind headwinds headword headwords headwork headworker headworkers heady heal healable healed healer healers healing heals health healthful healthfully healthfulness healthier healthiest healthily healthiness healths healthy heap heaped heaping heaps heapsort hear hearable heard hearer hearers hearing hearings hearken hearkened hearkening hearkens hears hearsay hearse hearsed hearses hearsing heart heartache heartaches heartbeat heartbeats heartbreak heartbreaker heartbreakers heartbreaking heartbreakingly heartbreaks heartbroken heartbrokenly heartbrokenness heartburn heartburning hearted heartedly heartedness hearten heartened heartening hearteningly heartens heartfelt hearth hearthrug hearthrugs hearths hearthside hearthsides hearthstone hearthstones heartier hearties heartiest heartily heartiness hearting heartland heartlands heartleaf heartleafs heartless heartlessly heartlessness heartrending heartrendingly hearts heartsease heartseases heartsick heartsickness heartsome heartsomely heartsore heartstring heartstrings heartthrob heartthrobs heartwarming heartwarmingly heartwood heartworm heartworms hearty heat heatable heated heatedly heater heaters heath heathen heathendom heathenish heathenishly heathenishness heathenism heathenize heathenized heathenizes heathenizing heathenry heathens heather heathers heathery heathless heathlike heathrow heaths heathy heating heatless heatproof heats heatstroke heatstrokes heave heaved heaven heavenliness heavenly heavens heavenward heavenwards heaver heavers heaves heavier heavies heaviest heavily heaviness heaving heaviside heavy heavyhearted heavyheartedly heavyheartedness heavyset heavyweight heavyweights hebdomad hebdomadal hebdomadally hebdomads hebe hebei hebephrenia hebephrenias hebephrenic hebetate hebetated hebetates hebetating hebetation hebetations hebetative hebetude hebetudes hebetudinous hebraic hebraical hebraically hebraism hebraist hebraistic hebraistical hebraistically hebraists hebraization hebraizations hebraize hebraized hebraizes hebraizing hebrew hebrews hebridean hebrideans hebrides hebron hecate hecatomb hecatombs heck heckelphone heckelphones heckle heckled heckler hecklers heckles heckling heckuva hectare hectares hectic hectically hectoampere hectoamperes hectobecquerel hectobecquerels hectocandela hectocandelas hectocotyli hectocotylus hectocoulomb hectocoulombs hectofarad hectofarads hectogram hectograms hectograph hectographed hectographic hectographically hectographing hectographs hectohenries hectohenry hectohenrys hectohertz hectojoule hectojoules hectokelvin hectokelvins hectoliter hectoliters hectolumen hectolumens hectolux hectometer hectometers hectomole hectomoles hectonewton hectonewtons hectoohm hectoohms hectopascal hectopascals hector hectoradian hectoradians hectored hectoring hectors hectosecond hectoseconds hectosiemens hectosievert hectosieverts hectosteradian hectosteradians hectotesla hectoteslas hectovolt hectovolts hectowatt hectowatts hectoweber hectowebers hecuba hedda heddle heddles heder heders hedge hedged hedgehog hedgehogs hedgehop hedgehopped hedgehopper hedgehoppers hedgehopping hedgehops hedgepig hedgepigs hedger hedgerow hedgerows hedgers hedges hedging hedgingly hedgy hedjaz hedonic hedonically hedonics hedonism hedonist hedonistic hedonistically hedonists hee heebie heed heeded heedful heedfully heedfulness heeding heedless heedlessly heedlessness heeds heehaw heehawed heehawing heehaws heel heelball heelballs heeled heeler heelers heeling heelless heelpiece heelpieces heelpost heelposts heels heeltap heeltaps heelwork heelworks heft hefted heftier heftiest heftily heftiness hefting hefts hefty hegang hegari hegaris hegel hegelian hegelianism hegelians hegemonic hegemonies hegemonism hegemonist hegemonists hegemony hegira hegiras heidelberg heifer heifers heigh height heighten heightened heightener heighteners heightening heightens heights heilbronn heilongjiang heilungkiang heimish heimlich heinie heinies heinous heinously heinousness heir heirdom heirdoms heiress heiresses heirless heirloom heirlooms heirs heirship heirships heisenberg heist heisted heisting heists hejaz hejira hejiras hekate hekla held heldentenor heldentenors helen helena helens helgoland heliacal heliacally heliborne helical helically helices helicoid helicoidal helicoids helicon helicons helicopter helicoptered helicoptering helicopters helicultural heliculturalist heliculturalists heliculture heligoland heliocentric heliocentrical heliocentricity heliogabalus heliograph heliographed heliographer heliographers heliographic heliographing heliographs heliography heliolatrous heliolatry heliometer heliometers heliometric heliometrical heliometrically heliometry heliopolis helios helioseismology heliosphere heliospheres heliostat heliostats heliotactic heliotaxis heliotaxises heliotherapies heliotherapy heliotrope heliotropes heliotropic heliotropically heliotropin heliotropins heliotropism heliotype heliotyped heliotypes heliotypic heliotyping heliotypy heliozoan heliozoans heliozoic helipad helipads heliport heliports helistop helistops helium helix helixes hell hellacious helladic hellas hellbender hellbenders hellbox hellboxes hellbroth hellcat hellcats helldiver helldivers hellebore hellebores helled hellene hellenes hellenian hellenians hellenic hellenism hellenist hellenistic hellenistical hellenists hellenization hellenizations hellenize hellenized hellenizer hellenizers hellenizes hellenizing heller helleri helleries hellers hellespont hellfire hellfires hellgrammite hellgrammites hellhole hellholes hellhound hellhounds helling hellion hellions hellish hellishly hellishness hello helloed helloes helloing hellos hells helluva helm helmed helmet helmeted helmeting helmetlike helmets helming helminth helminthiases helminthiasis helminthic helminthics helminthologist helminthologists helminthology helminths helms helmsman helmsmanship helmsmen helo helos helot helotism helotisms helotries helotry helots help helped helper helpers helpful helpfully helpfulness helping helpings helpless helplessly helplessness helpmate helpmates helpmeet helpmeets helps helsingborg helsingør helsinki helter helve helves helvetia helvetian helvetians helvetic helvetica helvetii hem hemacytometer hemacytometers hemagglutinate hemagglutinated hemagglutinates hemagglutinating hemagglutination hemagglutinations hemagglutinin hemagglutinins hemal hemangioma hemangiomas hemangiomata hemaphereses hemapheresis hematein hemateins hematic hematics hematin hematinic hematinics hematins hematite hematites hematitic hematoblast hematoblastic hematoblasts hematocrit hematocrits hematogenesis hematogenetic hematogenic hematogenous hematologic hematological hematologically hematologist hematologists hematology hematolysis hematoma hematomas hematomata hematophagous hematopoiesis hematopoietic hematoporphyrin hematoporphyrins hematothermia hematoxylin hematoxylins hematozoa hematozoal hematozoic hematozoon hematuria hematurias hematuric heme hemelytra hemelytron hemeralopia hemeralopias hemeralopic hemerocallis hemerocallises hemes hemialgia hemialgias hemic hemicellulose hemicelluloses hemichordate hemichordates hemicycle hemicycles hemidemisemiquaver hemidemisemiquavers hemihedral hemihydrate hemihydrated hemihydrates hemimetabolic hemimetabolism hemimetabolous hemimorphic hemimorphism hemimorphite hemimorphites hemin hemingway hemins hemiola hemiolas hemiparasite hemiparasites hemiparasitic hemiplegia hemiplegias hemiplegic hemiplegics hemipteran hemipterans hemipterous hemisphere hemispheres hemispheric hemispherical hemispherically hemistich hemistichs hemline hemlines hemlock hemlocks hemmed hemmer hemmers hemming hemochromatosis hemocoel hemocoels hemocyanin hemocyanins hemocyte hemocytes hemodialyses hemodialysis hemodynamic hemodynamically hemodynamics hemoflagellate hemoflagellates hemoglobin hemoglobinopathies hemoglobinopathy hemoglobins hemoglobinuria hemoglobinurias hemoglobinuric hemolymph hemolymphatic hemolymphs hemolysin hemolysins hemolysis hemolytic hemolyze hemolyzed hemolyzes hemolyzing hemophilia hemophiliac hemophiliacs hemophilic hemophobia hemophobic hemopoiesis hemopoietic hemoprotein hemoproteins hemoptysis hemorrhage hemorrhaged hemorrhages hemorrhagic hemorrhaging hemorrhoid hemorrhoidal hemorrhoidectomies hemorrhoidectomy hemorrhoids hemosiderin hemosiderins hemostasia hemostasis hemostat hemostatic hemostatics hemostats hemp hempen hemps hems hemstitch hemstitched hemstitcher hemstitchers hemstitches hemstitching hen henbane henbanes henbit henbits hence henceforth henceforward henchman henchmen hencoop hencoops hendecasyllabic hendecasyllabics hendecasyllable hendecasyllables hendiadys hendiadyses hendrix henequen henequens henequin henequins hengist henhouse henhouses henna hennaed hennaing hennas henneries hennery hennish hennishly hennishness henotheism henotheist henotheistic henotheists henpeck henpecked henpecking henpecks henries henry henrys hens hent hented henting hents hep heparin heparinize heparinized heparinizes heparinizing hepatic hepatica hepaticas hepatics hepatitides hepatitis hepatocellular hepatocyte hepatocytes hepatoma hepatomas hepatomata hepatomegalies hepatomegaly hepatotoxic hepatotoxicity hepatotoxin hepatotoxins hepcat hepcats hephaestos hephaestus hepper heppest hepplewhite heptachlor heptachlors heptad heptads heptagon heptagonal heptagons heptahedra heptahedral heptahedron heptahedrons heptameter heptameters heptane heptanes heptarchic heptarchical heptarchies heptarchy heptastich heptastiches heptateuch heptathlon heptathlons heptavalent heptose heptoses her hera heraclea heracles heraclitean heraclitus heraclius herakles herald heralded heraldic heraldically heralding heraldist heraldists heraldries heraldry heralds herb herbaceous herbage herbal herbalist herbalists herbals herbaria herbarium herbariums herbed herbert herbicidal herbicidally herbicide herbicides herbivore herbivores herbivorous herbivorously herblike herbs herby herculaneum herculean hercules hercynian herd herded herder herders herdic herdics herding herdlike herds herdsman herdsmen here hereabout hereabouts hereafter hereaway hereaways hereby hereditament hereditaments hereditarian hereditarianism hereditarians hereditarily hereditariness hereditary heredities hereditist hereditists heredity hereford herefords herein hereinabove hereinafter hereinbefore hereinbelow hereinto hereof hereon herero hereros heresiarch heresiarchs heresies heresy heretic heretical heretically hereticalness heretics hereto heretofore hereunder hereunto hereupon hereward herewith heriot heriots heritabilities heritability heritable heritably heritage heritages heritor heritors heriz herizes herky herl herls herm herma hermae hermai herman hermaphrodism hermaphrodite hermaphrodites hermaphroditic hermaphroditically hermaphroditism hermaphroditus hermas hermatypic hermeneutic hermeneutical hermeneutically hermeneutics hermeneutist hermeneutists hermes hermetic hermetical hermetically hermeticism hermetism hermetist hermetists hermit hermitage hermitages hermitian hermitic hermitical hermitically hermitism hermits hermon hermosillo herms hern hernia herniae hernial hernias herniate herniated herniates herniating herniation herniations herns hero herod herodas herodian herodias herodotus heroes heroic heroical heroically heroicalness heroicomic heroicomical heroics heroin heroine heroines heroinism heroinisms heroism heron heronries heronry herons heros herpes herpesvirus herpesviruses herpetic herpetologic herpetological herpetologically herpetologist herpetologists herpetology herr herren herrenvolk herrenvolks herrick herring herringbone herringboned herringbones herringboning herrings hers herschel herself hershey herstories herstory hertfordshire hertz hertzian hertzsprung herzegovina herzegovinian herzegovinians heshvan heshvans heshwan heshwans hesiod hesitance hesitancies hesitancy hesitant hesitantly hesitate hesitated hesitater hesitaters hesitates hesitating hesitatingly hesitation hesitations hesperian hesperidean hesperides hesperidia hesperidian hesperidin hesperidins hesperidium hesperus hess hesse hessian hessians hessite hessites hessonite hessonites hest hestia hests het hetaera hetaerae hetaeras hetaeric hetaira hetairai hetairas hetero heteroatom heteroatoms heterocarpies heterocarpous heterocarpy heterocercal heterochromatic heterochromatin heterochromatins heterochromatism heterochromatisms heterochromosome heterochromosomes heterocycle heterocycles heterocyclic heterocyst heterocysts heterodox heterodoxies heterodoxy heterodyne heterodyned heterodynes heterodyning heteroecious heteroecism heterogamete heterogametes heterogametic heterogamic heterogamies heterogamous heterogamy heterogeneity heterogeneous heterogeneously heterogeneousness heterogenic heterogenous heterogeny heterogonic heterogonous heterogony heterograft heterografts heterogynous heterokaryon heterokaryons heterokaryotic heterolecithal heterologous heterologously heterology heterolyses heterolysis heterolytic heteromerous heteromorphic heteromorphism heteronomous heteronomously heteronomy heteronym heteronymous heteronyms heteroousian heterophil heterophile heterophonic heterophony heterophyllous heterophylly heterophyte heterophytes heterophytic heteroplastic heteroplasties heteroplasty heteroploid heteroploids heteroploidy heteropterous heteros heterosexism heterosexual heterosexuality heterosexually heterosexuals heterosis heterosporous heterospory heterostyled heterostylous heterostyly heterotactic heterotactous heterotaxes heterotaxia heterotaxias heterotaxies heterotaxis heterotaxy heterothallic heterothallism heterotic heterotopia heterotopias heterotopic heterotopies heterotopy heterotroph heterotrophic heterotrophically heterotrophs heterotrophy heterotypic heterotypical heterousian heterozygosis heterozygosity heterozygote heterozygotes heterozygous heth hetman hetmans heulandite heulandites heuristic heuristically heuristics hew hewed hewer hewers hewing hewn hews hex hexachlorethane hexachlorethanes hexachloride hexachloroethane hexachloroethanes hexachlorophene hexachord hexachords hexad hexadecimal hexadecimally hexadecimals hexadic hexads hexafluoride hexagon hexagonal hexagonally hexagons hexagram hexagrams hexahedra hexahedral hexahedron hexahedrons hexahydrate hexamerism hexamerous hexameter hexameters hexamethonium hexamethylenetetramine hexamethylenetetramines hexametric hexametrical hexane hexaploid hexaploids hexaploidy hexapod hexapodous hexapods hexastyle hexateuch hexavalent hexed hexer hexerei hexereis hexers hexes hexing hexosan hexosans hexose hexoses hexyl hexylresorcinol hexylresorcinols hexyls hey heyday heydays heywood hezekiah hi hialeah hiatal hiatus hiatuses hiawatha hibachi hibachis hibernacula hibernaculum hibernal hibernate hibernated hibernates hibernating hibernation hibernations hibernator hibernators hibernia hibernian hibernians hiberno hibiscus hibiscuses hic hiccough hiccoughed hiccoughing hiccoughs hiccup hiccuped hiccuping hiccupped hiccupping hiccups hick hickey hickeys hickories hickory hicks hid hidalgo hidalgos hidatsa hidatsas hidden hiddenite hiddenites hiddenness hide hideaway hideaways hidebound hided hideosity hideous hideously hideousness hideout hideouts hider hiders hides hiding hidings hidroses hidrosis hidrotic hie hied hieing hiemal hierapolis hierarch hierarchal hierarchic hierarchical hierarchically hierarchies hierarchization hierarchizations hierarchize hierarchized hierarchizes hierarchizing hierarchs hierarchy hieratic hieratically hierocracies hierocracy hierocratic hierocratical hierodule hierodules hierodulic hieroglyph hieroglyphic hieroglyphical hieroglyphically hieroglyphics hieroglyphs hierologies hierologist hierologists hierology hierophant hierophantic hierophants hies hifalutin higashiosaka higgle higgled higgledy higgler higglers higgles higgling high highball highballed highballing highballs highbinder highbinders highborn highboy highboys highbred highbrow highbrowed highbrowism highbrows highbush highchair highchairs higher highest highfalutin highfaluting highflier highfliers highflyer highflyers highflying highhanded highhandedly highhandedness highjack highjacked highjacker highjackers highjacking highjacks highland highlander highlanders highlands highlife highlifer highlifers highlifes highlight highlighted highlighter highlighters highlighting highlights highline highly highness highnesses highroad highroads highs hight hightail hightailed hightailing hightails highway highwayman highwaymen highways hijack hijacked hijacker hijackers hijacking hijackings hijacks hijiki hijikis hijinks hike hiked hiker hikers hikes hiking hila hilar hilarious hilariously hilariousness hilarities hilarity hilary hilbert hildebrand hildesheim hilding hildings hill hillbillies hillbilly hillcrest hillcrests hilled hillel hiller hillers hilliard hillier hilliest hilliness hilling hillock hillocks hillocky hills hillscape hillside hillsides hilltop hilltops hilly hilo hilt hilted hilton hilts hilum hilversum him himachal himalaya himalayan himalayans himalayas himalia himatia himation himations himmler himself himyarite himyarites himyaritic hin hinayana hinayanist hinayanistic hinayanists hind hindbrain hindbrains hindemith hindenburg hinder hindered hinderer hinderers hindering hindermost hinders hindgut hindguts hindi hindmost hindoo hindquarter hindquarters hindrance hindrances hinds hindsight hindu hinduism hindus hindustan hindustani hinge hinged hinges hinging hinnies hinny hins hint hinted hinter hinterland hinterlands hinters hinting hints hip hipbone hipbones hipline hiplines hiply hipness hipparchus hipped hipper hippest hippias hippie hippiedom hippiehood hippies hipping hippo hippocampal hippocampi hippocampus hippocras hippocrases hippocrates hippocratic hippocrene hippodrome hippodromes hippogriff hippogriffs hippogryph hippolyta hippolytus hippomenes hippopotami hippopotamus hippopotamuses hippos hippy hips hipster hipsterism hipsters hirable hiragana hircine hire hireable hired hireling hirelings hirer hirers hires hiring hirohito hiroshima hirsute hirsuteness hirsutism hirudin hirudins his hispanic hispanicism hispanicisms hispanicization hispanicizations hispanicize hispanicized hispanicizes hispanicizing hispanics hispaniola hispanism hispanisms hispanist hispanists hispano hispanophile hispanophiles hispanophilia hispanophobe hispanophobes hispanophobia hispanos hispid hispidity hiss hissarlik hissed hisself hisser hissers hisses hissing hissingly hissy hist histaminase histaminases histamine histaminergic histamines histaminic histidine histidines histiocyte histiocytes histiocytic histiocytoses histiocytosis histochemical histochemically histochemistry histocompatibilities histocompatibility histocompatible histodialyses histodialysis histogenesis histogenetic histogenetically histogenic histogenically histogram histograms histologic histological histologically histologies histologist histologists histology histolysis histolytic histolytically histomoniases histomoniasis histone histones histopathologic histopathological histopathologically histopathologist histopathologists histopathology histophysiologic histophysiological histophysiology histoplasmoses histoplasmosis historian historians historiated historic historical historically historicalness historicism historicist historicists historicity historicization historicizations historicize historicized historicizes historicizing historied histories historiographer historiographers historiographic historiographical historiographically historiography history histrionic histrionical histrionically histrionics hit hitachi hitch hitched hitcher hitchers hitches hitchhike hitchhiked hitchhiker hitchhikers hitchhikes hitchhiking hitching hither hithermost hitherto hitherward hitherwards hitler hitlerism hitlerite hitlerites hitless hits hittable hitter hitters hitting hittite hittites hive hived hiveless hives hiving hiwassee hkakabo hmm hmong hmongs ho hoagie hoagies hoagy hoar hoard hoarded hoarder hoarders hoarding hoardings hoards hoarfrost hoarfrosts hoarier hoariest hoarily hoariness hoars hoarse hoarsely hoarsen hoarsened hoarseness hoarsening hoarsens hoarser hoarsest hoary hoatzin hoatzins hoax hoaxed hoaxer hoaxers hoaxes hoaxing hob hobart hobbed hobbes hobbesian hobbies hobbing hobbism hobbist hobbists hobbit hobbits hobble hobblebush hobblebushes hobbled hobbledehoy hobbledehoys hobbler hobblers hobbles hobbling hobby hobbyhorse hobbyhorses hobbyist hobbyists hobgoblin hobgoblins hobnail hobnailed hobnails hobnob hobnobbed hobnobber hobnobbers hobnobbing hobnobs hobo hoboed hoboes hoboing hoboism hoboken hobos hobs hoc hock hocked hocker hockers hockey hocking hocks hockshop hockshops hocus hocused hocuses hocusing hocussed hocusses hocussing hod hodgepodge hodgepodges hodgkin hodoscope hodoscopes hods hoe hoecake hoecakes hoed hoedown hoedowns hoeing hoer hoers hoes hog hogan hogans hogarth hogback hogbacks hogfish hogfishes hogg hogged hogging hoggish hoggishly hoggishness hoggs hogmanay hogmanays hognose hogs hogshead hogsheads hogwash hogweed hogweeds hohenlohe hohenstaufen hohenstaufens hohenzollern hohenzollerns hoi hoick hoicked hoicking hoicks hoise hoised hoises hoisin hoising hoist hoisted hoister hoisters hoisting hoists hoity hokan hokang hoke hoked hokes hokey hokeyness hokeypokey hokeypokeys hokier hokiest hokily hokiness hoking hokkaido hokku hokum hokums hokusai hokypokies holandric holarctic holbein hold holdall holdalls holdback holdbacks holden holder holders holdfast holdfasts holding holdings holdout holdouts holdover holdovers holds holdup holdups hole holed holes holey holiday holidayed holidayer holidayers holidaying holidaymaker holidaymakers holidays holier holies holiest holily holiness holing holinshed holism holisms holist holistic holistically holists holla hollaed hollaing holland hollandaise hollander hollanders hollas holler hollered hollering hollerith hollers hollies hollo holloa holloaed holloaing holloas holloed holloes holloing hollos hollow holloware hollowed hollower hollowest hollowing hollowly hollowness hollows hollowware holly hollyhock hollyhocks hollywood holm holmes holmic holmium holms holoblastic holoblastically holocaust holocaustal holocaustic holocausts holocene holocrine holoenzyme holoenzymes holofernes hologamous hologram holograms holograph holographic holographical holographically holographs holography hologynic holohedral holometabolism holometabolous holophrastic holophytic holoplankton holoplanktons holothurian holothurians holotype holotypes holotypic holozoic holp holpen holst holstein holsteins holster holstered holstering holsters holt holts holy holyoke holystone holystoned holystones holystoning homage homager homagers hombre hombres homburg homburgs home homebodies homebody homebound homeboy homeboys homebred homebuilder homebuilders homebuilding homebuilt homebuyer homebuyers homecoming homecomings homed homefolk homefolks homegrown homeland homelands homeless homelessness homelier homeliest homelike homeliness homely homemade homemaker homemakers homemaking homeobox homeoboxes homeomorphic homeomorphism homeomorphisms homeomorphous homeopath homeopathic homeopathically homeopathies homeopathist homeopathists homeopaths homeopathy homeostasis homeostatic homeotherm homeothermal homeothermic homeothermous homeotherms homeowner homeowners homeownership homer homered homeric homerically homering homeroom homerooms homers homes homesick homesickness homesite homesites homespun homestead homesteaded homesteader homesteaders homesteading homesteads homestretch homestretches hometown hometowns homeward homewards homework homey homeyness homicidal homicidally homicide homicides homier homiest homiletic homiletical homiletically homiletics homilies homilist homilists homily hominem hominess homing hominid hominidae hominids hominization hominizations hominoid hominoids hominy hommos homo homocentric homocercal homochirality homochromatic homochromatism homoecious homoerotic homoeroticism homoerotism homogametic homogamous homogamy homogenate homogenates homogeneities homogeneity homogeneous homogeneously homogeneousness homogenies homogenization homogenizations homogenize homogenized homogenizer homogenizers homogenizes homogenizing homogenous homogeny homograft homografts homograph homographic homographs homoiotherm homoiothermal homoiothermic homoiothermous homoiotherms homoiousian homoiousians homolecithal homolog homologate homologated homologates homologating homologation homologic homological homologically homologies homologize homologized homologizer homologizers homologizes homologizing homologous homolographic homologs homologue homologues homology homolosine homolysis homolytic homomorphic homomorphism homomorphisms homomorphous homonuclear homonym homonymic homonymies homonymous homonymously homonyms homonymy homoousian homoousians homophile homophiles homophobe homophobes homophobia homophobic homophone homophones homophonic homophonies homophonous homophony homophylic homophylies homophyly homoplasies homoplastic homoplastically homoplasy homopolar homopolymer homopolymers homopteran homopterans homopterous homos homoscedastic homoscedasticity homosexual homosexuality homosexually homosexuals homosporous homospory homostyled homostylous homostyly homotaxial homotaxic homotaxis homotaxises homothallic homothallism homotransplant homotransplantation homozygosis homozygosity homozygote homozygotes homozygotic homozygous homozygously homunculi homunculus homy hon honan honans honcho honchoed honchoing honchos honduran hondurans honduras hone honed honer honers hones honest honesties honestly honesty honewort honeworts honey honeybee honeybees honeyberries honeyberry honeybunch honeybunches honeycomb honeycombed honeycombing honeycombs honeycreeper honeycreepers honeydew honeydews honeyeater honeyeaters honeyed honeying honeymoon honeymooned honeymooner honeymooners honeymooning honeymoons honeys honeysuckle honeysuckles honeywell honfleur hong hongs honiara honied honing honk honked honker honkers honkey honkeys honkie honkies honking honks honky honkytonks honolulu honor honorabilities honorability honorable honorableness honorably honoraria honorarily honorarium honorariums honorary honored honoree honorees honorer honorers honorific honorifically honorifics honoring honors honshu hoo hooch hooches hood hooded hoodedness hooding hoodlike hoodlum hoodlumish hoodlumism hoodlums hoodmold hoodmolds hoodoo hoodooed hoodooing hoodooism hoodoos hoods hoodwink hoodwinked hoodwinker hoodwinkers hoodwinking hoodwinks hooey hoof hoofbeat hoofbeats hoofbound hoofed hoofer hoofers hoofing hoofprint hoofprints hoofs hook hookah hookahs hooked hookedness hooker hookers hookey hookeys hookies hooking hooklet hooklets hooknose hooknosed hooknoses hooks hookup hookups hookworm hookworms hooky hooligan hooliganism hooligans hoop hooped hooper hoopers hooping hoopla hooplike hoopoe hoopoes hoops hoopskirt hoopskirts hoorah hoorahs hooray hoorayed hooraying hoorays hoosegow hoosegows hoosier hoosiers hoot hootch hootches hootchy hooted hootenannies hootenanny hooter hooters hooting hoots hooved hooverville hoovervilles hooves hop hopatcong hope hoped hopeful hopefully hopefulness hopefuls hopeh hopei hopeless hopelessly hopelessness hoper hopers hopes hopewell hophead hopheads hopi hoping hopis hoplite hoplites hoplitic hopped hopper hoppergrass hoppergrasses hoppers hopping hops hopsack hopsacking hopsacks hopscotch hopscotched hopscotches hopscotching hora horace horah horahs horary horas horatian horatio horde hordes horehound horehounds horizon horizonal horizons horizontal horizontally horizontals hormogonia hormogonium hormonal hormonally hormone hormonelike hormones hormonic horn hornbeam hornbeams hornbill hornbills hornblende hornblower hornbook hornbooks horned hornedness horner hornet hornets hornfels hornier horniest horniness horning hornist hornists hornito hornitos hornless hornlessness hornlike hornpipe hornpipes hornpout hornpouts horns hornswoggle hornswoggled hornswoggles hornswoggling horntail horntails hornworm hornworms hornwort hornworts horny horologe horologer horologers horologes horologic horological horologist horologists horologium horology horometrical horoscope horoscopes horrendous horrendously horrent horrible horribleness horribly horrid horridly horridness horrific horrifically horrification horrified horrifiedly horrifies horrify horrifying horrifyingly horripilate horripilated horripilates horripilating horripilation horripilations horror horrors horrorstricken horrorstruck hors horsa horse horseback horsebacks horsecar horsecars horsed horsefeathers horseflesh horseflies horsefly horsehair horsehide horsehides horselaugh horselaughs horseleech horseleeches horseless horselike horseman horsemanship horsemeat horsemen horsemint horsemints horseplay horseplayer horseplayers horsepower horserace horseraces horseracing horseradish horseradishes horses horseshit horseshits horseshoe horseshoed horseshoeing horseshoer horseshoers horseshoes horsetail horsetails horseweed horseweeds horsewhip horsewhipped horsewhipping horsewhips horsewoman horsewomen horsey horsier horsiest horsily horsiness horsing horst horsts horsy hortative hortatively hortatory horticultural horticulturalist horticulturalists horticulturally horticulture horticulturist horticulturists horus hosanna hosannah hosannahs hosannas hose hosea hosed hosel hosels hoses hosey hoseyed hoseying hoseys hosiery hosing hospice hospices hospitable hospitably hospital hospitaler hospitalers hospitalities hospitality hospitalization hospitalizations hospitalize hospitalized hospitalizes hospitalizing hospitaller hospitallers hospitals host hosta hostage hostages hostas hosted hostel hosteled hosteler hostelers hosteling hostelries hostelry hostels hostess hostesses hostile hostilely hostiles hostilities hostility hosting hostler hostlers hostly hosts hot hotbed hotbeds hotblood hotbloods hotbox hotboxes hotcake hotcakes hotch hotched hotches hotching hotchpot hotchpotch hotchpotches hotchpots hotdog hotdogged hotdogging hotdogs hotel hotelier hoteliers hotelkeeper hotelkeepers hotelman hotelmen hotels hotfoot hotfooted hotfooting hotfoots hothead hotheaded hotheadedly hotheadedness hotheads hothouse hothouses hotkey hotline hotlines hotly hotness hotplate hotplates hotpot hotpots hotrod hotrods hots hotshot hotshots hotspot hotspots hotspur hotted hottentot hottentots hotter hottest hotting hottish houdah houdahs houdan houdans houdini hound hounded hounder hounders hounding hounds houndstooth hour hourglass hourglasses houri houris hourlies hourlong hourly hours housatonic house houseboat houseboats housebound houseboy houseboys housebreak housebreaker housebreakers housebreaking housebreaks housebroke housebroken housecarl housecarls houseclean housecleaned housecleaner housecleaners housecleaning housecleans housecoat housecoats housed housedog housedogs housedress housedresses housefather housefathers houseflies housefly housefront housefronts houseful housefuls houseguest houseguests household householder householders households househusband househusbands housekeep housekeeper housekeepers housekeeping housekeeps housekept housel houseled houseleek houseleeks houseless houselessness houselights houseling housels housemaid housemaids houseman housemaster housemasters housemate housemates housemen housemother housemothers housepainter housepainters houseparent houseparents houseperson housepersons houseplant houseplants houseroom houserooms housers houses housesat housesit housesits housesitting housetop housetops housetrain housetrained housetraining housetrains housewares housewarming housewarmings housewife housewifeliness housewifely housewifery housewives housework houseworker houseworkers housing housings houston houstonian houstonians hove hovel hovels hover hovercraft hovercrafts hovered hoverer hoverers hovering hoveringly hovers how howard howards howbeit howdah howdahs howdy howe howes however howf howff howffs howfs howitzer howitzers howl howled howler howlers howling howls hows howsoever hoy hoya hoyas hoyden hoydenish hoydens hoyle hoys html hualapai hualapais huang huarache huaraches huascarán hub hubba hubbard hubbies hubble hubbub hubbubs hubby hubcap hubcaps hubris hubristic hubristically hubs huck huckaback huckabacks huckleberries huckleberry hucks huckster huckstered huckstering hucksterism hucksters huddle huddled huddler huddlers huddles huddling hudibras hudibrastic hudson hue hued hues huevos huff huffed huffier huffiest huffily huffiness huffing huffish huffishly huffishness huffs huffy hug huge hugely hugeness hugeous hugeously hugeousness huger hugest huggable hugged hugger huggermugger huggermuggered huggermuggering huggermuggers huggermuggery huggers hugging hugo hugs huguenot huguenotic huguenotism huguenots huh hui huipil huipils huis hula hulas hulk hulked hulking hulks hulky hull hullaballoo hullaballoos hullabaloo hullabaloos hulled huller hullers hulling hullo hulls hum human humane humanely humaneness humanhood humanism humanist humanistic humanistically humanists humanitarian humanitarianism humanitarians humanities humanity humanization humanize humanized humanizer humanizers humanizes humanizing humankind humanlike humanly humanness humanoid humanoids humans humate humates humberside humble humblebee humblebees humbled humbleness humbler humblers humbles humblest humbling humbly humboldt humbug humbugged humbugger humbuggers humbuggery humbugging humbugs humdinger humdingers humdrum hume humectant humectants humectation humeral humerals humeri humerus humic humid humidification humidifications humidified humidifier humidifiers humidifies humidify humidifying humidistat humidistats humidity humidly humidor humidors humification humifications humified humiliate humiliated humiliates humiliating humiliatingly humiliation humiliations humilities humility hummable hummed hummer hummers humming hummingbird hummingbirds hummock hummocks hummocky hummus humongous humor humoral humored humoredly humoresque humoresques humoring humorist humoristic humorists humorless humorlessly humorlessness humorous humorously humorousness humors hump humpback humpbacked humpbacks humped humperdinck humph humphed humphing humphrey humphreys humphs humpier humpiest humping humps humpty humpy hums humungous humus humuses hun hunan hunch hunchback hunchbacked hunchbacks hunched hunches hunching hundred hundredfold hundreds hundredth hundredths hundredweight hundredweights hung hungarian hungarians hungary hunger hungered hungering hungers hungrier hungriest hungrily hungriness hungry hunk hunker hunkered hunkering hunkers hunkies hunkpapa hunkpapas hunks hunky hunnish hunnishness huns hunt hunted hunter hunters hunting huntings huntington huntress huntresses hunts huntsman huntsmen huntsville hup hurdle hurdled hurdler hurdlers hurdles hurdling hurdy hurl hurled hurler hurlers hurlies hurling hurlings hurls hurly huron hurons hurrah hurrahed hurrahing hurrahs hurray hurricane hurricanes hurried hurriedly hurriedness hurrier hurriers hurries hurry hurrying hurt hurter hurters hurtful hurtfully hurtfulness hurting hurtle hurtled hurtles hurtless hurtling hurts husband husbanded husbander husbanders husbanding husbandly husbandman husbandmen husbandry husbands hush hushed hushes hushing hushpuppies hushpuppy husk husked husker huskers huskier huskies huskiest huskily huskiness husking huskings husks husky huss hussar hussars hussies hussite hussites hussitism hussy hustings hustle hustled hustler hustlers hustles hustling hut hutch hutches hutment huts hutted hutterite hutterites hutting hutu hutus hutzpa hutzpah huxley huygens huzza huzzah huzzahs huzzas huáscar hwang hwei hweis hyacinth hyacinthine hyacinths hyacinthus hyades hyaena hyaenas hyalin hyaline hyalines hyalinization hyalins hyalite hyalites hyaloid hyaloplasm hyaloplasms hyaluronic hyaluronidase hyaluronidases hyannis hybrid hybridism hybridist hybridists hybridity hybridization hybridizations hybridize hybridized hybridizer hybridizers hybridizes hybridizing hybridoma hybridomas hybrids hybris hydathode hydathodes hydatid hydatids hyde hyderabad hydra hydrae hydralazine hydralazines hydramine hydramines hydrangea hydrangeas hydrant hydranth hydranths hydrants hydrarch hydras hydrase hydrases hydrastine hydrastines hydrate hydrated hydrates hydrating hydration hydrations hydrator hydrators hydraulic hydraulically hydraulics hydrazide hydrazides hydrazine hydric hydride hydrides hydrilla hydrillas hydriodic hydro hydrobiological hydrobiologist hydrobiologists hydrobiology hydrobromic hydrocarbon hydrocarbonaceous hydrocarbonic hydrocarbonous hydrocarbons hydrocele hydroceles hydrocephalic hydrocephaloid hydrocephalous hydrocephalus hydrocephaly hydrochemistry hydrochloric hydrochloride hydrochlorides hydrochlorothiazide hydrochlorothiazides hydrocolloid hydrocolloidal hydrocolloids hydrocoral hydrocorals hydrocortisone hydrocrack hydrocracked hydrocracker hydrocrackers hydrocracking hydrocrackings hydrocracks hydrocyanic hydrodynamic hydrodynamical hydrodynamically hydrodynamicist hydrodynamicists hydrodynamics hydroelectric hydroelectrically hydroelectricity hydrofluoric hydrofoil hydrofoils hydroformer hydroformers hydroforming hydroformings hydrogen hydrogenase hydrogenases hydrogenate hydrogenated hydrogenates hydrogenating hydrogenation hydrogenations hydrogenolysis hydrogenous hydrogeologic hydrogeological hydrogeologist hydrogeologists hydrogeology hydrographer hydrographers hydrographic hydrographically hydrographies hydrography hydroid hydroids hydrokinetic hydrokinetical hydrokinetics hydrolase hydrolases hydrologic hydrological hydrologically hydrologist hydrologists hydrology hydrolysate hydrolysates hydrolysis hydrolyte hydrolytic hydrolytically hydrolyzable hydrolyzate hydrolyzates hydrolyzation hydrolyze hydrolyzed hydrolyzes hydrolyzing hydromagnetic hydromagnetics hydromancy hydromechanical hydromechanics hydromedusa hydromedusae hydromedusas hydromel hydromels hydrometallurgical hydrometallurgy hydrometeor hydrometeorological hydrometeorologist hydrometeorologists hydrometeorology hydrometeors hydrometer hydrometers hydrometric hydrometrical hydrometrically hydrometry hydromorphic hydronic hydronically hydronium hydroniums hydropath hydropathic hydropathical hydropathies hydropathist hydropathists hydropaths hydropathy hydroperoxide hydrophane hydrophanes hydrophanous hydrophile hydrophiles hydrophilic hydrophilicity hydrophilous hydrophily hydrophobia hydrophobias hydrophobic hydrophobicity hydrophone hydrophones hydrophyte hydrophytes hydrophytic hydroplane hydroplaned hydroplanes hydroplaning hydroponic hydroponically hydroponicist hydroponicists hydroponics hydroponist hydroponists hydropower hydroquinol hydroquinols hydroquinone hydroquinones hydros hydroscope hydroscopes hydroscopic hydrosere hydrosol hydrosolic hydrosols hydrospace hydrospaces hydrosphere hydrospheres hydrospheric hydrostatic hydrostatical hydrostatically hydrostatics hydrosulfate hydrosulfates hydrosulfide hydrosulfides hydrosulfite hydrosulfites hydrosulfurous hydrotactic hydrotaxis hydrotaxises hydrotherapeutic hydrotherapeutics hydrotherapies hydrotherapy hydrothermal hydrothermally hydrothorax hydrothoraxes hydrotropic hydrotropically hydrotropism hydrous hydroxide hydroxides hydroxy hydroxyapatite hydroxyapatites hydroxyl hydroxylamine hydroxylamines hydroxylate hydroxylated hydroxylates hydroxylating hydroxylation hydroxylic hydroxyls hydroxyproline hydroxyzine hydrozoa hydrozoan hydrozoans hydrus hyena hyenas hyenic hyetal hyetometer hyetometers hyetometrograph hyetometrographs hygeia hygiene hygienic hygienically hygienics hygienist hygienists hygrograph hygrographs hygrometer hygrometers hygrometric hygrometry hygrophyte hygrophytes hygrophytic hygroscope hygroscopes hygroscopic hygroscopically hygroscopicity hygrostat hygrostats hying hyla hylas hylozoic hylozoism hylozoist hylozoistic hylozoists hymen hymenal hymeneal hymeneally hymeneals hymenia hymenial hymenium hymeniums hymenopteran hymenopterans hymenopteron hymenopterons hymenopterous hymens hymettus hymie hymies hymn hymnal hymnals hymnaries hymnary hymnbook hymnbooks hymned hymning hymnodies hymnodist hymnodists hymnody hymnography hymnologic hymnological hymnologist hymnologists hymnology hymns hyoid hyoids hyoscine hyoscines hyoscyamine hyoscyamines hypabyssal hypabyssally hypaethral hypanthia hypanthial hypanthium hype hyped hyper hyperacid hyperacidity hyperactive hyperactively hyperactivity hyperacuity hyperacute hyperaesthesia hyperaesthesias hyperaesthetic hyperaggressive hyperalert hyperarid hyperarousal hyperaware hyperawareness hyperbaric hyperbarically hyperbaton hyperbatons hyperbola hyperbolae hyperbolas hyperbole hyperbolic hyperbolical hyperbolically hyperbolism hyperbolisms hyperbolist hyperbolists hyperbolize hyperbolized hyperbolizes hyperbolizing hyperboloid hyperboloidal hyperboloids hyperborean hyperboreans hypercalcemia hypercalcemias hypercapnia hypercapnias hypercatabolism hypercatalectic hypercatalexis hypercautious hypercharge hypercharged hypercharges hypercholesterolemia hypercholesterolemias hypercivilized hypercoagulability hypercoagulable hypercompetitive hyperconcentration hyperconscious hyperconsciousness hypercorrect hypercorrection hypercorrections hypercorrectly hypercorrectness hypercritic hypercritical hypercritically hypercriticism hypercriticisms hypercriticize hypercriticizes hypercritics hypercube hypercubes hyperdense hyperdevelopment hyperefficient hyperemia hyperemic hyperemotional hyperemotionality hyperendemic hyperenergetic hyperesthesia hyperesthesias hyperesthetic hypereutectic hyperexcitability hyperexcitable hyperexcited hyperexcitement hyperexcretion hyperextend hyperextended hyperextending hyperextends hyperextension hyperextensions hyperfastidious hyperfine hyperfunction hyperfunctional hyperfunctioning hypergamies hypergamy hypergeometric hyperglycemia hyperglycemic hypergol hypergolic hypergolically hyperimmune hyperimmunization hyperimmunize hyperimmunized hyperimmunizes hyperimmunizing hyperinflated hyperinflation hyperinflationary hyperinflations hyperinnervation hyperinsulinism hyperinsulinisms hyperintellectual hyperintelligent hyperintense hyperinvolution hyperion hyperirritability hyperirritable hyperkeratoses hyperkeratosis hyperkeratotic hyperkinesia hyperkinesis hyperkinetic hyperlink hyperlinks hyperlipemia hyperlipemias hyperlipidemia hyperlipidemias hypermania hypermanic hypermarket hypermarkets hypermasculine hypermedia hypermetabolic hypermetabolism hypermeter hypermeters hypermetric hypermetrical hypermetropia hypermetropias hypermetropic hypermetropical hypermetropy hypermnesia hypermnesias hypermnesic hypermobility hypermodern hypermodernist hypermutability hypermutable hypernationalistic hyperon hyperons hyperope hyperopia hyperopias hyperopic hyperostoses hyperostosis hyperostotic hyperparasite hyperparasites hyperparasitic hyperparasitism hyperparathyroidism hyperphagia hyperphagic hyperphysical hyperpigmentation hyperpigmented hyperpituitarism hyperpituitarisms hyperpituitary hyperplane hyperplanes hyperplasia hyperplasias hyperplastic hyperploid hyperploidy hyperpnea hyperpneas hyperpneic hyperpolarize hyperpolarized hyperpolarizes hyperpolarizing hyperproducer hyperproducers hyperproduction hyperpure hyperpyretic hyperpyrexia hyperpyrexial hyperpyrexias hyperrational hyperrationality hyperreactive hyperreactivity hyperreactor hyperreactors hyperrealism hyperrealisms hyperrealist hyperrealistic hyperrealists hyperresponsive hyperromantic hypersaline hypersalinity hypersalivation hypersecretion hypersensitive hypersensitiveness hypersensitivities hypersensitivity hypersensitization hypersensitize hypersensitized hypersensitizes hypersensitizing hypersexual hypersexuality hypersomnolence hypersonic hypersonically hyperspace hyperspaces hyperstatic hypersthene hypersthenes hypersthenic hyperstimulate hyperstimulated hyperstimulates hyperstimulating hyperstimulation hypersurface hypersurfaces hypersusceptibility hypersusceptible hypertense hypertension hypertensive hypertext hypertexts hyperthermal hyperthermia hyperthermias hyperthermic hyperthyroid hyperthyroidism hypertonia hypertonias hypertonic hypertonicity hypertrophic hypertrophied hypertrophies hypertrophy hypertrophying hypertypical hypervelocity hyperventilate hyperventilated hyperventilates hyperventilating hyperventilation hypervigilance hypervigilant hypervirulent hyperviscosity hypervitaminoses hypervitaminosis hypes hypesthesia hypesthesias hypethral hypha hyphae hyphal hyphen hyphenate hyphenated hyphenates hyphenating hyphenation hyphenations hyphened hyphening hyphenless hyphens hyping hypnagogic hypnoanalyses hypnoanalysis hypnogenesis hypnogenetic hypnogenetically hypnogogic hypnoid hypnoidal hypnopedia hypnopedias hypnophobia hypnophobias hypnophobic hypnopompic hypnos hypnoses hypnosis hypnotherapies hypnotherapy hypnotic hypnotically hypnotics hypnotism hypnotist hypnotists hypnotizability hypnotizable hypnotization hypnotize hypnotized hypnotizer hypnotizers hypnotizes hypnotizing hypo hypoacidities hypoacidity hypoactive hypoallergenic hypobaric hypobarism hypoblast hypoblastic hypoblasts hypocaust hypocausts hypocenter hypocenters hypocentral hypochlorite hypochlorites hypochlorous hypochondria hypochondriac hypochondriacal hypochondriacally hypochondriacs hypochondriases hypochondriasis hypochondrium hypocorism hypocorisms hypocoristic hypocoristical hypocoristically hypocotyl hypocotyls hypocrisies hypocrisy hypocrite hypocrites hypocritical hypocritically hypocycloid hypocycloids hypoderm hypodermal hypodermic hypodermically hypodermics hypodermis hypodermises hypoderms hypoed hypoesthesia hypoesthesias hypoeutectic hypogastria hypogastric hypogastrium hypogea hypogeal hypogeally hypogean hypogene hypogenous hypogeous hypogeum hypoglossal hypoglycemia hypoglycemic hypogynous hypogyny hypoing hypolimnetic hypolimnial hypolimnion hypolimnions hypomania hypomanias hypomanic hypomorphic hyponastic hyponasties hyponasty hypophosphite hypophosphites hypophosphorous hypophyseal hypophyses hypophysial hypophysis hypopituitarism hypopituitarisms hypopituitary hypoplasia hypoplasias hypoplastic hypoploid hypoploidy hypopnea hypopneas hypopneic hypos hyposensitive hyposensitivities hyposensitivity hyposensitization hyposensitizations hyposensitize hyposensitized hyposensitizes hyposensitizing hypostases hypostasis hypostatic hypostatical hypostatically hypostatization hypostatize hypostatized hypostatizes hypostatizing hyposthenia hyposthenias hyposthenic hypostyle hypostyles hyposulfite hyposulfites hyposulfurous hypotactic hypotaxis hypotaxises hypotension hypotensions hypotensive hypotensives hypotenuse hypotenuses hypothalamic hypothalamus hypothalamuses hypothecate hypothecated hypothecates hypothecating hypothecation hypothecations hypothecator hypothecators hypothenuse hypothermal hypothermia hypothermic hypotheses hypothesi hypothesis hypothesize hypothesized hypothesizer hypothesizers hypothesizes hypothesizing hypothetic hypothetical hypothetically hypothyroid hypothyroidism hypotonic hypotonicity hypotrophic hypotrophies hypotrophy hypoventilation hypoventilations hypoxanthine hypoxanthines hypoxemia hypoxemias hypoxemic hypoxia hypoxias hypoxic hypsographic hypsographical hypsographies hypsography hypsometer hypsometers hypsometric hypsometrical hypsometrically hypsometrist hypsometrists hypsometry hyraces hyrax hyraxes hyson hysons hyssop hyssops hysterectomies hysterectomize hysterectomized hysterectomizes hysterectomizing hysterectomy hystereses hysteresis hysteretic hysteria hysterias hysteric hysterical hysterically hysterics hysterogenic hysteroid hysteron hysterotomies hysterotomy hälsingborg héloise hôte hôtel i i'd i'll i'm i've iago iamb iambi iambic iambics iambs iambus iambuses iapetus iatrogenic iatrogenically iberia iberian iberians ibex ibexes ibibio ibibios ibid ibidem ibis ibises ibiza ibizan ibo ibos ibsen ibsenian ibsenism ibsenite ibsenites ibuprofen icaria icarus ice iceball iceballs iceberg icebergs iceblink iceblinks iceboat iceboater iceboaters iceboating iceboats icebound icebox iceboxes icebreaker icebreakers icebreaking icecap icecaps iced icefall icefalls icehouse icehouses iceland icelander icelanders icelandic iceless icelike icemaker icemakers iceman icemen iceni icenian icenic icepack icepacks ices icescape icescapes ich ichihara ichikawa ichinomiya ichneumon ichneumons ichnite ichnites ichnographies ichnography ichnolite ichnolites ichor ichorous ichors ichthyic ichthyofauna ichthyofaunal ichthyofaunas ichthyoid ichthyoids ichthyologic ichthyological ichthyologically ichthyologist ichthyologists ichthyology ichthyophagous ichthyornis ichthyornises ichthyosaur ichthyosauri ichthyosaurian ichthyosaurs ichthyosaurus ichthyosis ici icicle icicles icier iciest icily iciness icing icings ickier ickiest ickiness icky icon iconic iconically iconicity iconified iconifies iconify iconifying iconoclasm iconoclast iconoclastic iconoclastically iconoclasts iconographer iconographers iconographic iconographical iconographically iconographies iconography iconolater iconolaters iconolatric iconolatry iconological iconologist iconologists iconology iconoscope iconoscopes iconostases iconostasis icons icosahedra icosahedral icosahedron icosahedrons icteric icterics icterus ictinus ictus ictuses icy id ida idaho idahoan idahoans idahoes idahos idea ideal idealess idealism idealist idealistic idealistically idealists idealities ideality idealization idealizations idealize idealized idealizer idealizers idealizes idealizing idealless ideally idealogue idealogy ideals ideas ideate ideated ideates ideating ideation ideational ideationally ideations idem idempotent identic identical identically identicalness identics identifiable identifiably identification identifications identified identifier identifiers identifies identify identifying identities identity identité ideogram ideogramic ideogrammatic ideogrammatically ideogrammic ideograms ideograph ideographic ideographically ideographs ideography ideologic ideological ideologically ideologies ideologist ideologists ideologize ideologized ideologizes ideologizing ideologue ideologues ideology ideomotor ides idioblast idioblastic idioblasts idiocies idiocy idiographic idiolect idiolectal idiolectic idiolects idiom idiomatic idiomatically idiomaticness idiomorphic idioms idiopathic idiopathically idiopathies idiopathy idiosyncrasies idiosyncrasy idiosyncratic idiosyncratically idiot idiotic idiotical idiotically idiotism idiots idiotype idiotypic idle idled idleness idler idlers idles idlesse idlest idling idly idocrase idocrases idol idolater idolaters idolator idolators idolatries idolatrous idolatrously idolatrousness idolatry idolization idolizations idolize idolized idolizer idolizers idolizes idolizing idols ids idyl idyll idyllic idyllically idyllist idyllists idylls idyls idée idées if iffier iffiest iffiness iffy ifni ifs igbo igbos igg igged igging iggs igitur igloo igloos ignatius igneous ignes ignescent igni ignimbrite ignimbrites ignis ignitability ignitable ignite ignited igniter igniters ignites ignitible igniting ignition ignitions ignitor ignitors ignitron ignitrons ignobility ignoble ignobleness ignobly ignominies ignominious ignominiously ignominiousness ignominy ignorable ignoramus ignoramuses ignorance ignorant ignorantia ignorantly ignorantness ignoratio ignore ignored ignorer ignorers ignores ignoring ignotius ignotum igorot igorots igraine iguana iguanas iguanodon iguanodons iguassú iguaçú ihram ihrams ijmuiden ijsselmeer ikaria ikat ikebana ikhnaton ikon ikons il ilang ilea ileac ileal ileitis ileostomies ileostomy ileum ileus ilex ilexes ilia iliac iliad iliadic ilial iliamna ilion ilium ilk ilka ill illae illampu illation illations illative illatively illatives illaudable illaudably illegal illegalities illegality illegalization illegalize illegalized illegalizes illegalizing illegally illegals illegibility illegible illegibleness illegibly illegitimacies illegitimacy illegitimate illegitimated illegitimately illegitimates illegitimating illegitimatize illegitimatizes iller illiberal illiberalism illiberality illiberally illiberalness illicit illicitly illicitness illimani illimitability illimitable illimitableness illimitably illinoian illinois illinoisan illinoisans illiquid illiquidity illis illite illiteracies illiteracy illiterate illiterately illiterateness illiterates illitic illness illnesses illocutionary illogic illogical illogicalities illogicality illogically illogicalness ills illume illumed illumes illuminable illuminance illuminances illuminant illuminants illuminate illuminated illuminates illuminati illuminating illuminatingly illumination illuminations illuminative illuminator illuminators illumine illumined illumines illuming illumining illuminism illuminist illuminists illusion illusional illusionary illusionism illusionist illusionistic illusionistically illusionists illusionless illusions illusive illusively illusiveness illusorily illusoriness illusory illustratable illustrate illustrated illustrates illustrating illustration illustrational illustrations illustrative illustratively illustrator illustrators illustrious illustriously illustriousness illuvial illuviate illuviated illuviates illuviating illuviation illuviations illy illyria illyrian illyrians illyricums ilmenite ilmenites ilocano ilocanos iloilo ilokano ilokanos ilorin ils image imaged imageless imager imageries imagers imagery images imaginability imaginable imaginableness imaginably imaginaire imaginal imaginaries imaginarily imaginariness imaginary imagination imaginational imaginations imaginative imaginatively imaginativeness imagine imagined imaginer imaginers imagines imaging imagings imagining imaginings imagism imagist imagistic imagistically imagists imago imagoes imam imamate imamates imams imaret imarets imari imbalance imbalanced imbalances imbecile imbecilely imbeciles imbecilic imbecilities imbecility imbed imbedded imbedding imbedment imbeds imbibe imbibed imbiber imbibers imbibes imbibing imbibition imbibitional imbibitions imbitter imbosom imbricate imbricated imbricates imbricating imbrication imbrications imbroglio imbroglios imbrown imbrue imbrued imbrues imbruing imbrute imbruted imbrutes imbruting imbue imbued imbues imbuing imidazole imidazoles imide imides imidic imido imine imines imino imipramine imipramines imitable imitate imitated imitates imitating imitation imitational imitations imitative imitatively imitativeness imitator imitators immaculacies immaculacy immaculate immaculately immaculateness immane immanence immanency immanent immanentism immanentist immanentistic immanentists immanently immanuel immaterial immaterialism immaterialist immaterialists immaterialities immateriality immaterialize immaterialized immaterializes immaterializing immaterially immaterialness immature immaturely immatureness immaturity immeasurability immeasurable immeasurableness immeasurably immediacies immediacy immediate immediately immediateness immedicable immedicably immelmann immemorial immemorially immense immensely immenseness immensities immensity immensurable immerge immerged immergence immergences immerges immerging immerse immersed immerses immersible immersing immersion immersions immesh immeshed immeshes immeshing immethodical immethodically immigrant immigrants immigrate immigrated immigrates immigrating immigration immigrational immigrations imminence imminencies imminency imminent imminently imminentness immingle immiscibility immiscible immiscibly immitigability immitigable immitigableness immitigably immittance immittances immix immixed immixes immixing immixture immixtures immobile immobilism immobility immobilization immobilizations immobilize immobilized immobilizer immobilizers immobilizes immobilizing immoderacies immoderacy immoderate immoderately immoderateness immoderation immodest immodestly immodesty immolate immolated immolates immolating immolation immolations immolator immolators immoral immoralism immoralist immoralists immoralities immorality immorally immortal immortality immortalization immortalize immortalized immortalizer immortalizers immortalizes immortalizing immortally immortals immortelle immortelles immotile immotility immovability immovable immovableness immovables immovably immune immunes immunities immunity immunization immunizations immunize immunized immunizes immunizing immunoassay immunoassayable immunoassays immunoblot immunoblotting immunochemical immunochemically immunochemist immunochemistry immunochemists immunocompetence immunocompetent immunocompromised immunocytochemical immunocytochemically immunocytochemistry immunodeficiencies immunodeficiency immunodeficient immunodepressant immunodepressants immunodepression immunodepressive immunodiagnosis immunodiagnostic immunodiffusion immunoelectrophoresis immunoelectrophoretic immunoelectrophoretically immunofluorescence immunofluorescences immunofluorescent immunogen immunogenesis immunogenetic immunogenetically immunogeneticist immunogeneticists immunogenetics immunogenic immunogenicity immunogens immunoglobulin immunoglobulins immunohematologic immunohematological immunohematologist immunohematologists immunohematology immunohistochemical immunohistochemistry immunologic immunological immunologically immunologist immunologists immunology immunomodulator immunomodulators immunomodulatory immunopathologic immunopathological immunopathologist immunopathologists immunopathology immunoprecipitate immunoprecipitated immunoprecipitates immunoprecipitating immunoprecipitation immunoreaction immunoreactions immunoreactive immunoreactivity immunoregulation immunoregulatory immunosorbent immunosuppress immunosuppressant immunosuppressants immunosuppressed immunosuppresses immunosuppressing immunosuppression immunosuppressive immunotherapeutic immunotherapies immunotherapist immunotherapists immunotherapy immure immured immurement immurements immures immuring immutability immutable immutableness immutably imogen imp impact impacted impacter impacters impacting impaction impactions impactive impactor impactors impacts impaint impainted impainting impaints impair impaired impairer impairers impairing impairment impairments impairs impala impalas impale impaled impalement impalements impaler impalers impales impaling impalpability impalpable impalpably impanel impaneled impaneling impanelled impanelling impanelment impanelments impanels imparadise imparadised imparadises imparadising imparities imparity impart impartation imparted impartial impartiality impartially impartialness impartibility impartible impartibly imparting impartment imparts impassability impassable impassableness impassably impasse impasses impassibility impassible impassibleness impassibly impassion impassioned impassioning impassions impassive impassively impassiveness impassivity impaste impasted impastes impasting impasto impastoed impastos impatience impatiens impatient impatiently impawn impawned impawning impawns impeach impeachability impeachable impeached impeachers impeaches impeaching impeachment impeachments impearl impearled impearling impearls impeccability impeccable impeccably impecuniosity impecunious impecuniously impecuniousness imped impedance impede impeded impeder impeders impedes impediment impedimenta impedimental impedimentary impediments impeding impel impelled impeller impellers impelling impellor impellors impels impend impended impendent impending impends impenetrability impenetrable impenetrableness impenetrably impenetrate impenitence impenitent impenitently impenitents impera imperative imperatively imperativeness imperatives imperator imperatorial imperators imperatriz imperceivable imperceptibility imperceptible imperceptibleness imperceptibly imperceptive imperceptiveness imperceptivity impercipience impercipient imperfect imperfecta imperfectability imperfection imperfections imperfective imperfectly imperfectness imperfects imperforate imperforates imperia imperial imperialism imperialist imperialistic imperialistically imperialists imperially imperials imperil imperiled imperiling imperilled imperilling imperilment imperilments imperils imperious imperiously imperiousness imperishability imperishable imperishableness imperishably imperium impermanence impermanency impermanent impermanently impermeabilities impermeability impermeable impermeableness impermeably impermissibility impermissible impermissibly impersonal impersonality impersonalization impersonalize impersonalized impersonalizes impersonalizing impersonally impersonate impersonated impersonates impersonating impersonation impersonations impersonator impersonators impertinence impertinencies impertinency impertinent impertinently imperturbability imperturbable imperturbableness imperturbably impervious imperviously imperviousness impetiginous impetigo impetigos impetrate impetrated impetrates impetrating impetration impetrations impetuosities impetuosity impetuous impetuously impetuousness impetus impetuses impieties impiety imping impinge impinged impingement impingements impinger impingers impinges impinging impious impiously impiousness impish impishly impishness impitoyable impitoyables implacability implacable implacableness implacably implant implantable implantation implantations implanted implanter implanters implanting implants implausibility implausible implausibleness implausibly implead impleaded impleading impleads implement implementation implementations implemented implementer implementers implementing implementor implementors implements implicate implicated implicates implicating implication implications implicative implicatively implicativeness implicit implicitly implicitness implied implies implode imploded implodes imploding imploration implorations implore implored implorer implorers implores imploring imploringly implosion implosions implosive implosives implume imply implying impolite impolitely impoliteness impolitic impolitical impolitically impoliticly imponderability imponderable imponderableness imponderables imponderably impone imponed impones imponing import importability importable importance importancy important importantly importation importations imported importer importers importing imports importunate importunately importunateness importune importuned importunely importuner importuners importunes importuning importunities importunity impose imposed imposer imposers imposes imposing imposingly imposition impositions impossibilities impossibility impossible impossibleness impossibly impost imposter imposters imposthume impostor impostors imposts impostume imposture impostures impotence impotencies impotency impotent impotently impound impoundage impoundages impounded impounder impounders impounding impoundment impoundments impounds impoverish impoverished impoverisher impoverishers impoverishes impoverishing impoverishment impoverishments impracticability impracticable impracticableness impracticably impractical impracticalities impracticality impractically impracticalness imprecate imprecated imprecates imprecating imprecation imprecations imprecator imprecators imprecatory imprecise imprecisely impreciseness imprecision imprecisions impregnability impregnable impregnableness impregnably impregnant impregnants impregnate impregnated impregnates impregnating impregnation impregnations impregnator impregnators impresa impresario impresarios impresas impress impressed impresser impressers impresses impressibility impressible impressibly impressing impression impressionability impressionable impressionableness impressionably impressionism impressionist impressionistic impressionistically impressionists impressions impressive impressively impressiveness impressment impressments impressure impressures imprest imprests imprimatur imprimaturs imprimis imprint imprinted imprinter imprinters imprinting imprintings imprints imprison imprisonable imprisoned imprisoning imprisonment imprisonments imprisons improbabilist improbabilists improbabilities improbability improbable improbableness improbably improbity impromptu impromptus improper improperly improperness impropriate impropriated impropriates impropriating impropriation improprieties impropriety improvability improvable improve improved improvement improvements improver improvers improves improvidence improvident improvidently improving improvisation improvisational improvisationally improvisations improvisator improvisatore improvisatores improvisatori improvisatorial improvisators improvisatory improvise improvised improviser improvisers improvises improvising improvisor improvisors improviste imprudence imprudent imprudently imps impudence impudences impudencies impudency impudent impudently impudicity impugn impugnable impugned impugner impugners impugning impugns impuissance impuissances impuissant impulse impulsed impulses impulsing impulsion impulsive impulsively impulsiveness impulsivity impunities impunity impure impurely impureness impurer impurest impurities impurity imputability imputable imputably imputation imputations imputative imputatively impute imputed imputes imputing in inability inaccessibility inaccessible inaccessibly inaccuracies inaccuracy inaccurate inaccurately inaccurateness inaction inactivate inactivated inactivates inactivating inactivation inactivations inactive inactively inactiveness inactivity inadequacies inadequacy inadequate inadequately inadequateness inadmissibility inadmissible inadmissibly inadvertence inadvertencies inadvertency inadvertent inadvertently inadvisability inadvisable inadvisably inalienability inalienable inalienably inalterability inalterable inalterableness inalterably inamorata inamoratas inamorato inamoratos inane inanely inaneness inaner inanest inanimate inanimately inanimateness inanities inanition inanity inapparent inapparently inappeasable inappetence inappetences inappetencies inappetency inappetent inapplicability inapplicable inapplicably inapposite inappositely inappositeness inappreciable inappreciably inappreciative inappreciatively inappreciativeness inapproachability inapproachable inapproachably inappropriate inappropriately inappropriateness inapt inaptitude inaptly inaptness inarguable inarguably inarticulacy inarticulate inarticulately inarticulateness inartistic inartistically inasmuch inassimilable inattention inattentive inattentively inattentiveness inaudibility inaudible inaudibly inaugural inaugurals inaugurate inaugurated inaugurates inaugurating inauguration inaugurations inaugurator inaugurators inauguratory inauspicious inauspiciously inauspiciousness inauthentic inauthenticity inboard inboards inborn inbound inbounded inbounding inbounds inbreathe inbreathed inbreathes inbreathing inbred inbreed inbreeder inbreeders inbreeding inbreedings inbreeds inbuilt inca incaic incalculability incalculable incalculableness incalculably incalescence incalescent incan incandesce incandesced incandescence incandescent incandescently incandesces incandescing incans incantation incantational incantations incantatory incapability incapable incapableness incapably incapacitant incapacitants incapacitate incapacitated incapacitates incapacitating incapacitation incapacitations incapacities incapacity incapsulate incapsulated incapsulates incapsulating incapsulation incapsulations incapsulator incapsulators incarcerate incarcerated incarcerates incarcerating incarceration incarcerations incarcerator incarcerators incarnadine incarnadined incarnadines incarnadining incarnate incarnated incarnates incarnating incarnation incarnations incarnator incarnators incas incase incased incasement incasements incases incasing incautious incautiously incautiousness incendiaries incendiarism incendiary incense incensed incenses incensing incentive incentives incentivize incentivized incentivizes incentivizing incept incepted incepting inception inceptions inceptive inceptives inceptor inceptors incepts incertitude incessancy incessant incessantly incest incestuous incestuously incestuousness inch inched incher inchers inches inching inchmeal inchoate inchoately inchoateness inchoative inchoatively inchoatives inchworm inchworms incidence incidences incident incidental incidentally incidentals incidents incinerate incinerated incinerates incinerating incineration incinerations incinerator incinerators incipience incipiency incipient incipiently incipit incipits incise incised incises incising incision incisions incisive incisively incisiveness incisor incisors incitation incitations incite incited incitement incitements inciter inciters incites inciting incivilities incivility inclasp inclasped inclasping inclasps inclemency inclement inclemently inclinable inclination inclinations incline inclined incliner incliners inclines inclining inclinometer inclinometers inclose inclosed incloses inclosing includable include included includes includible including inclusion inclusionary inclusions inclusive inclusively inclusiveness incoercible incogitant incognita incognitas incognito incognitos incognitum incognizance incognizant incoherence incoherencies incoherency incoherent incoherently incoherentness incombustibility incombustible incombustibles incombustibly income incomes incoming incomings incommensurability incommensurable incommensurables incommensurably incommensurate incommensurately incommensurateness incommode incommoded incommodes incommoding incommodious incommodiously incommodiousness incommodities incommodity incommunicability incommunicable incommunicably incommunicado incommunicative incommunicatively incommunicativeness incommutability incommutable incommutableness incommutably incomparability incomparable incomparableness incomparably incompatibilities incompatibility incompatible incompatibleness incompatibles incompatibly incompetence incompetency incompetent incompetently incompetents incomplete incompletely incompleteness incompletion incompletions incompliance incompliancy incompliant incompliantly incomprehensibility incomprehensible incomprehensibleness incomprehensibly incomprehension incomprehensive incomprehensively incomprehensiveness incompressibility incompressible incomputability incomputable inconceivability inconceivable inconceivableness inconceivably inconcinnity inconclusive inconclusively inconclusiveness incondensability incondensable incondensible incondite inconditely inconformity incongruence incongruences incongruent incongruently incongruities incongruity incongruous incongruously incongruousness inconsequence inconsequent inconsequential inconsequentiality inconsequentially inconsequentialness inconsequently inconsiderable inconsiderableness inconsiderably inconsiderate inconsiderately inconsiderateness inconsideration inconsistence inconsistences inconsistencies inconsistency inconsistent inconsistently inconsolability inconsolable inconsolableness inconsolably inconsonance inconsonant inconsonantly inconspicuous inconspicuously inconspicuousness inconstancies inconstancy inconstant inconstantly inconsumable inconsumably incontestability incontestable incontestableness incontestably incontinence incontinent incontinently incontrollable incontrovertibility incontrovertible incontrovertibleness incontrovertibly inconvenience inconvenienced inconveniences inconveniencing inconvenient inconveniently inconvertibility inconvertible inconvertibleness inconvertibly inconvincible incoordinate incoordinately incoordination incoordinations incorporable incorporate incorporated incorporates incorporating incorporation incorporations incorporative incorporator incorporators incorporeal incorporeality incorporeally incorporeity incorrect incorrectly incorrectness incorrigibility incorrigible incorrigibleness incorrigibles incorrigibly incorrupt incorruptibility incorruptible incorruptibly incorruption incorruptly incorruptness increasable increase increased increaser increasers increases increasing increasingly increate increately incredibility incredible incredibleness incredibly incredulity incredulous incredulously incredulousness increment incremental incrementalism incrementalist incrementalists incrementally incremented incrementing increments increscent incretion incretions incriminate incriminated incriminates incriminating incrimination incriminations incriminator incriminators incriminatory incrust incrustation incrustations incrusted incrusting incrusts incubate incubated incubates incubating incubation incubational incubations incubative incubator incubators incubi incubus incubuses incudes inculcate inculcated inculcates inculcating inculcation inculcations inculcator inculcators inculpable inculpate inculpated inculpates inculpating inculpation inculpations inculpatory incult incumbencies incumbency incumbent incumbently incumbents incunable incunables incunabula incunabular incunabulars incunabulis incunabulum incur incurability incurable incurableness incurables incurably incuriosity incurious incuriously incuriousness incurred incurrence incurrences incurrent incurring incurs incursion incursions incurvate incurvated incurvates incurvating incurvation incurvations incurvature incurve incurved incurves incurving incus incuse incused incuses incusing indaba indabas indagate indagated indagates indagating indagation indagator indagators indamine indamines indebted indebtedness indecencies indecency indecent indecently indecipherability indecipherable indecipherableness indecipherably indecision indecisive indecisively indecisiveness indeclinable indecomposable indecorous indecorously indecorousness indecorum indecorums indeed indefatigability indefatigable indefatigableness indefatigably indefeasibility indefeasible indefeasibly indefectibility indefectible indefectibly indefensibility indefensible indefensibleness indefensibly indefinability indefinable indefinableness indefinables indefinably indefinite indefinitely indefiniteness indehiscence indehiscent indelibility indelible indelibleness indelibly indelicacies indelicacy indelicate indelicately indelicateness indemnification indemnifications indemnificatory indemnified indemnifier indemnifiers indemnifies indemnify indemnifying indemnities indemnity indemonstrability indemonstrable indemonstrableness indemonstrably indene indenes indent indentation indentations indented indenter indenters indenting indention indents indenture indentured indentures indenturing independence independencies independency independent independently independents inderal indescribability indescribable indescribableness indescribably indestructibility indestructible indestructibleness indestructibly indeterminable indeterminably indeterminacy indeterminate indeterminately indeterminateness indetermination indeterminations indeterminism indeterminist indeterministic indeterminists index indexation indexed indexer indexers indexes indexical indexing india indiaman indian indiana indianapolis indianism indianist indianists indianization indianize indianized indianizes indianizing indianness indians indic indican indicans indicant indicants indicate indicated indicates indicating indication indicational indications indicative indicatively indicatives indicator indicators indicatory indices indicia indicium indics indict indictable indicted indictee indictees indicter indicters indicting indiction indictions indictment indictments indictor indictors indicts indie indies indifference indifferency indifferent indifferentism indifferentist indifferentists indifferently indigen indigence indigene indigenes indigenization indigenizations indigenize indigenized indigenizes indigenizing indigenous indigenously indigenousness indigens indigent indigently indigents indigested indigestibility indigestible indigestibly indigestion indigirka indign indignant indignantly indignation indignities indignity indigo indigoes indigos indigotin indigotins indirect indirection indirectly indirectness indiscernible indiscernibly indisciplinable indiscipline indisciplined indisciplines indiscoverable indiscreet indiscreetly indiscreetness indiscrete indiscretion indiscretions indiscriminate indiscriminately indiscriminateness indiscriminating indiscriminatingly indiscrimination indiscriminations indiscriminative indispensability indispensable indispensableness indispensables indispensably indispose indisposed indisposes indisposing indisposition indispositions indisputable indisputableness indisputably indissociable indissociably indissolubility indissoluble indissolubleness indissolubly indistinct indistinctive indistinctively indistinctiveness indistinctly indistinctness indistinguishability indistinguishable indistinguishableness indistinguishably indite indited inditement inditements inditer inditers indites inditing indium indiums individual individualism individualist individualistic individualistically individualists individualities individuality individualization individualizations individualize individualized individualizes individualizing individually individuals individuate individuated individuates individuating individuation indivisibility indivisible indivisibleness indivisibly indo indochina indochinese indocile indocility indocin indoctrinate indoctrinated indoctrinates indoctrinating indoctrination indoctrinations indoctrinator indoctrinators indole indoleacetic indoleamine indoleamines indolebutyric indolence indolent indolently indoles indologist indologists indology indomethacin indomethacins indomitability indomitable indomitableness indomitably indonesia indonesian indonesians indoor indoors indophenol indophenols indorsable indorse indorsed indorsement indorsements indorser indorsers indorses indorsing indorsor indorsors indoxyl indoxyls indra indraft indrafts indrawn indri indris indubitability indubitable indubitableness indubitably induce induced inducement inducements inducer inducers induces inducibility inducible inducing induct inductance inducted inductee inductees inducting induction inductions inductive inductively inductiveness inductor inductors inducts indue indued indues induing indulge indulged indulgence indulgenced indulgences indulgencing indulgent indulgently indulger indulgers indulges indulging indult indults indument indumenta induments indumentum induplicate indurate indurated indurates indurating induration indurations indurative indus indusia indusium industrial industrialism industrialist industrialists industrialization industrializations industrialize industrialized industrializes industrializing industrially industrials industries industrious industriously industriousness industry industrywide indwell indweller indwellers indwelling indwells indwelt inebriant inebriants inebriate inebriated inebriates inebriating inebriation inebriations inebriety inedibility inedible inedibly inedited ineducability ineducable ineffability ineffable ineffableness ineffably ineffaceability ineffaceable ineffaceably ineffective ineffectively ineffectiveness ineffectual ineffectuality ineffectually ineffectualness inefficacious inefficaciously inefficaciousness inefficacy inefficiencies inefficiency inefficient inefficiently inegalitarian inelastic inelasticity inelegance inelegant inelegantly ineligibility ineligible ineligibles ineligibly ineloquence ineloquent ineloquently ineluctability ineluctable ineluctably ineludible inenarrable inept ineptitude ineptly ineptness inequalities inequality inequitable inequitableness inequitably inequities inequity inequivalve inequivalved ineradicability ineradicable ineradicably inerrancy inerrant inerrantism inerrantist inerrantists inert inertia inertial inertially inertly inertness inescapable inescapably inessential inessentiality inessentials inestimable inestimably inevitabilist inevitabilists inevitabilities inevitability inevitable inevitableness inevitably inexact inexactitude inexactitudes inexactly inexactness inexcusable inexcusableness inexcusably inexhaustibility inexhaustible inexhaustibleness inexhaustibly inexistence inexistent inexorability inexorable inexorableness inexorably inexpedience inexpediency inexpedient inexpediently inexpensive inexpensively inexpensiveness inexperience inexperienced inexpert inexpertly inexpertness inexpiable inexpiably inexplainable inexplainably inexplicability inexplicable inexplicableness inexplicably inexplicit inexpressibility inexpressible inexpressibleness inexpressibly inexpressive inexpressively inexpressiveness inexpugnability inexpugnable inexpugnableness inexpugnably inexpungible inextensible inextinguishable inextinguishably inextirpable inextricability inextricable inextricableness inextricably infall infallibility infallible infallibleness infallibly infalling infalls infamies infamous infamously infamousness infamy infancies infancy infant infanta infantas infante infantes infanticidal infanticide infanticides infantile infantilism infantility infantilization infantilizations infantilize infantilized infantilizes infantilizing infantine infantries infantry infantryman infantrymen infants infantum infarct infarcted infarction infarctions infarcts infare infares infatuate infatuated infatuatedly infatuates infatuating infatuation infatuations infauna infaunal infaunas infaustus infeasibility infeasible infect infecta infected infecting infection infections infectious infectiously infectiousness infective infectiveness infectivity infector infectors infects infecundity infelicities infelicitous infelicitously infelicity infer inferable inferably inference inferences inferential inferentially inferior inferiority inferiorly inferiors infernal infernally inferno infernos inferred inferrer inferrers inferrible inferring infers infertile infertility infest infestant infestants infestation infestations infested infester infesters infesting infests infidel infidelities infidelity infidelium infidels infield infielder infielders infields infight infighter infighters infighting infights infill infills infiltrate infiltrated infiltrates infiltrating infiltration infiltrations infiltrative infiltrator infiltrators infinite infinitely infiniteness infinitesimal infinitesimally infinitesimals infinities infinitival infinitive infinitively infinitives infinitude infinitudes infinitum infinity infirm infirmaries infirmary infirmities infirmity infirmly infix infixation infixations infixed infixes infixing inflame inflamed inflamer inflamers inflames inflaming inflammability inflammable inflammableness inflammably inflammation inflammations inflammatorily inflammatory inflatable inflatables inflate inflated inflater inflaters inflates inflating inflation inflationary inflationism inflationist inflationists inflations inflator inflators inflect inflectable inflected inflecting inflection inflectional inflectionally inflections inflective inflector inflectors inflects inflexed inflexibility inflexible inflexibleness inflexibly inflexion inflexions inflict inflicted inflicter inflicters inflicting infliction inflictions inflictive inflictor inflictors inflicts inflorescence inflorescences inflorescent inflow inflows influence influenceable influenced influencer influencers influences influencing influent influential influentially influentials influents influenza influenzal influx influxes info infobahn infold infolded infolder infolders infolding infoldment infoldments infolds infomercial infomercials inform informal informalities informality informally informant informants informatics information informational informationally informative informatively informativeness informatorily informatory informed informedly informer informercial informercials informers informing informs infotainment infotainments infra infraclass infraclasses infract infracted infracting infraction infractions infractor infractors infracts infrahuman infrahumans infrangibility infrangible infrangibly infrared infrareds infrasonic infrasound infrasounds infraspecific infrastructure infrastructures infrequence infrequency infrequent infrequently infringe infringed infringement infringements infringer infringers infringes infringing infructescence infructescences infundibula infundibular infundibulate infundibuliform infundibulum infuriate infuriated infuriates infuriating infuriatingly infuriation infuriations infuse infused infuser infusers infuses infusibility infusible infusibleness infusing infusion infusions infusorial infusorian infusorians infâme ing ingather ingathered ingathering ingathers ingeminate ingeminated ingeminates ingeminating ingenious ingeniously ingeniousness ingenue ingenues ingenuities ingenuity ingenuous ingenuously ingenuousness ingest ingesta ingested ingestible ingesting ingestion ingestions ingestive ingests ingle inglenook inglenooks ingles inglese inglorious ingloriously ingloriousness ingoing ingot ingots ingrain ingrained ingrainedly ingraining ingrains ingrate ingrates ingratiate ingratiated ingratiates ingratiating ingratiatingly ingratiation ingratiations ingratiatory ingratitude ingredient ingredients ingres ingress ingression ingressions ingressive ingressiveness ingrowing ingrown ingrownness ingrowth ingrowths inguinal inguinale ingurgitate ingurgitated ingurgitates ingurgitating ingurgitation ingurgitations ingénue ingénues inhabit inhabitability inhabitable inhabitancies inhabitancy inhabitant inhabitants inhabitation inhabitations inhabited inhabiter inhabiters inhabiting inhabits inhalant inhalants inhalation inhalational inhalations inhalator inhalators inhale inhaled inhaler inhalers inhales inhaling inharmonic inharmonies inharmonious inharmoniously inharmoniousness inharmony inhere inhered inherence inherency inherent inherently inheres inhering inherit inheritability inheritable inheritableness inheritance inheritances inherited inheriting inheritor inheritors inheritress inheritresses inheritrix inheritrixes inherits inhibin inhibins inhibit inhibitable inhibited inhibiter inhibiters inhibiting inhibition inhibitions inhibitive inhibitor inhibitors inhibitory inhibits inholder inholders inholding inholdings inhomogeneities inhomogeneity inhomogeneous inhospitable inhospitableness inhospitably inhospitality inhuman inhumane inhumanely inhumanities inhumanity inhumanly inhumanness inhumation inhumations inhume inhumed inhumer inhumers inhumes inhuming inigo inimical inimically inimitability inimitable inimitableness inimitably inion inions iniquities iniquitous iniquitously iniquitousness iniquity initial initialed initialing initialism initialization initializations initialize initialized initializer initializers initializes initializing initialled initialling initially initialness initials initiate initiated initiates initiating initiation initiations initiative initiatively initiatives initiator initiators initiatory initio inject injectable injectables injectant injectants injected injecting injection injections injective injector injectors injects injudicious injudiciously injudiciousness injunction injunctions injunctive injure injured injurer injurers injures injuries injuring injurious injuriously injuriousness injury injustice injustices ink inkberries inkberry inkblot inkblots inked inker inkers inkhorn inkhorns inkier inkiest inkiness inking inkle inkles inkling inklings inkpot inkpots inks inkstand inkstands inkstone inkstones inkwell inkwells inky inlace inlaced inlacement inlacements inlaces inlacing inlaid inland inlander inlanders inlay inlayer inlayers inlaying inlays inlet inlets inlier inliers inly inlying inmate inmates inmesh inmeshed inmeshes inmeshing inmeshment inmeshments inmost inn innards innate innately innateness inner innerly innermost innerness innersole innersoles innerspring innersprings innervate innervated innervates innervating innervation innervational innervations innerve innerved innerves innerving innerwear innigkeit inning innings innkeeper innkeepers innocence innocencies innocency innocent innocently innocents innocuous innocuously innocuousness innominate innovate innovated innovates innovating innovation innovational innovations innovative innovatively innovativeness innovator innovators innovatory inns innsbruck innuendo innuendoes innuit innuits innumerable innumerableness innumerably innumeracy innumerate innumerates innumerous innutrition innutritious inobservance inobservant inobtrusive inocula inoculability inoculable inoculant inoculants inoculate inoculated inoculates inoculating inoculation inoculations inoculative inoculator inoculators inoculum inoculums inodorous inoffensive inoffensively inoffensiveness inofficious inoperable inoperably inoperative inoperativeness inoperculate inopportune inopportunely inopportuneness inordinacy inordinate inordinately inordinateness inorganic inorganically inosculate inosculated inosculates inosculating inosculation inosculations inositol inositols inotropic inpatient inpatients inphase inpouring inpourings input inputs inputted inputting inquest inquests inquietude inquietudes inquiline inquilines inquilinism inquilinity inquilinous inquire inquired inquirer inquirers inquires inquiries inquiring inquiringly inquiry inquisition inquisitional inquisitions inquisitive inquisitively inquisitiveness inquisitor inquisitorial inquisitorially inquisitors inro inroad inroads inrush inrushes ins insalivate insalivated insalivates insalivating insalivation insalivations insalubrious insalubriously insalubrity insane insanely insaneness insanitary insanitation insanities insanity insatiability insatiable insatiableness insatiably insatiate insatiately insatiateness inscape inscapes inscribe inscribed inscriber inscribers inscribes inscribing inscription inscriptional inscriptions inscriptive inscriptively inscroll inscrolled inscrolling inscrolls inscrutability inscrutable inscrutableness inscrutably insculp insculped insculping insculps inseam inseams insect insectaria insectaries insectarium insectary insecticidal insecticidally insecticide insecticides insectile insectival insectivore insectivores insectivorous insects insecure insecurely insecureness insecurities insecurity inselberg inselberge inselberges inselbergs inseminate inseminated inseminates inseminating insemination inseminations inseminator inseminators insensate insensately insensateness insensibility insensible insensibleness insensibly insensitive insensitively insensitiveness insensitivity insentience insentient inseparability inseparable inseparableness inseparably insert inserted inserter inserters inserting insertion insertional insertions inserts insessorial inset insets insetted insetting inshallah inshore inshrine inshrined inshrinement inshrinements inshrines inshrining inside insider insiders insides insidious insidiously insidiousness insight insightful insightfully insightfulness insights insigne insignia insignias insignificance insignificancies insignificancy insignificant insignificantly insincere insincerely insincerity insinuate insinuated insinuates insinuating insinuatingly insinuation insinuations insinuative insinuator insinuators insinuatory insipid insipidities insipidity insipidly insipidness insipidus insipience insist insisted insistence insistency insistent insistently insister insisters insisting insistingly insists insnare insnared insnarement insnarements insnarer insnarers insnares insnaring insobriety insociability insociable insociably insofar insolate insolated insolates insolating insolation insolations insole insolence insolent insolently insolents insoles insolubility insolubilization insolubilizations insolubilize insolubilized insolubilizes insolubilizing insoluble insolubleness insolubles insolubly insolvability insolvable insolvably insolvencies insolvency insolvent insolvents insomnia insomniac insomniacs insomuch insouciance insouciant insouciantly insoul insouled insouling insouls inspan inspanned inspanning inspans inspect inspected inspecting inspection inspectional inspections inspective inspector inspectoral inspectorate inspectorates inspectorial inspectors inspectorship inspectorships inspects insphere insphered inspheres insphering inspiration inspirational inspirationally inspirations inspirator inspirators inspiratory inspire inspired inspiredly inspirer inspirers inspires inspiring inspiringly inspirit inspirited inspiriting inspiritingly inspirits inspissate inspissated inspissates inspissating inspissation inspissations inspissator inspissators instabilities instability instal install installation installations installed installer installers installing installment installments installs instalment instalments instals instance instanced instances instancies instancing instancy instant instantaneity instantaneous instantaneously instantaneousness instanter instantiate instantiated instantiates instantiating instantiation instantiations instantly instantness instants instar instarred instarring instars instate instated instatement instates instating instauration instaurations instead instep insteps instigate instigated instigates instigating instigation instigations instigative instigator instigators instil instill instillation instillations instilled instiller instillers instilling instillment instills instils instinct instinctive instinctively instincts instinctual instinctually institute instituted instituter instituters institutes instituting institution institutional institutionalism institutionalist institutionalists institutionalization institutionalizations institutionalize institutionalized institutionalizes institutionalizing institutionally institutions institutor institutors instroke instrokes instruct instructed instructing instruction instructional instructions instructive instructively instructiveness instructor instructors instructorship instructorships instructress instructresses instructs instrument instrumental instrumentalism instrumentalist instrumentalists instrumentalities instrumentality instrumentally instrumentals instrumentation instrumented instrumenting instruments insubordinate insubordinately insubordinates insubordination insubordinations insubstantial insubstantiality insufferable insufferableness insufferably insufficiencies insufficiency insufficient insufficiently insufflate insufflated insufflates insufflating insufflation insufflations insufflator insufflators insulant insulants insular insularism insularity insularly insulate insulated insulates insulating insulation insulations insulative insulator insulators insulin insult insulted insulter insulters insulting insultingly insults insuperability insuperable insuperableness insuperably insupportable insupportableness insupportably insuppressible insuppressibly insurability insurable insurance insurances insure insured insureds insurer insurers insures insurgence insurgencies insurgency insurgent insurgently insurgents insuring insurmountability insurmountable insurmountableness insurmountably insurrection insurrectional insurrectionary insurrectionism insurrectionist insurrectionists insurrections insusceptibility insusceptible insusceptibly intact intactly intactness intaglio intaglios intake intakes intangibility intangible intangibleness intangibles intangibly intarsia intarsias integer integers integrability integrable integral integrality integrally integrals integrand integrands integrant integrate integrated integrates integrating integration integrationist integrationists integrations integrative integrator integrators integrity integro integument integumentary intellect intellection intellections intellective intellectively intellectronics intellects intellectual intellectualism intellectualist intellectualistic intellectualists intellectuality intellectualization intellectualizations intellectualize intellectualized intellectualizer intellectualizers intellectualizes intellectualizing intellectually intellectualness intellectuals intelligam intelligence intelligencer intelligencers intelligences intelligent intelligential intelligently intelligentsia intelligibility intelligible intelligibleness intelligibly intelligunt intelsat intemperance intemperate intemperately intemperateness intend intendance intendances intendancies intendancy intendant intendants intended intendedly intender intenders intending intendment intendments intends intenerate intenerated intenerates intenerating inteneration intenerations intense intensely intenseness intenser intensest intensification intensifications intensified intensifier intensifiers intensifies intensify intensifying intension intensional intensionality intensionally intensions intensities intensity intensive intensively intensiveness intensives intent intention intentional intentionality intentionally intentioned intentions intently intentness intents inter interabang interabangs interact interactant interactants interacted interacting interaction interactional interactions interactive interactively interactivity interacts interagency interallelic interallied interanimation interanimations interannual interassociation interassociations interatomic interavailability interbank interbasin interbed interbehavior interbehavioral interborough interbrain interbrains interbranch interbred interbreed interbreeding interbreeds intercalary intercalate intercalated intercalates intercalating intercalation intercalations intercalative intercalibration intercampus intercaste intercede interceded interceder interceders intercedes interceding intercell intercellular intercensal intercept intercepted intercepter intercepters intercepting interception interceptions interceptive interceptor interceptors intercepts intercession intercessional intercessions intercessor intercessors intercessory interchain interchange interchangeability interchangeable interchangeableness interchangeably interchanged interchanger interchangers interchanges interchanging interchannel interchromosomal interchurch intercity interclan interclass interclavicle interclavicles interclavicular interclub intercluster intercoastal intercollegiate intercolonial intercolumniation intercolumniations intercom intercommunal intercommunicate intercommunicated intercommunicates intercommunicating intercommunication intercommunications intercommunicative intercommunion intercommunions intercommunity intercompany intercomparable intercompare intercomparison intercomprehensibility intercoms interconnect interconnectable interconnected interconnectedness interconnectible interconnecting interconnection interconnections interconnectivity interconnects intercontinental interconversion interconvert interconverted interconvertibility interconvertible interconverting interconverts intercool intercooled intercooler intercoolers intercooling intercools intercorporate intercorrelate intercorrelation intercortical intercostal intercostals intercountry intercounty intercouple intercourse intercrater intercrop intercropped intercropping intercrops intercross intercrystalline intercultural interculturally interculture intercurrent intercut intercuts intercutting interdealer interdenominational interdental interdentally interdentals interdepartmental interdepartmentally interdepend interdependence interdependencies interdependency interdependent interdependently interdialectal interdict interdicted interdicting interdiction interdictions interdictive interdictively interdictor interdictors interdictory interdicts interdictus interdiffuse interdiffusion interdigitate interdigitated interdigitates interdigitating interdigitation interdisciplinary interdistrict interdivisional interdominion interelectrode interelectron interelectronic interepidemic interest interested interestedly interestedness interesting interestingly interestingness interests interethnic interface interfaced interfaces interfacial interfacing interfacings interfaculty interfaith interfamilial interfamily interfascicular interfere interfered interference interferences interferential interferer interferers interferes interfering interferingly interferogram interferograms interferometer interferometers interferometric interferometrically interferometry interferon interfertile interfertility interfiber interfile interfirm interflow interfluve interfluves interfluvial interfold interfraternity interfuse interfused interfuses interfusing interfusion intergalactic intergalactically intergang intergeneration intergenerational intergeneric interglacial interglacials intergovernmental intergovernmentally intergradation intergradational intergradations intergrade intergraded intergrades intergrading intergraft intergranular intergroup intergrowth interhemispheric interim interindividual interindustry interinfluence interinstitutional interinvolve interionic interior interiority interiorization interiorizations interiorize interiorized interiorizes interiorizing interiorly interiors interisland interject interjected interjecting interjection interjectional interjectionally interjections interjector interjectors interjectory interjects interjurisdictional interlace interlaced interlacement interlaces interlacing interlacustrine interlaken interlaminar interlaminate interlaminated interlaminates interlaminating interlamination interlaminations interlanguage interlanguages interlard interlarded interlarding interlards interlay interlayer interleaf interleave interleaved interleaves interleaving interlend interleukin interleukins interlibrary interline interlinear interlinearly interlineation interlined interliner interlines interlingua interlining interlinings interlink interlinked interlinking interlinks interlobular interlocal interlock interlocked interlocking interlocks interlocution interlocutions interlocutor interlocutors interlocutory interlope interloped interloper interlopers interlopes interloping interlude interludes interlunar interlunary intermale intermarginal intermarriage intermarriages intermarried intermarries intermarry intermarrying intermeddle intermeddled intermeddler intermeddlers intermeddles intermeddling intermediacy intermediaries intermediary intermediate intermediated intermediately intermediateness intermediates intermediating intermediation intermediations intermediator intermediators intermedin intermedins intermembrane intermenstrual interment interments intermesh intermeshed intermeshes intermeshing intermetallic intermezzi intermezzo intermezzos interminability interminable interminableness interminably intermingle intermingled intermingles intermingling interministerial intermission intermissionless intermissions intermit intermitotic intermits intermitted intermittence intermittency intermittent intermittently intermitter intermitters intermitting intermix intermixed intermixes intermixing intermixture intermixtures intermodal intermodulation intermodulations intermolecular intermolecularly intermont intermontane intermountain intern internal internality internalization internalizations internalize internalized internalizes internalizing internally internals international internationale internationalism internationalist internationalists internationality internationalization internationalizations internationalize internationalized internationalizes internationalizing internationally internationals interne internecine interned internee internees internet interneuron interneuronal interneurons interning internist internists internment internodal internode internodes interns internship internships internuclear internucleon internucleonic internucleotide internuncial internuncially internuncio internuncios interobserver interocean interoceanic interoceptive interoceptor interoceptors interoffice interoperability interoperable interoperative interorbital interorgan interorganizational interosculate interosculated interosculates interosculating interpandemic interparish interparochial interparoxysmal interparticle interparty interpellate interpellated interpellates interpellating interpellation interpellations interpellator interpellators interpenetrate interpenetrated interpenetrates interpenetrating interpenetration interpenetrations interperceptual interpermeate interpersonal interpersonally interphalangeal interphase interphased interphases interphasing interplanetary interplant interplanted interplanting interplants interplay interplayed interplaying interplays interplead interpleaded interpleader interpleaders interpleading interpleads interpluvial interpoint interpol interpolate interpolated interpolates interpolating interpolation interpolations interpolative interpolator interpolators interpopulation interpopulational interposal interpose interposed interposer interposers interposes interposing interposition interpositions interpret interpretability interpretable interpretableness interpretably interpretation interpretational interpretations interpretative interpretatively interpreted interpreter interpreters interpreting interpretive interpretively interprets interprofessional interprovincial interproximal interpsychic interpupillary interracial interracially interred interregional interregna interregnal interregnum interregnums interrelate interrelated interrelatedly interrelatedness interrelates interrelating interrelation interrelations interrelationship interrelationships interreligious interrenal interring interrobang interrobangs interrogate interrogated interrogatee interrogatees interrogates interrogating interrogation interrogational interrogations interrogative interrogatively interrogatives interrogator interrogatories interrogatorily interrogators interrogatory interrogee interrogees interrow interrupt interrupted interrupter interrupters interruptible interrupting interruption interruptions interruptive interruptor interruptors interrupts interruptus inters interscholastic interscholastically interschool intersect intersected intersecting intersection intersectional intersections intersects intersegment intersegmental intersensory interservice intersession intersessional intersessions intersex intersexes intersexual intersexuality intersexually intersocietal intersociety interspace interspaced interspaces interspacing interspatial interspecies interspecific intersperse interspersed interspersedly intersperses interspersing interspersion interspersions interstadial interstage interstate interstates interstation interstellar intersterile intersterility interstice interstices interstimulation interstimulus interstitial interstitially interstrain interstrand interstratification interstratify intersubjective intersubjectively intersubjectivity intersubstitutability intersubstitutable intersystem interterm interterminal interterritorial intertestamental intertexture intertextures intertidal intertidally intertie interties intertill intertillage intertilled intertilling intertills intertranslatable intertransmutation intertrial intertribal intertroop intertropical intertwine intertwined intertwinement intertwinements intertwines intertwining intertwist intertwisted intertwisting intertwists interunion interunit interuniversity interurban interval intervale intervales intervalic intervalley intervallic intervalometer intervalometers intervals intervene intervened intervener interveners intervenes intervening intervenor intervenors intervention interventional interventionism interventionist interventionists interventions interventricular intervertebral intervertebrally interview interviewable interviewed interviewee interviewees interviewer interviewers interviewing interviews intervillage intervisibility intervisible intervisitation intervocalic intervocalically interwar interweave interweaves interweaving interwired interwork interworking interwove interwoven interzonal interzone intestacies intestacy intestate intestates intestinal intestinally intestine intestines inthrall inthralled inthralling inthrallingly inthrallment inthralls inthrone inthroned inthronement inthronements inthrones inthroning inti intima intimacies intimacy intimae intimal intimas intimate intimated intimately intimateness intimater intimaters intimates intimating intimation intimations intime intimidate intimidated intimidates intimidating intimidatingly intimidation intimidations intimidator intimidators intimidatory intinction intinctions intine intines intis intitule intituled intitules intituling into intolerability intolerable intolerableness intolerably intolerance intolerant intolerantly intolerantness intonate intonated intonates intonating intonation intonational intonations intone intoned intonement intonements intoner intoners intones intoning intoxicant intoxicants intoxicate intoxicated intoxicatedly intoxicates intoxicating intoxicatingly intoxication intoxications intoxicative intoxicator intoxicators intra intracardiac intracardial intracardially intracellular intracellularly intracerebral intracerebrally intracoastal intracompany intracranial intracranially intractability intractable intractableness intractably intracutaneous intracutaneously intracytoplasmic intraday intradepartmental intradermal intradermally intrados intradoses intraepithelial intragalactic intragenic intralingual intramolecular intramolecularly intramural intramurally intramuscular intramuscularly intranasal intranasally intransigeance intransigeant intransigeantly intransigence intransigency intransigent intransigently intransigents intransitive intransitively intransitiveness intransitives intransitivity intranuclear intraocular intraocularly intraperitoneal intraperitoneally intrapersonal intrapersonally intraplate intrapopulation intrapreneur intrapreneurial intrapreneurialism intrapreneurially intrapreneurs intrapsychic intrapsychically intrapulmonary intraspecies intraspecific intrastate intrathecal intrathecally intrathoracic intrathoracically intrauterine intravasation intravasations intravascular intravascularly intravenous intravenouses intravenously intraventricular intraventricularly intravital intravitally intravitam intrazonal intreat intreated intreating intreatingly intreatment intreats intrench intrenched intrenches intrenching intrenchment intrenchments intrepid intrepidity intrepidly intrepidness intricacies intricacy intricate intricately intricateness intrigant intrigants intriguant intriguants intrigue intrigued intriguer intriguers intrigues intriguing intriguingly intrinsic intrinsical intrinsically intro introduce introduced introducer introducers introduces introducible introducing introduction introductions introductorily introductory introgressant introgressants introgression introgressions introgressive introit introits introject introjected introjecting introjection introjections introjects intromission intromissions intromissive intromit intromits intromitted intromittent intromitter intromitters intromitting intron introns introrse intros introspect introspected introspecting introspection introspectional introspectionism introspectionist introspectionistic introspectionists introspective introspectively introspectiveness introspects introversion introversions introversive introversively introvert introverted introverting introverts intrude intruded intruder intruders intrudes intruding intrusion intrusions intrusive intrusively intrusiveness intrust intrusted intrusting intrusts intubate intubated intubates intubating intubation intubational intubationally intubations intuit intuitable intuited intuiting intuition intuitional intuitionally intuitionism intuitionist intuitionists intuitions intuitive intuitively intuitiveness intuits intumesce intumesced intumescence intumescences intumescent intumesces intumescing intussuscept intussuscepted intussuscepting intussusception intussusceptions intussusceptive intussuscepts intwine intwined intwinement intwinements intwines intwining intwist intwisted intwisting intwists inuit inuits inuktitut inulase inulases inulin inulins inunction inunctions inundate inundated inundates inundating inundation inundations inundator inundators inundatory inupiaq inupiaqs inupiat inupiats inure inured inurement inurements inures inuring inurn inurned inurning inurns inutile inutilely inutility inuvik invade invaded invader invaders invades invading invaginate invaginated invaginates invaginating invagination invaginations invalid invalidate invalidated invalidates invalidating invalidation invalidations invalidator invalidators invalided invaliding invalidism invalidity invalidly invalids invaluable invaluableness invaluably invariability invariable invariableness invariably invariance invariant invariantly invariants invasion invasions invasive invasively invasiveness invective invectively invectiveness invectives inveigh inveighed inveigher inveighers inveighing inveighs inveigle inveigled inveiglement inveiglements inveigler inveiglers inveigles inveigling invenient invenit invent invented inventible inventing invention inventional inventions inventive inventively inventiveness inventor inventorial inventorially inventoried inventories inventors inventory inventorying inventress inventresses invents inveracities inveracity invercargill inverness invernesses inverse inversely inverses inversion inversions inversive invert invertase invertases invertebrate invertebrates inverted inverter inverters invertible inverting inverts invest investable invested investigable investigate investigated investigates investigating investigation investigational investigations investigative investigator investigatorial investigators investigatory investing investiture investitures investment investments investor investors invests inveteracy inveterate inveterately inveterateness inviability inviable invidia invidious invidiously invidiousness invigilate invigilated invigilates invigilating invigilation invigilations invigilator invigilators invigorant invigorants invigorate invigorated invigorates invigorating invigoratingly invigoration invigorations invigorative invigorator invigorators invincibility invincible invincibleness invincibly inviolability inviolable inviolableness inviolably inviolacy inviolate inviolately inviolateness inviscid invisibility invisible invisibleness invisibles invisibly invita invitation invitational invitationals invitations invitatories invitatory invite invited invitee invitees inviter inviters invites inviting invitingly invocate invocated invocates invocating invocation invocational invocations invocatory invoice invoiced invoices invoicing invoke invoked invoker invokers invokes invoking involucel involucels involucra involucral involucrate involucre involucres involucrum involuntarily involuntariness involuntary involute involuted involutely involutes involuting involution involutional involutions involve involved involvedly involvement involvements involver involvers involves involving invulnerability invulnerable invulnerableness invulnerably inward inwardly inwardness inwards inweave inweaved inweaves inweaving inwind inwinding inwinds inwound inwove inwoven inwrap inwrapped inwrapping inwraps inwreathe inwreathed inwreathes inwreathing inwrought io iodate iodated iodates iodating iodation iodations iodic iodide iodides iodinate iodinated iodinates iodinating iodination iodinations iodine iodization iodizations iodize iodized iodizes iodizing iodoform iodoforms iodophor iodophors iodopsin iodopsins ion iona ionia ionian ionians ionic ionicity ionics ionium ionizable ionization ionize ionized ionizer ionizers ionizes ionizing ionone ionones ionophore ionophores ionosphere ionospheric ionospherically ions iontophoreses iontophoresis iontophoretic iontophoretically iota iotacism iowa iowan iowans iowas ipecac ipecacuanha iphigenia iproniazid iproniazids ipse ipsilateral ipsilaterally ipsissima ipso ipsos ipsum iran iranian iranians iraq iraqi iraqis irascibility irascible irascibleness irascibly irate irately irateness ire ireful irefully ireland irelands irenic irenical irenically ireton iridaceous iridectomies iridectomy irides iridescence iridescent iridescently iridic iridium iridologist iridologists iridology iridosmine iridosmines iris irises irish irishism irishisms irishman irishmen irishness irishries irishry irishwoman irishwomen iritic iritis irk irked irking irks irksome irksomely irksomeness irkutsk iroko irokos iron ironbark ironbarks ironbound ironclad ironclads irondequoit ironed ironer ironers ironfisted ironhanded ironhandedness ironhearted ironic ironical ironically ironicalness ironies ironing ironings ironist ironists ironize ironized ironizes ironizing ironmaster ironmasters ironmonger ironmongeries ironmongers ironmongery ironness irons ironside ironsides ironsmith ironsmiths ironstone ironstones ironware ironweed ironweeds ironwood ironwoods ironwork ironworker ironworkers ironworks irony iroquoian iroquoians iroquois irradiance irradiances irradiancy irradiant irradiate irradiated irradiates irradiating irradiation irradiations irradiative irradiator irradiators irradicable irradicably irrational irrationalism irrationalist irrationalistic irrationalists irrationalities irrationality irrationalize irrationalized irrationalizes irrationalizing irrationally irrationalness irrawaddy irreal irreality irreclaimability irreclaimable irreclaimableness irreclaimably irreconcilability irreconcilable irreconcilableness irreconcilables irreconcilably irrecoverable irrecoverableness irrecoverably irrecusable irrecusably irredeemable irredeemably irredenta irredentism irredentist irredentists irreducibility irreducible irreducibleness irreducibly irreflexive irreformability irreformable irrefragability irrefragable irrefragably irrefrangible irrefrangibly irrefutability irrefutable irrefutably irregardless irregular irregularities irregularity irregularly irregulars irrelative irrelatively irrelevance irrelevancies irrelevancy irrelevant irrelevantly irreligion irreligionist irreligionists irreligions irreligious irreligiously irreligiousness irremeable irremediable irremediableness irremediably irremissibility irremissible irremissibly irremovability irremovable irremovably irreparability irreparable irreparableness irreparably irrepealability irrepealable irreplaceability irreplaceable irreplaceableness irreplaceably irrepressibility irrepressible irrepressibleness irrepressibly irreproachability irreproachable irreproachableness irreproachably irreproducibility irreproducible irresistibility irresistible irresistibleness irresistibly irresoluble irresolute irresolutely irresoluteness irresolution irresolvable irrespective irrespectively irrespirable irresponsibility irresponsible irresponsibleness irresponsibles irresponsibly irresponsive irresponsively irresponsiveness irretrievability irretrievable irretrievableness irretrievably irreverence irreverences irreverent irreverently irreversibility irreversible irreversibleness irreversibly irrevocability irrevocable irrevocableness irrevocably irridenta irrigable irrigate irrigated irrigates irrigating irrigation irrigational irrigations irrigator irrigators irritabilities irritability irritable irritableness irritably irritant irritants irritate irritated irritatedly irritates irritating irritatingly irritation irritations irritative irritator irritators irrotational irrupt irrupted irrupting irruption irruptions irruptive irruptively irrupts irving iráklion is isaac isabella isaiah isaias isallobar isallobaric isallobars iscariot ischaemia ischemia ischemic ischia ischial ischium isentropic isentropically iseult isfahan ishmael ishmaelite ishmaelites ishmaelitish ishmaelitism ishmaels ishtar isinglass isis iskenderun islam islamabad islamic islamics islamism islamist islamists islamization islamize islamized islamizes islamizing island islanded islander islanders islanding islands islay isle isled isles islet islets isling ism ismaili ismailian ismailians ismailis ismene isms isn isn't isoagglutination isoagglutinations isoagglutinin isoagglutinins isoagglutinogen isoagglutinogens isoalloxazine isoantibodies isoantibody isoantigen isoantigenic isoantigenicity isoantigens isobar isobaric isobars isobutane isobutanes isobutylene isobutylenes isocaloric isocarboxazid isocarboxazids isochromatic isochromosome isochromosomes isochron isochronal isochronally isochrone isochrones isochronism isochronize isochronized isochronizes isochronizing isochronous isochronously isochrons isochroous isocitric isoclinal isoclinally isoclinals isoclinic isocrates isocyanate isocyanates isocyclic isodiametric isodimorphism isodose isodynamic isoelectric isoelectronic isoelectronically isoenzymatic isoenzyme isoenzymes isoenzymic isogamete isogametes isogametic isogamies isogamous isogamy isogeneic isogenic isogenous isogeny isogloss isoglossal isoglosses isoglossic isogon isogonal isogonic isogons isogony isograft isografts isogram isograms isohel isohels isohyet isohyetal isohyets isokinetic isolable isolatable isolate isolated isolates isolating isolation isolationism isolationist isolationistic isolationists isolations isolator isolators isolde isolecithal isoleucine isoleucines isoline isolines isomagnetic isomer isomerase isomerases isomeric isomerism isomerisms isomerization isomerizations isomerize isomerized isomerizes isomerizing isomerous isomers isometric isometrical isometrically isometrics isometropia isometropias isometry isomorph isomorphic isomorphically isomorphism isomorphous isomorphs isoniazid isoniazids isooctane isopach isophotal isophote isophotes isopiestic isopiestics isopleth isoplethic isopleths isopod isopods isoprenaline isoprenalines isoprene isoprenoid isopropyl isoproterenol isopycnic isosceles isoseismal isoseismic isosmotic isosmotically isospin isospins isostasy isostatic isostatically isotach isotactic isotherm isothermal isothermally isothermals isotherms isotone isotones isotonic isotonically isotonicity isotope isotopes isotopic isotopically isotretinoin isotretinoins isotropic isotropism isotropy isozyme isozymes isozymic ispahan israel israeli israelis israelite israelites israelitic issachar issei isseis issuable issuably issuance issuant issue issued issueless issuer issuers issues issuing istanbul isthmi isthmian isthmic isthmus isthmuses istle istles istria istrian istrians it it'd it'll it's itacolumite itacolumites itaconic italian italianate italianism italianisms italianization italianizations italianize italianized italianizes italianizing italians italic italicism italicisms italicization italicizations italicize italicized italicizes italicizing italics italophile italophiles italophilia italophobe italophobes italophobia italy itasca itch itched itches itchier itchiest itchiness itching itchy item itemed iteming itemization itemizations itemize itemized itemizer itemizers itemizes itemizing items iterance iterances iterant iterate iterated iterates iterating iteration iterations iterative iteratively ithaca ithaka ithyphallic itháki itineracy itinerancies itinerancy itinerant itinerantly itinerants itineraries itinerary itinerate itinerated itinerates itinerating itineration itinerations its itself itsukushima itsy itty ituraea ituraean ituraeans ivanhoe ivermectin ivermectins ivied ivies iviza ivories ivory ivorybill ivorybills ivy iwis ixion ixodid ixtle ixtles iyar iyyar izalco izar izars izzard j jab jabbed jabber jabbered jabberer jabberers jabbering jabbers jabberwocky jabbing jabiru jabirus jaborandi jaborandis jabot jaboticaba jabots jabs jacal jacales jacals jacamar jacamars jacana jacanas jacaranda jacarandas jacinth jacinths jacinto jack jackal jackals jackanapes jackanapeses jackass jackassery jackasses jackboot jackbooted jackboots jackdaw jackdaws jacked jacker jackers jacket jacketed jacketing jacketless jackets jackfruit jackfruits jackhammer jackhammered jackhammering jackhammers jacking jackknife jackknifed jackknifes jackknifing jackknives jackleg jacklegs jacklight jacklighted jacklighting jacklights jackplane jackplanes jackpot jackpots jackrabbit jackrabbited jackrabbiting jackrabbits jacks jackscrew jackscrews jackshaft jackshafts jacksmelt jacksnipe jacksnipes jackson jacksonian jacksonianism jacksonians jackstay jackstays jackstone jackstones jackstraw jackstraws jacob jacobean jacobeans jacobian jacobians jacobin jacobinic jacobinical jacobinism jacobinize jacobinized jacobinizes jacobinizing jacobins jacobite jacobites jacobitical jacobitism jacobus jaconet jaconets jacquard jacquards jacquerie jacqueries jactitation jactitations jacuzzi jade jaded jadedly jadedness jadeite jadeites jades jadestone jadestones jading jaditic jaeger jaegers jaffa jaffas jag jagatai jagged jaggedly jaggedness jagger jaggeries jaggers jaggery jaggier jaggiest jagging jaggy jagless jags jaguar jaguarondi jaguarondis jaguars jaguarundi jaguarundis jah jahveh jahweh jai jail jailbait jailbird jailbirds jailbreak jailbreaks jailed jailer jailers jailhouse jailhouses jailing jailor jailors jails jain jaina jainas jainism jainisms jains jaipur jakarta jake jakes jakob jalalabad jalap jalapeño jalapeños jalaps jalopies jalopy jalousie jalousies jam jamaica jamaican jamaicans jamb jambalaya jambe jambeau jambeaux jambes jamboree jamborees jambs james jamesian jammable jammed jammer jammers jammies jamming jammu jammy jams jamshid jamshyd jane janeiro janeite janeites jangle jangled jangler janglers jangles jangling jangly janissaries janissary janitor janitorial janitors janizaries janizary jansenism jansenist jansenistic jansenists januaries january januarys janus jap japan japanese japanization japanize japanized japanizes japanizing japanned japanner japanners japanning japans jape japed japer japers japery japes japheth japhetic japing japlish japonaiserie japonaiseries japonica japonicas japonism japonisms japs japurá jar jardiniere jardinieres jardinière jardinières jarful jarfuls jargon jargoned jargoneer jargoneers jargoning jargonish jargonist jargonistic jargonists jargonize jargonized jargonizes jargonizing jargons jargoon jargoons jarhead jarheads jarl jarls jarlsberg jarrah jarrahs jarred jarring jarringly jars jasmine jasmines jason jasper jaspers jasperware jaspery jassid jassids jat jato jatos jats jaunce jaunced jaunces jauncing jaundice jaundiced jaundices jaundicing jaunt jaunted jauntier jauntiest jauntily jauntiness jaunting jaunts jaunty java javanese javarí javas javelin javelina javelinas javelins javelle jaw jawbone jawboned jawboner jawboners jawbones jawboning jawbreaker jawbreakers jawbreaking jawbreakingly jawed jawing jawless jawline jawlines jaws jay jaybird jaybirds jaycee jaycees jaygee jaygees jayhawker jayhawkers jays jayvee jayvees jaywalk jaywalked jaywalker jaywalkers jaywalking jaywalks jazz jazzed jazzer jazzers jazzes jazzier jazziest jazzily jazziness jazzing jazzish jazzlike jazzman jazzmen jazzy jaçana jaçanas je jealous jealousies jealously jealousness jealousy jean jeaned jeans jeddah jee jeebies jeep jeepers jeepney jeepneys jeeps jeer jeered jeerer jeerers jeering jeeringly jeers jeez jefe jefes jefferson jeffersonian jeffersonianism jeffersonians jeffrey jehad jehads jehoshaphat jehovah jehu jehus jejuna jejunal jejune jejunely jejuneness jejunum jekyll jell jellaba jellabas jelled jellicoe jellied jellies jellified jellifies jellify jellifying jelling jells jelly jellybean jellybeans jellyfish jellyfishes jellying jellylike jellyroll jellyrolls jelutong jemmied jemmies jemmy jemmying jena jenner jennet jennets jennies jenny jeon jeopard jeoparded jeopardies jeoparding jeopardize jeopardized jeopardizes jeopardizing jeopardous jeopards jeopardy jequirity jequitinhonha jerboa jerboas jeremiad jeremiads jeremiah jeremiahs jeremias jerez jericho jerk jerked jerker jerkers jerkier jerkiest jerkily jerkin jerkiness jerking jerkingly jerkins jerks jerkwater jerky jeroboam jeroboams jerome jerrican jerricans jerries jerry jerrybuild jerrybuilder jerrybuilders jerrybuilding jerrybuilds jerrybuilt jersey jerseys jerusalem jess jessamine jessamines jesse jessed jesses jessing jest jested jester jesters jesting jestingly jests jesuit jesuitic jesuitical jesuitically jesuitism jesuitry jesuits jesus jet jetavator jetavators jetbead jetbeads jetfighter jetfighters jetfoil jetfoils jetful jetlike jetliner jetliners jetpack jetpacks jetport jetports jets jetsam jetted jettied jetties jettiness jetting jettison jettisonable jettisoned jettisoning jettisons jetty jettying jetway jeté jeu jeunesse jeux jew jewel jeweled jeweler jewelers jewelfish jewelfishes jeweling jewelled jeweller jewellers jewellery jewellike jewelling jewelry jewels jewelweed jewelweeds jewess jewesses jewfish jewfishes jewish jewishly jewishness jewries jewry jews jezebel jezebels jiao jib jibaro jibaros jibbed jibber jibbers jibbing jibboom jibbooms jibe jibed jibes jibing jibs jicama jicamas jicarilla jicarillas jiff jiffies jiffs jiffy jig jigged jigger jiggers jiggery jigging jiggle jiggled jiggles jiggling jiggly jigs jigsaw jigsaws jihad jihads jill jillion jillionaire jillionaires jillions jillionth jillionths jills jilt jilted jilter jilters jilting jilts jim jimjams jimmied jimmies jimmy jimmying jimsonweed jimsonweeds jingle jingled jingler jinglers jingles jingling jingly jingo jingoes jingoish jingoism jingoist jingoistic jingoistically jingoists jink jinked jinking jinks jinmen jinn jinnee jinni jinns jinricksha jinrickshas jinrikisha jinrikishas jinriksha jinrikshas jinx jinxed jinxes jinxing jipijapa jipijapas jitney jitneys jitter jitterbug jitterbugged jitterbugging jitterbugs jittered jitterier jitteriest jitteriness jittering jitters jittery jiujitsu jiujutsu jivaro jivaros jive jived jiver jivers jives jivey jiving jivy jo joan job jobbed jobber jobbers jobbery jobbing jobholder jobholders jobless joblessness jobs jocasta jock jockey jockeyed jockeying jockeys jocks jockstrap jockstraps jocose jocosely jocoseness jocosity jocular jocularity jocularly jocund jocundity jocundly jodhpur jodhpurs jodrell joe joel joes joey joeys jog jogged jogger joggers jogging joggle joggled joggles joggling jogjakarta jogs johannesburg john johnboat johnboats johnnies johnny johnnycake johnnycakes johns johnson johnsonian johnsonians johnstone johnstown joie join joinder joinders joined joiner joineries joiners joinery joining joins joint jointed jointer jointers jointing jointly joints jointure jointures jointworm jointworms joist joisted joisting joists jojoba jojobas joke joked joker jokers jokes jokester jokesters jokey jokier jokiest jokily jokiness joking jokingly joky jolie jollied jollier jollies jolliest jollification jollifications jollily jolliness jollities jollity jolly jollyboat jollyboats jollying jolt jolted jolter jolters joltily joltiness jolting jolts jolty jomada jonah jonahs jonathan jones jongleur jongleurs jonnycake jonnycakes jonquil jonquils jonson jooal jordan jordanian jordanians jorum jorums joseph josephs josephus josh joshed josher joshers joshes joshing joshingly joshua josiah joss josses jostle jostled jostler jostlers jostles jostling josé jot jots jotted jotting jottings joual joule joules jounce jounced jounces jouncing jour journal journalese journalism journalist journalistic journalistically journalists journalize journalized journalizer journalizers journalizes journalizing journals journey journeyed journeyer journeyers journeying journeyman journeymen journeys journeywork joust jousted jouster jousters jousting jousts jove jovial joviality jovially jovian jowett jowl jowlier jowliest jowliness jowls jowly joy joyance joyce joyed joyful joyfully joyfulness joying joyless joylessly joylessness joyous joyously joyousness joypop joypopped joypopper joypoppers joypopping joypops joyride joyrider joyriders joyrides joyriding joys joystick joysticks joão juan juanism juans juba jubal jubas jubilance jubilant jubilantly jubilarian jubilarians jubilate jubilated jubilates jubilating jubilation jubilee jubilees judaea judah judaic judaica judaical judaically judaism judaist judaistic judaists judaization judaizations judaize judaized judaizer judaizers judaizes judaizing judas judases judder juddered juddering judders jude judea judean judeans judeo judge judged judgement judgements judger judgers judges judgeship judgeships judging judgmatic judgmatical judgmatically judgment judgmental judgmentally judgments judicable judicata judicator judicatories judicators judicatory judicature judicatures judice judicial judicially judiciaries judiciary judicious judiciously judiciousness judith judo judoist judoists judos judy jug juga jugate jugful jugfuls jugged juggernaut juggernauts jugging juggle juggled juggler juggleries jugglers jugglery juggles juggling jugoslav jugoslavs jugs jugular jugulars jugulate jugulated jugulates jugulating jugum jugums juice juiced juicehead juiceheads juiceless juicer juicers juices juicier juiciest juicily juiciness juicing juicy jujitsu juju jujube jujubes jujuism jujus jujutsu juke jukebox jukeboxes juked jukes juking julep juleps julian julienne julienned juliet juliett julius july julys jumada jumble jumbled jumbles jumbling jumbo jumbos jumbuck jumbucks jump jumped jumper jumpers jumpier jumpiest jumpily jumpiness jumping jumpmaster jumpmasters jumps jumpsuit jumpsuits jumpy junco juncoes juncos junction junctional junctions junctural juncture junctures june juneau juneberries juneberry junes jung jungfrau jungian jungians jungle jungled junglelike jungles jungly junior juniorate juniors juniper junipers junius junk junked junker junkerdom junkerism junkers junket junketed junketeer junketeered junketeering junketeers junketer junketers junketing junkets junkie junkier junkies junkiest junking junkman junkmen junks junky junkyard junkyards juno junoesque junta juntas junto juntos jupiter jura jural jurally jurassic jurat jurats jure jureipswich jurel jurels juridic juridical juridically juried juries juris jurisconsult jurisconsults jurisdiction jurisdictional jurisdictionally jurisdictions jurisprudence jurisprudent jurisprudential jurisprudentially jurisprudents jurist juristic juristical juristically jurists juror jurors jury jurying juryman jurymen jurywoman jurywomen jus jussive jussives just juste justed justes justice justices justiciability justiciable justiciar justiciaries justiciars justiciary justifiability justifiable justifiableness justifiably justification justifications justificative justificatory justified justifier justifiers justifies justify justifying justing justinian justly justness justs jut jute jutish jutland juts jutted juttied jutties jutting jutty juttying juvenal juvenescence juvenescent juvenile juvenilely juvenileness juveniles juvenilia juvenilities juvenility juxtapose juxtaposed juxtaposes juxtaposing juxtaposition juxtapositional juxtapositions juárez jyväskylä k kaaba kab kabala kabalas kabbala kabbalah kabbalas kabob kabobs kabs kabuki kabukis kabul kabyle kabyles kachina kachinas kaddish kaffeeklatsch kaffeeklatsches kaffir kaffirs kaffiyeh kaffiyehs kafir kafiri kafirs kafka kafkaesque kaftan kaftans kagoshima kahn kahoolawe kahuna kaiak kaiaked kaiaker kaiakers kaiaking kaiaks kailas kailyard kainit kainite kainites kainits kaiser kaiserdom kaiserdoms kaiserin kaiserins kaiserism kaisers kaka kakapo kakapos kakas kakemono kakemonos kaki kakiemon kakis kakistocracies kakistocracy kalahari kalamazoo kalanchoe kalashnikov kalashnikovs kale kaleidoscope kaleidoscopes kaleidoscopic kaleidoscopical kaleidoscopically kalends kalgoorlie kalimantan kalimba kalimbas kaliningrad kallidin kallidins kallikrein kallikreins kalmar kalmuck kalmucks kalmuk kalmuks kalmyk kalmyks kalpac kalpacs kalsomine kalsomines kama kamaaina kamala kamalas kamasutra kamchatka kame kamehameha kames kamet kamikaze kamikazes kampala kampong kampongs kampuchea kampuchean kampucheans kana kanak kanaka kanakas kanaks kanamycin kanamycins kanarese kanas kanban kanchenjunga kandy kangaroo kangaroos kangchenjunga kaniapiskau kanji kanjis kankakee kannada kano kansa kansan kansans kansas kansu kant kantele kanteles kantian kantians kanuri kanuris kanzu kanzus kaolin kaoline kaolines kaolinite kaolinites kaolinitic kaolinize kaolinized kaolinizes kaolinizing kaolins kaon kaons kapellmeister kaph kapok kaposi kaposi's kappa kaput kaputt kara karabiner karabiners karachi karaism karaite karaites karakoram karakorum karakul karakuls karaoke karaokes karat karate karateist karateists karats karaya karelia karelian karelians karen karenina karens kari kariba karma karmic karnak karnataka karok karoks karoo karoos kaross karroo karroos karst karstic karsts kart karting kartings karts karyogamies karyogamy karyokinesis karyokinetic karyologic karyological karyology karyolymph karyolymphs karyoplasm karyoplasms karyosome karyosomes karyotype karyotyped karyotypes karyotypic karyotypical karyotypically karyotyping kasbah kasha kashan kashans kasher kashered kashering kashers kashmir kashmiri kashmiris kashrut kashruth kashubian kaskaskia kaskaskias kata katabatic katahdin katakana katakanas katanga katangese katas katchina katcina katharevusa katharsis kathiawar kathmandu katmai katmandu kattegat katydid katydids katzenjammer katzenjammers kauai kauri kauris kava kavas kaw kawartha kaws kay kayak kayaked kayaker kayakers kayaking kayaks kaybecker kaybeckers kayo kayoed kayoing kayos kazak kazakh kazakhs kazakhstan kazaks kazbek kazoo kazoos kea kealakekua kean keas keats keatsian kebab kebabs kebbock kebbocks kebbuck kebbucks keble kebob kebobs kechua kechuas ked kedge kedged kedgeree kedges kedging keek keeked keeking keeks keel keelboat keelboats keeled keelhaul keelhauled keelhauling keelhauls keeling keelless keels keelson keelsons keen keened keener keeners keenest keening keenly keenness keens keep keeper keepers keeping keeps keepsake keepsakes keeshond keeshonden keeshonds keester keesters keewatin kef kefallinía keffiyeh kefir kefirs keflavík kefs keg kegged kegging kegler keglers kegling kegs keister keisters kelim kelims kelly keloid keloidal keloids kelp kelpie kelpies kelps kelpy kelson kelsons kelt keltic kelts kelvin kelvins kemijoki kemp kempis kempt ken kenaf kenai kendal kendo kendos kenilworth kennebec kenned kennedy kennel kenneled kenneling kennelled kennelling kennels kenning kennings keno kenos kenosis kenotic kens kenspeckle kent kentish kentledge kentledges kentuckian kentuckians kentucky kenya kenyan kenyans keogh kephalin kephalins kepi kepis kepler kept kerala keratectomies keratectomy keratin keratinization keratinizations keratinize keratinized keratinizes keratinizing keratinophilic keratinous keratitides keratitis keratoconjunctivitis keratoplasties keratoplasty keratoses keratosis keratotic keratotomies keratotomy kerb kerbs kerch kerchief kerchiefed kerchiefs kerchieves keresan keresans kerf kerfs kerfuffle kerfuffles kerguelen kerman kermans kermes kermess kermesse kermesses kermis kermises kern kerne kerned kernel kerneled kernels kernes kerning kernite kernites kerns kerogen kerogens kerosene kerosenes kerosine kerosines kerria kerrias kerries kerry kersey kerseymere kerseymeres kerseys kerygma kerygmas kerygmatic kestrel kestrels ketch ketches ketchup ketene ketenes ketoacidosis ketogenesis ketogenic ketoglutaric ketone ketones ketonic ketose ketoses ketosis ketosteroid ketosteroids ketotic kettle kettledrum kettledrums kettles kevel kevels keweenaw kewpie kewpies key keyboard keyboarded keyboarder keyboarders keyboarding keyboardist keyboardists keyboards keybutton keybuttons keycard keycards keyed keyhole keyholes keying keyless keynes keynesian keynesianism keynesians keynote keynoted keynoter keynoters keynotes keynoting keypad keypads keypunch keypunched keypuncher keypunchers keypunches keypunching keys keystone keystones keystroke keystroked keystrokes keystroking keyway keyways keyword keywords kg khaddar khaddars khadi khaki khakis khalif khalifs khalkha khalkidhikí khamsin khamsins khan khanate khanates khans khapra khartoum khartum khat khatanga khats khedival khedive khedives khedivial khi khmer khmerian khmers khoikhoi khoikhoin khoikhoins khoikhois khoisan khoisans khoum khowar khwarizmi khyber khíos kiang kiangs kiangsi kiangsu kiaugh kiaughs kibbe kibbi kibbitz kibbitzer kibbitzers kibble kibbled kibbles kibbling kibbutz kibbutzim kibbutznik kibbutzniks kibe kibei kibeis kibes kibitz kibitzed kibitzer kibitzers kibitzes kibitzing kiblah kiblahs kibosh kiboshed kiboshes kiboshing kick kickable kickapoo kickapoos kickback kickbacks kickboard kickboards kickboxer kickboxers kickboxing kicked kicker kickers kickier kickiest kicking kickoff kickoffs kicks kickshaw kickshaws kickstand kickstands kickup kickups kicky kid kidcom kidcoms kidded kidder kidderminster kidderminsters kidders kiddie kiddies kidding kiddingly kiddish kiddo kiddos kiddush kiddushes kiddy kideo kideos kidnap kidnaped kidnapee kidnapees kidnaper kidnapers kidnaping kidnapped kidnappee kidnappees kidnapper kidnappers kidnapping kidnappings kidnaps kidney kidneys kids kidskin kidvid kidvids kielbasa kierkegaard kieselguhr kieselguhrs kieserite kieserites kiev kif kifs kigali kike kikes kikládhes kikongo kikongos kikuyu kikuyus kilauea kilderkin kilderkins kilim kilimanjaro kilims kill killable killarney killdeer killdeers killed killer killers killersat killersats killick killicks killie killies killifish killifishes killing killingly killings killjoy killjoys killock killocks kills kiln kilned kilning kilns kilo kiloampere kiloamperes kilobar kilobars kilobase kilobases kilobecquerel kilobecquerels kilobit kilobits kilobyte kilobytes kilocalorie kilocalories kilocandela kilocandelas kilocoulomb kilocoulombs kilocurie kilocuries kilocycle kilocycles kilofarad kilofarads kilogauss kilogausses kilogram kilograms kilohenries kilohenry kilohenrys kilohertz kilojoule kilojoules kilokelvin kilokelvins kiloliter kiloliters kilolumen kilolumens kilolux kilomegacycle kilomegacycles kilometer kilometers kilometric kilomole kilomoles kilonewton kilonewtons kilooersted kilooersteds kiloohm kiloohms kiloparsec kiloparsecs kilopascal kilopascals kilorad kiloradian kiloradians kilorads kilos kilosecond kiloseconds kilosiemens kilosievert kilosieverts kilosteradian kilosteradians kilotesla kiloteslas kiloton kilotons kilovolt kilovolts kilowatt kilowatts kiloweber kilowebers kilt kilted kilter kiltie kilties kilting kilts kilty kimberley kimberlite kimberlites kimberlitic kimbundu kimbundus kimchee kimchees kimchi kimchis kimono kimonoed kimonos kin kina kinas kinase kinases kind kinder kindergarten kindergartener kindergarteners kindergartens kindergartner kindergartners kindersley kindest kindhearted kindheartedly kindheartedness kindle kindled kindler kindlers kindles kindless kindlessly kindlier kindliest kindliness kindling kindlings kindly kindness kindnesses kindred kindredness kinds kine kinema kinematic kinematical kinematically kinematics kinescope kinescoped kinescopes kinescoping kineses kinesic kinesics kinesiologist kinesiologists kinesiology kinesis kinestheses kinesthesia kinesthesias kinesthesis kinesthetic kinesthetically kinetic kinetically kineticism kineticist kineticists kinetics kinetin kinetins kinetochore kinetochores kinetoplast kinetoplasts kinetoscope kinetoscopes kinetosome kinetosomes kinfolk kinfolks king king's kingbird kingbirds kingbolt kingbolts kingcraft kingcrafts kingcup kingcups kingdom kingdoms kinged kingfish kingfisher kingfishers kingfishes kinging kinglet kinglets kinglier kingliest kingliness kingly kingmaker kingmakers kingmaking kingpin kingpins kings kingship kingships kingside kingsides kingsley kingstown kingwood kingwoods kinin kinins kink kinkajou kinkajous kinked kinkier kinkiest kinkily kinkiness kinking kinks kinky kinnikinnic kinnikinnick kinnikinnicks kinnikinnics kino kinos kinsfolk kinshasa kinship kinsman kinsmen kinswoman kinswomen kinyarwanda kioga kiosk kiosks kiowa kiowas kip kipling kipped kipper kippered kipperer kipperers kippering kippers kipping kippur kips kir kirche kirchhoff kirghiz kirghizes kirghizia kirghizstan kirgiz kirgizes kirgizia kirgizstan kiri kiribati kirigami kirin kirk kirkpatrick kirks kirlian kirman kirmans kirmess kirmesses kirs kirsch kirschwasser kirschwassers kirtland kirtle kirtles kirundi kirundis kishka kishkas kishke kishkes kiska kislev kismet kiss kissable kissed kisser kissers kisses kissimmee kissing kist kists kiswahili kit kitchen kitchenette kitchenettes kitchens kitchenware kite kited kitelike kites kith kithara kitharas kithe kithed kithing kitikmeot kiting kits kitsch kitschified kitschifies kitschifing kitschify kitschy kitted kitten kittened kittening kittenish kittenishly kittenishness kittens kitties kitting kittiwake kittiwakes kittle kittled kittles kittling kitts kitty kiva kivas kiwanian kiwanians kiwi kiwifruit kiwis klagenfurt klamath klamaths klan klanism klansman klansmen klatch klatches klatsch klavern klaverns klaxon klaxons klebsiella klebsiellas klee kleenex kleenexes kleig klein klemperer klepht klephtic klephts kleptocracies kleptocracy kleptocratic kleptomania kleptomaniac kleptomaniacal kleptomaniacs klezmer klezmorim klieg kliegs klinefelter klingon klingons klipspringer klipspringers klister klisters klondike kloof kloofs klosters kludge kludged kludges kludging kludgy kluge kluged kluges kluging klugy klutz klutzes klutziness klutzy klux kluxer kluxism klystron klystrons km knack knacker knackered knackers knackery knacks knackwurst knackwursts knap knapped knapper knappers knapping knaps knapsack knapsacked knapsacks knapweed knapweeds knar knars knaur knaurs knave knaveries knavery knaves knavish knavishly knavishness knawe knawel knawels knawes knead kneadable kneaded kneader kneaders kneading kneads knee kneeboard kneeboarded kneeboarding kneeboards kneecap kneecapped kneecapping kneecaps kneed kneehole kneeholes kneeing kneel kneeled kneeler kneelers kneeling kneels kneepad kneepads kneepan kneepans knees kneesock kneesocks knell knelled knelling knells knelt knesset knessets knew knickerbocker knickerbockers knickers knickknack knickknacks knife knifed knifelike knifeman knifemen knifepoint knifepoints knifer knifers knifes knifing knifings knight knighted knighthood knighting knightliness knightly knights knish knishes knit knits knitted knitter knitters knitting knitwear knives knob knobbed knobbier knobbiest knobblier knobbliest knobbly knobby knobkerrie knobkerries knobs knock knockabout knockabouts knockdown knockdowns knocked knocker knockers knocking knockings knockoff knockoffs knockout knockouts knocks knockwurst knockwursts knoll knolled knolling knolls knop knopped knops knossos knot knotgrass knotgrasses knothole knotholes knots knotted knotter knotters knottier knottiest knottiness knotting knotty knotweed knotweeds knout knouted knouting knouts know knowable knower knowers knowing knowingly knowingness knowledge knowledgeability knowledgeable knowledgeableness knowledgeably known knows knox knoxville knubby knuckle knuckleball knuckleballer knuckleballers knuckleballs knucklebone knucklebones knuckled knucklehead knuckleheaded knuckleheads knuckler knucklers knuckles knuckling knur knurl knurled knurling knurls knurly knurs ko koa koala koalas koan koans koas kob kobo kobold kobolds kobs koch kodak kodiak kohl kohlrabi kohlrabies koi koine koines kokanee kokanees kola kolache kolacky kolas kolinskies kolinsky kolkhoz kolkhozes kolkhoznik kolkhozniki kolkhozniks kolkhozy kolo kolos kolyma komandorski komati komatik komatiks kombu kombus komodo komondor komondorok komondors komsomol kong kongo kongos konkani koodoo koodoos kook kookaburra kookaburras kookie kookier kookiest kookiness kooks kooky kootchy kootenay kopeck kopecks kopek kopeks koph kopje kopjes koppie koppies kor korai koran koranic korat korats kordofanian kordofanians kore korea korean koreans kors korsakoff korsakov korun koruna korunas koruny kos kosciusko kosher koshered koshering koshers kosovo koto kotos koumiss koumisses kouprey kouroi kouros kowloon kowtow kowtowed kowtowing kowtows kra kraal kraals kraft krait kraits krakatau krakatoa kraken krakens kraków krater kraters kraut krauts krebs kremlin kremlinological kremlinologist kremlinologists kremlinology kreplach kreutzer kreutzers kreuzer kreuzers krewe krewes kriemhild kriemhilde krill krimmer krimmers kringle krio kris krises krishna krishnaism krishnas kriss kroenecker krona krone kronecker kronen kroner kronor kronos kronur krugerrand krugerrands krumhorn krumhorns krummholz krummhorn krummhorns krummkake krummkakes krypton kshatriya kshatriyas ku kuala kublai kuchean kuchen kuchens kudo kudos kudu kudus kudzu kufic kugel kugels kulak kulaks kultur kulturkampf kulturkampfs kulturs kumiss kumisses kumquat kumquats kundalini kung kunlun kunming kunzite kunzites kuoyu kuoyus kurchatovium kurd kurdish kurdistan kurds kurgan kurgans kuril kurile kurilian kurilians kurland kuroshio kurrajong kurrajongs kurtoses kurtosis kuru kurus kush kuskokwim kutch kutenai kutenais kuwait kuwaiti kuwaitis kvass kvasses kvetch kvetched kvetches kvetching kvetchy kwa kwacha kwachas kwajalein kwakiutl kwakiutls kwangtung kwantung kwanza kwanzaa kwanzas kwas kwashiorkor kweichow kyack kyacks kyanite kyanites kyanize kyanized kyanizes kyanizing kyat kyats kybosh kylikes kylix kymogram kymograms kymograph kymographic kymographs kymography kymric kyoga kyoto kyphosis kyphotic kyrgyz kyrgyzstan kyrie kyries kyte kythe kyushu kárpathos kérkira kíthira kórinthos köln königsberg küche kümmel kümmelweck l l'oeil l'oeils l'évêque la laager laagered laagering laagers laari lab laban labanotation labanotations labara labarum labdanum labdanums label labelable labeled labeler labelers labeling labella labellate labelled labeller labellers labelling labellum labels labia labial labialization labializations labialize labialized labializes labializing labially labials labiate labiates labile lability labiodental labiodentals labionasal labionasals labiovelar labiovelars labium lablab lablabs labor laboratories laboratory labored laborer laborers laboring laborious laboriously laboriousness laborite laborites labors laborsaving labour labourite labourites labours labra labrador labradorean labradoreans labradorian labradorians labradorite labradorites labradors labret labrets labrum labs labuan laburnum laburnums labyrinth labyrinthian labyrinthine labyrinthodont labyrinthodonts labyrinths lac laccadive laccolith laccolithic laccoliths lace laced lacedaemon lacedaemonian laceless lacelike lacer lacerate lacerated lacerates lacerating laceration lacerations lacerative lacers lacerta lacertilian laces lacewing lacewings lacework lacey laches lachesis lachrymal lachrymation lachrymations lachrymator lachrymators lachrymatory lachrymose lachrymosely lachrymosity lacier laciest laciness lacing lacings lacinia lacinias laciniate laciniation laciniations lack lackadaisical lackadaisically lackadaisicalness lackaday lacked lackey lackeyed lackeying lackeys lacking lackluster lacks laconia laconic laconically laconism laconisms lacquer lacquered lacquerer lacquerers lacquering lacquers lacquerware lacquerwork lacrimal lacrimation lacrimations lacrimator lacrimators lacrosse lacs lactalbumin lactalbumins lactamase lactase lactate lactated lactates lactating lactation lactational lactations lacteal lacteally lactescence lactescent lactic lactiferous lactiferousness lactobacilli lactobacillus lactoflavin lactoflavins lactogenic lactoglobulin lactoglobulins lactometer lactometers lactone lactones lactonic lactoprotein lactoproteins lactose lacuna lacunae lacunal lacunar lacunaria lacunars lacunas lacunate lacustrine lacy lad ladanum ladanums ladder laddered laddering ladderlike ladders laddie laddies lade laded laden ladened ladening ladens lades ladies ladin lading ladino ladinos ladins ladle ladled ladler ladlers ladles ladling ladoga lads lady ladybird ladybirds ladybug ladybugs ladyfinger ladyfingers ladyfish ladyfishes ladykin ladykins ladylike ladylikeness ladylove ladyloves ladysfinger ladysfingers ladyship ladyships ladysmith laertes laetare laetrile lafayette lag lagan lagans lagend lagends lager lagers laggard laggardly laggardness laggards lagged lagger laggers lagging laggings lagniappe lagniappes lagomorph lagomorphic lagomorphous lagomorphs lagoon lagoonal lagoons lagos lagrangian lagrangians lags lahar lahars lahnda lahontan lahore laic laical laically laicals laicism laicization laicizations laicize laicized laicizes laicizing laics laid laide lain lair laird lairdly lairds lairs laisser laissez lait laitance laity laius lake lakebed lakebeds laked lakefront lakefronts lakeland lakelike laker lakers lakes lakeshore lakeshores lakeside lakesides lakh laking lakota lakotas lakshadweep lakshmi laky lalapalooza lalapaloozas lallan lalland lallands lallans lallapalooza lallapaloozas lallation lallations lally lallygag lallygagged lallygagging lallygags lam lama lamaism lamaist lamaistic lamaists lamarck lamarckian lamarckianism lamarckians lamarckism lamas lamaseries lamasery lamaze lamb lambast lambaste lambasted lambastes lambasting lambasts lambda lambdoid lambed lambency lambent lambently lamber lambers lambert lamberts lambing lambkill lambkills lamblike lambrequin lambrequins lambrusco lambs lambskin lamby lame lamebrain lamebrained lamebrains lamed lamedh lamella lamellae lamellar lamellarly lamellas lamellate lamellated lamellately lamellation lamellations lamellibranch lamellibranchs lamellicorn lamellicorns lamelliform lamely lameness lament lamentable lamentableness lamentably lamentation lamentations lamented lamentedly lamenter lamenters lamenting laments lamer lames lamest lamia lamiae lamian lamians lamias lamina laminae laminal laminar laminaria laminarian laminarians laminarin laminarins laminas laminate laminated laminates laminating lamination laminations laminator laminators laminectomies laminectomy laming laminitis lamister lamisters lammas lammases lammastide lammed lammergeier lammergeiers lammergeyer lammergeyers lammermoor lamming lamp lampblack lampbrush lamper lampion lampions lamplight lamplighter lamplighters lampoon lampooned lampooner lampooners lampoonery lampooning lampoonist lampoonists lampoons lamppost lampposts lamprey lampreys lamprophyre lamprophyres lamps lampshade lampshades lampshell lampshells lampworking lampworkings lams lamster lamsters lamé lamés lanai lanais lanate lancashire lancaster lancasters lancastrian lancastrians lance lanced lancelet lancelets lancelot lanceolate lanceolately lancer lancers lances lancet lanceted lancets lancewood lancewoods lancinating lancing land landau landaulet landaulets landaus landed lander landers landes landfall landfalls landfill landfilled landfilling landfills landform landforms landgrab landgrabs landgrave landgraves landgraviate landgraviates landgravine landgravines landholder landholders landholding landholdings landing landings landladies landlady landless landlessness landline landlines landlocked landlord landlordism landlords landlubber landlubberliness landlubberly landlubbers landlubbing landmark landmarks landmass landmasses landmine landmines landowner landowners landownership landowning landrace landraces lands landscape landscaped landscaper landscapers landscapes landscaping landscapist landscapists landseer landside landsides landsleit landslide landslides landslip landslips landsmaal landsmal landsman landsmen landsmål landtag landtags landward landwards lane lanes laneway laneways lanfranc lang langbeinite langbeinites langerhans langlauf langlaufer langlaufers langlaufs langley langleys langobard langobardic langobards langostino langostinos langouste langoustes langoustine langoustines langrage langrages langsyne language languages langue languedoc langues languet languets languid languidly languidness languish languished languisher languishers languishes languishing languishingly languishment languishments languor languorous languorously languorousness langur langurs laniard laniards laniferous lank lanka lankan lankans lanker lankest lankier lankiest lankily lankiness lankly lankness lanky lanner lanneret lannerets lanners lanolin lanose lanosity lansing lantana lantanas lantern lanterns lanthanide lanthanum lanthorn lanthorns lanuginose lanuginous lanuginousness lanugo lanugos lanyard lanyards lanzarote lao laocoon laodicea laodicean laodiceans laomedon laos laotian laotians lap laparoscope laparoscopes laparoscopic laparoscopies laparoscopist laparoscopists laparoscopy laparotomies laparotomy lapboard lapboards lapdog lapdogs lapel lapeled lapelled lapels lapful lapfuls lapidarian lapidaries lapidary lapilli lapillus lapin lapis lapith lapiths laplace lapland laplander laplanders lapp lapped lapper lappers lappet lappets lapping lappish lapps laps lapsang lapse lapsed lapser lapsers lapses lapsing lapstrake lapstreak laptev laptop laptops laputa laputan laputans lapwing lapwings lar laramie larboard larboards larcener larceners larcenies larcenist larcenists larcenous larcenously larceny larch larches lard larded larder larders larding lardon lardons lardoon lardoons lards lardy laree larees lares large largehearted largeheartedness largely largemouth largeness larger largess largesse largesses largest larghetto larghettos largish largo largos lariat lariats lark larked larker larkers larkier larkiest larkiness larking larkish larks larkspur larkspurs larky larmoyante larnaca larrigan larrigans larrikin larrikins larrup larruped larruping larrups larum larums larva larvae larval larvas larvicidal larvicide larvicides laryngal laryngals laryngeal laryngeals laryngectomies laryngectomized laryngectomy larynges laryngitic laryngitis laryngologist laryngologists laryngology laryngopharynx laryngopharynxs laryngoscope laryngoscopes laryngoscopic laryngoscopical laryngoscopically laryngoscopy larynx larynxes lasagna lasagnas lasagne lascar lascars lascivious lasciviously lasciviousness lase lased laser laserlike lasers lases lash lashed lasher lashers lashes lashing lashings lashins lasing lass lassa lassen lasses lassie lassies lassitude lasso lassoed lassoer lassoers lassoes lassoing lassos last lasted laster lasters lastex lasting lastingly lastingness lastly lasts latakia latch latched latches latchet latchets latching latchkey latchkeys latchstring latchstrings late latecomer latecomers lated lateen lateener lateeners lateens latelies lately laten latencies latency latened lateness latening latens latensification latensifications latent latently later laterad lateral lateraled lateraling laterality lateralization lateralizations lateralize lateralized lateralizes lateralizing lateralled lateralling laterally laterals laterite laterites lateritic laterization laterizations latest latests latewood latewoods latex latexes lath lathe lathed lather lathered latherer latherers lathering lathers lathery lathes lathing lathings laths lathyrism lathyrisms lathyritic latices laticifer laticiferous laticifers latifundia latifundio latifundios latifundium latigo latigoes latigos latimer latin latina latinate latinism latinisms latinist latinists latinity latinization latinizations latinize latinized latinizer latinizers latinizes latinizing latino latinos latins latish latissimi latissimus latitude latitudes latitudinal latitudinally latitudinarian latitudinarianism latitudinarians latium latke latkes latosol latosolic latosols latrine latrines latten lattens latter latterly lattermost lattice latticed lattices latticework latticing latus latvia latvian latvians lauan lauans laud laudability laudable laudableness laudably laudanum laudation laudations laudative laudatory laude lauded lauder lauderdale lauders lauding lauds laugh laughable laughableness laughably laughed laugher laughers laughing laughingly laughingstock laughingstocks laughs laughter launce launces launch launched launcher launchers launches launching launchings launchpad launchpads launder laundered launderer launderers launderette launderettes laundering launderings launders laundress laundresses laundrette laundrettes laundries laundromat laundromats laundry laundryman laundrymen launfal laura lauras laurasia laureate laureates laureateship laureateships laureation laureations laurel laureled laureling laurelled laurelling laurels laurent laurentian lauric lauryl lausanne lautrec lava lavabo lavaboes lavage lavages lavalava lavalavas lavalier lavaliere lavalieres lavalike lavallière lavallières lavas lavation lavations lavatories lavatory lave laved lavender lavendered lavendering lavenders laver laverock laverocks lavers laves laving lavinia lavish lavished lavisher lavishers lavishes lavishing lavishly lavishness lavoisier lavrock lavrocks law lawbreaker lawbreakers lawbreaking lawed lawful lawfully lawfulness lawgiver lawgivers lawing lawless lawlessly lawlessness lawmaker lawmakers lawmaking lawman lawmen lawn lawnmower lawnmowers lawns lawny lawrence lawrencian lawrencium lawrentian laws lawsuit lawsuits lawyer lawyering lawyerings lawyerlike lawyerly lawyers lax laxation laxations laxative laxatives laxer laxest laxities laxity laxly laxness lay layabout layabouts layaway layaways layback laybacks layer layerage layerages layered layering layerings layers layette layettes laying layman laymen layoff layoffs layout layouts layover layovers laypeople layperson laypersons lays layup layups laywoman laywomen lazar lazaret lazarets lazarette lazarettes lazaretto lazarettos lazarist lazarists lazars lazarus laze lazed lazes lazied lazier lazies laziest lazily laziness lazing lazuli lazulite lazulites lazurite lazurites lazy lazybones lazying lazyish lb lea leach leachability leachable leachate leachates leached leacher leachers leaches leaching lead leaded leaden leadenly leadenness leader leaderless leaders leadership leaderships leadier leadiest leading leadingly leadless leadman leadmen leadoff leadoffs leadplant leadplants leads leadscrew leadscrews leadsman leadsmen leadwork leadwort leadworts leady leaf leafage leafed leafhopper leafhoppers leafier leafiest leafiness leafing leafless leaflet leafleted leafleteer leafleteers leafleting leaflets leafletted leafletting leaflike leafs leafstalk leafstalks leafy league leagued leaguer leaguered leaguering leaguers leagues leaguing leah leak leakage leakages leaked leaker leakers leakier leakiest leakily leakiness leaking leakproof leaks leaky leal leally lean leander leaned leaner leanest leaning leanings leanly leanness leans leant leap leaped leaper leapers leapfrog leapfrogged leapfrogging leapfrogs leaping leaps leapt lear learn learnable learned learnedly learnedness learner learners learning learns learnt leary leas leasable lease leaseback leased leasehold leaseholder leaseholders leaseholds leaser leasers leases leash leashed leashes leashing leasing leasings least leastways leastwise leather leatherback leatherbacks leathered leatherette leatherettes leatherhead leatherheads leatheriness leathering leatherjacket leatherjackets leatherleaf leatherlike leathern leatherneck leathernecks leathers leatherwear leatherwood leatherwoods leatherwork leatherworker leatherworkers leatherworking leatherworks leathery leave leaved leaven leavened leavening leavenings leavens leaver leavers leaves leaving leavings leavis leavisite lebanese lebanon lebensraum lebenswelt lebkuchen lecce lech leched lecher lecheries lecherous lecherously lecherousness lechers lechery leches leching lechwe lechwes lecithin lecithinase lecithinases lectern lecterns lectin lectins lection lectionaries lectionary lections lector lectors lectotype lectotypes lecture lectured lecturer lecturers lectures lectureship lectureships lecturing led leda lederhosen ledge ledger ledgers ledges ledgy lee leeboard leeboards leech leeched leeches leeching leechlike leek leeks leer leered leerier leeriest leerily leeriness leering leeringly leers leery lees leeuwenhoek leeward leeway left lefties leftish leftism leftist leftists leftmost leftover leftovers lefts leftward leftwards leftwing lefty leg legacies legacy legal legalese legaleses legalism legalisms legalist legalistic legalistically legalists legalities legality legalization legalizations legalize legalized legalizer legalizers legalizes legalizing legally legals legate legated legatee legatees legates legateship legateships legatine legating legation legationary legations legato legator legators legatos legend legendarily legendary legendries legendry legends leger legerdemain legerdemains legerity legers leges legged legger leggers leggier leggiest leggin legginess legging leggings leggins leggy leghold leghorn leghorns legibility legible legibleness legibly legion legionaries legionary legionella legionellae legionnaire legionnaires legions legislate legislated legislates legislating legislation legislative legislatively legislatives legislator legislatorial legislators legislatorship legislatorships legislature legislatures legist legists legit legitimacy legitimate legitimated legitimately legitimateness legitimates legitimating legitimation legitimations legitimatize legitimatized legitimatizes legitimatizing legitimator legitimators legitimism legitimist legitimists legitimization legitimizations legitimize legitimized legitimizer legitimizers legitimizes legitimizing legless legman legmen legomena legomenon legroom legs legume legumes leguminous legwork lehar lehigh lehua lehuas lei leibnitz leicester leicesters leicestershire leiden leipzig leis leishmania leishmanial leishmanias leishmaniasis leister leistered leistering leisters leisure leisured leisureliness leisurely leisurewear leitmotif leitmotifs leitmotiv leitmotivs lek leke leks leku lekvar lekvars lely leman lemans lemma lemmas lemmata lemming lemminglike lemmings lemniscal lemniscate lemnisci lemniscus lemnos lemon lemonade lemonades lemongrass lemongrasses lemons lemony lempira lempiras lemur lemures lemurlike lemurs lenape lenapes lend lendable lender lenders lending lends length lengthen lengthened lengthener lengtheners lengthening lengthens lengthier lengthiest lengthily lengthiness lengths lengthways lengthwise lengthy lenience leniencies leniency lenient leniently lenin leningrad leninism leninist leninists leninite leninites lenis lenition lenitions lenitive lenitively lenitives lenity lennon lennox leno lenos lens lense lensed lenses lensing lensless lensman lensmen lent lentamente lentando lenten lentic lenticel lenticellate lenticels lenticular lenticule lenticules lentigines lentiginose lentiginous lentigo lentil lentils lentisk lentisks lentissimo lentivirus lentiviruses lento lentos lents leo leonardo leone leones leonian leonians leonid leonides leonids leonine leopard leopardess leopardesses leopardi leopards leopold leos leotard leotarded leotards lepanto lepcha lepchas leper lepers lepidolite lepidolites lepidoptera lepidopteran lepidopterans lepidopterist lepidopterists lepidopterological lepidopterologist lepidopterologists lepidopterology lepidopterous lepidote lepontic lepontine leporine leprechaun leprechaunish leprechauns lepromatous leprosaria leprosarium leprosariums leprose leprosy leprotic leprous leprously leprousness lepta leptocephali leptocephalus lepton leptonic leptons leptosomatic leptosome leptosomes leptospiral leptospire leptospires leptospirosis leptotene leptotenes lepus lerici lesbian lesbianism lesbians lesbos lese lesion lesioned lesions lesotho lespedeza lespedezas less lessee lessees lessen lessened lessening lessens lesser lesson lessoned lessoning lessons lessor lessors lest let let's letch letches letdown letdowns lethal lethality lethally lethalness lethargic lethargically lethargies lethargy lethe lethean leto lets lett letted letter letterbox letterboxed letterboxes letterboxing lettered letterer letterers letterform letterforms lettergram lettergrams letterhead letterheads lettering letterings letterman lettermen letterpress letterpresses letters letterspacing lettic letting lettings lettish letts lettuce lettuces letup letups leu leucine leucines leucite leucites leucitic leucocidin leucocidins leucocyte leucocytes leucocytic leucocytoid leucocytoses leucocytosis leucocytotic leucoderma leucodermal leucodermas leucodermic leucopenia leucopenias leucopenic leucoplast leucoplastid leucoplastids leucoplasts leucorrhea leucorrheal leucorrheas leucotomies leucotomy leukemia leukemic leukemics leukemogenesis leukemogenic leukemoid leukocyte leukocytes leukocytic leukocytoid leukocytoses leukocytosis leukocytotic leukoderma leukodermal leukodermas leukodermic leukodystrophy leukopenia leukopenias leukopenic leukoplakia leukoplakias leukoplakic leukoplasia leukoplasias leukopoiesis leukopoietic leukorrhea leukorrheal leukorrheas leukoses leukosis leukotomies leukotomy leukotriene leukotrienes lev leva levalloisian levant levanted levanter levanters levantine levantines levanting levants levas levator levatores levators levee leveed leveeing levees level leveled leveler levelers levelheaded levelheadedly levelheadedness leveling levelled leveller levellers levelling levelly levelness levels lever leverage leveraged leverages leveraging levered leveret leverets leverhulme levering leverkusen levers levi levi's leviable leviathan leviathans levied levier leviers levies levigate levigated levigates levigating levigation levigations levin levins levirate levirates leviratic leviratical levis levitate levitated levitates levitating levitation levitational levitations levitator levitators levite levites levitic levitical leviticus levities levity levo levodopa levodopas levorotary levorotation levorotations levorotatory levs levulose levuloses levy levying lewd lewder lewdest lewdly lewdness lewis lewises lewisite lewisites lewisson lewissons lex lexeme lexemes lexemic lexes lexica lexical lexicality lexicalization lexicalizations lexicalize lexicalized lexicalizes lexicalizing lexically lexicographer lexicographers lexicographic lexicographical lexicographically lexicography lexicological lexicologically lexicologist lexicologists lexicology lexicon lexicons lexington lexis lexises ley leyden león lhasa lhotse li liabilities liability liable liaise liaised liaises liaising liaison liaisons liana lianas liane lianes liang liao liaodong liaoning liaotung liar liars liassic lib libation libationary libations libbed libber libbers libbing libecchio libeccio libel libelant libelants libeled libelee libelees libeler libelers libeling libelist libelists libellant libellants libelled libellee libellees libelling libellous libelous libelously libels libera liberace liberal liberalism liberalist liberalistic liberalists liberalities liberality liberalization liberalizations liberalize liberalized liberalizer liberalizers liberalizes liberalizing liberally liberalness liberals liberate liberated liberates liberating liberatingly liberation liberationist liberationists liberations liberator liberators liberia liberian liberians libertarian libertarianism libertarians liberties libertinage libertinages libertine libertines libertinism liberty libidinal libidinally libidinous libidinously libidinousness libido libidos libitum libra librae libran librans librarian librarians librarianship librarianships libraries library libration librational librations libratory libre libres libretti librettist librettists libretto librettos libriform libris librist librists librium libs libya libyan libyans lice licence licenced licences licencing licensable license licensed licensee licensees licenser licensers licenses licensing licensor licensors licensure licensures licente licentiate licentiates licentious licentiously licentiousness lich lichee lichees lichen lichened lichening lichenological lichenologist lichenologists lichenology lichenous lichens licit licitly licitness lick licked licker lickerish lickerishly lickerishness lickers lickety licking lickings licks lickspittle lickspittles licorice lictor lictors lid lidar lidded lidding lidless lido lidocaine lidos lids lie liebfraumilch liebig liechtenstein liechtensteiner liechtensteiners lied lieder liederkranz lief liefer liefest liege liegeman liegemen lieges lien liens lier lierne liernes liers lies lieu lieutenancies lieutenancy lieutenant lieutenants life lifeblood lifeboat lifeboats lifeful lifeguard lifeguarded lifeguarding lifeguards lifejacket lifejackets lifeless lifelessly lifelessness lifelike lifelikeness lifeline lifelines lifelong lifer lifers lifes lifesaver lifesavers lifesaving lifestyle lifestyles lifetime lifetimes lifeway lifework lifo lift liftable lifted lifter lifters liftgate liftgates lifting liftman liftmen liftoff liftoffs lifts ligament ligamental ligamentary ligamentous ligaments ligan ligand ligands ligans ligase ligases ligate ligated ligates ligating ligation ligations ligature ligatured ligatures ligaturing liger ligers light lightbulb lightbulbs lighted lighten lightened lightener lighteners lightening lightens lighter lighterage lighterages lighters lightest lightface lightfaced lightfast lightfastness lightheaded lightheadedly lightheadedness lighthearted lightheartedly lightheartedness lighthouse lighthouses lighting lightings lightish lightless lightlessness lightly lightness lightning lightninged lightninglike lightnings lightplane lightplanes lightproof lights lightship lightships lightsome lightsomely lightsomeness lighttight lightweight lightweights lightwood lightwoods ligneous lignification lignifications lignified lignifies lignify lignifying lignin lignite lignitic lignocellulose lignocelluloses lignocellulosic lignosulfonate lignosulfonates lignum ligroin ligula ligulae ligulas ligulate ligule ligules ligure ligures liguria ligurian ligurians likability likable likableness like likeable likeableness liked likelier likeliest likelihood likeliness likely liken likened likeness likenesses likening likens likes likewise liking likings likker likuta lilac lilacs lilangeni lilied lilies lilith lille lilliput lilliputian lilliputians lilt lilted lilting liltingly liltingness lilts lily lima limacine limacon limacons limas limassol limb limba limbas limbate limbeck limbecks limbed limber limbered limbering limberly limberness limbers limbi limbic limbing limbless limbo limbos limbs limburg limburger limburgers limbus limby lime limeade limeades limed limekiln limekilns limelight limen limens limerick limericks limes limestone limewater limewaters limey limeys limicoline limicolous limier limiest limina liminal liming limit limitability limitable limitary limitation limitational limitations limitative limited limitedly limitedness limiteds limiter limiters limites limiting limitingly limitless limitlessly limitlessness limitrophe limits limmer limmers limn limned limner limners limnetic limning limnologic limnological limnologically limnologist limnologists limnology limns limo limoges limonene limonenes limonite limonitic limos limousin limousine limousines limp limpa limped limper limpest limpet limpets limpid limpidity limpidly limpidness limping limpkin limpkins limply limpness limpopo limps limuli limulus limy linac linacs linage linages linalool linalools linchpin linchpins lincoln lincolnesque lincolniana lincolnshire lincomycin lincomycins lindane lindanes lindbergh lindemann linden lindens lindesnes lindies lindisfarne lindy line lineage lineages lineal lineality lineally lineament lineamental lineaments linear linearity linearization linearizations linearize linearized linearizes linearizing linearly lineation lineations linebacker linebackers linebacking linebred linebreeding linecaster linecasters linecasting linecut linecuts lined linefeed linefeeds lineman linemen linen linens lineolate liner linerboard linerboards linerless liners lines linesman linesmen lineswoman lineswomen lineup lineups liney ling linga lingala lingalas lingam lingams lingas lingayat lingayats lingayen lingberries lingberry lingcod lingcods linger lingered lingerer lingerers lingerie lingering lingeringly lingers lingo lingoes lingonberries lingonberry lings lingua linguae lingual lingually linguals linguine linguini linguist linguistic linguistical linguistically linguistician linguisticians linguistics linguists lingulate liniment liniments linin lining linings linins link linkage linkages linkboy linkboys linked linker linkers linking linkings linkman linkmen links linksman linksmen linkup linkups linn linnaean linnaeus linnean linnet linnets linnhe linns linocut linocuts linoleate linoleates linoleic linolenic linoleum linotype linotypes linsang linsangs linseed linseeds linsey linstock linstocks lint lintel lintels linter linters lintless lintwhite lintwhites linty linuron linurons lion lioness lionesses lionfish lionfishes lionheart lionhearted lionization lionizations lionize lionized lionizer lionizers lionizes lionizing lionlike lions lip lipan lipans lipari lipase lipases lipectomies lipectomy lipid lipide lipides lipidic lipids lipizzan lipizzaner lipizzaners lipizzans lipless liplike lipogenesis lipoic lipoid lipoidal lipoids lipolyses lipolysis lipolytic lipoma lipomas lipomata lipomatous lipophilic lipopolysaccharide lipopolysaccharides lipoprotein lipoproteins liposomal liposome liposomes liposuction liposuctions lipotropic lipotropin lipotropins lipotropism lipotropy lipped lippes lippi lippier lippiest lipping lippizan lippizaner lippizaners lippizans lippy lipreading lips lipstick lipsticked lipsticks liptauer liptauers lipton liquate liquated liquates liquating liquation liquations liquefacient liquefaction liquefactions liquefactive liquefiable liquefied liquefier liquefiers liquefies liquefy liquefying liquescence liquescency liquescent liqueur liqueurs liquid liquidambar liquidambars liquidate liquidated liquidates liquidating liquidation liquidations liquidator liquidators liquidity liquidize liquidized liquidizes liquidizing liquidly liquidness liquids liquified liquifies liquify liquifying liquor liquored liquorice liquoring liquors lira liras lire liri liripipe liripipes lirot liroth lisbon lisente lisle lisp lisped lisper lispers lisping lisps lissom lissome lissomely lissomeness list listed listee listees listel listels listen listenability listenable listened listener listeners listenership listenerships listening listens lister listeria listerias listeriosis listers listing listings listless listlessly listlessness lists liszt lit litanies litany litchi litchis lite liter literacy literal literalism literalist literalistic literalists literality literalization literalizations literalize literalized literalizes literalizing literally literalness literals literarily literariness literary literate literately literateness literates literati literatim literation literations literator literators literature literatures literatus liters litharge litharges lithe lithely litheness lither lithesome lithest lithia lithias lithiases lithiasis lithic lithification lithifications lithified lithifies lithify lithifying lithium litho lithoed lithoes lithograph lithographed lithographer lithographers lithographic lithographical lithographically lithographing lithographs lithography lithoing lithologic lithological lithologically lithologist lithologists lithology lithophane lithophanes lithophyte lithophytes lithophytic lithopone lithopones lithos lithosol lithosols lithosphere lithospheres lithospheric lithostratigraphic lithostratigraphy lithotomies lithotomy lithotripsies lithotripsy lithotripter lithotripters lithotriptor lithotriptors lithotrities lithotrity lithuania lithuanian lithuanians litigable litigant litigants litigate litigated litigates litigating litigation litigations litigator litigators litigious litigiously litigiousness litmus litotes litre litres litten litter litterateur litterateurs litterbag litterbags litterbug litterbugs littered litterer litterers littering littermate littermates litters littery little littleneck littlenecks littleness littler littlest littoral littorals littérateur littérateurs liturgic liturgical liturgically liturgics liturgies liturgiologist liturgiologists liturgiology liturgist liturgists liturgy livability livable livableness live liveability liveable livebearer livebearers lived livelier liveliest livelihood livelihoods livelily liveliness livelong lively liven livened liveness livening livens liver livered liveried liveries liverish liverishness liverleaf liverleaves liverpudlian liverpudlians livers liverwort liverworts liverwurst livery liveryman liverymen lives livestock livetrap livetraps livid lividity lividly lividness living livingly livingness livings livingstone livonia livonian livonians livorno livre livres livy lixiviate lixiviated lixiviates lixiviating lixiviation lixiviations lizard lizardfish lizardfishes lizardlike lizards lizzie liège ljubljana ll llama llamas llano llanos lloyd llullaillaco lo loach loaches load loaded loader loaders loading loadings loadmaster loadmasters loads loadstar loadstars loadstone loadstones loaf loafed loafer loafers loafing loafs loam loamed loaming loams loamy loan loanable loanda loaned loaner loaners loaning loans loansharking loansharkings loanword loanwords loath loathe loathed loather loathers loathes loathing loathingly loathings loathly loathness loathsome loathsomely loathsomeness loaves lob lobar lobate lobated lobately lobation lobations lobbed lobber lobbers lobbied lobbies lobbing lobby lobbyer lobbyers lobbygow lobbygows lobbying lobbyism lobbyist lobbyists lobe lobectomies lobectomy lobed lobefin lobefinned lobefins lobelia lobelias lobeline lobelines lobes loblollies loblolly lobo lobola lobolas lobos lobotomies lobotomize lobotomized lobotomizes lobotomizing lobotomy lobs lobscouse lobscouses lobster lobstered lobsterer lobsterers lobstering lobsterlike lobsterman lobstermen lobsters lobular lobularly lobulate lobulated lobulation lobulations lobule lobules lobulose lobworm lobworms loc local locale locales localism localisms localist localists localite localites localities locality localizability localizable localization localizations localize localized localizer localizers localizes localizing locally localness locals locarno locatable locate located locater locaters locates locating location locational locationally locations locative locatives locator locators loch lochia lochial lochs loci lock lockable lockage lockages lockbox lockboxes lockdown lockdowns locke locked locker lockers locket lockets locking lockjaw lockkeeper lockkeepers lockmaster lockmasters locknut locknuts lockout lockouts lockram locks lockset locksets locksmith locksmithing locksmiths lockstep lockstitch lockstitched lockstitches lockstitching lockup lockups loco locoed locoes locofoco locofocos locoing locoism locoisms locomote locomoted locomotes locomoting locomotion locomotive locomotives locomotor locomotory locos locoweed locoweeds locular loculate loculated loculation loculations locule loculed locules loculi loculicidal loculus locum locus locust locusts locution locutions lode loden lodens lodes lodestar lodestars lodestone lodestones lodge lodged lodgement lodgements lodgepole lodger lodgers lodges lodging lodgings lodgment lodgments lodicule lodicules loeb loess loessial loft lofted loftier loftiest loftily loftiness lofting loftlike lofts lofty log loganberries loganberry logarithm logarithmic logarithmical logarithmically logarithms logbook logbooks loge loges logged logger loggerhead loggerheads loggers loggia loggias logging loggings logia logic logical logicality logically logicalness logician logicians logics logier logiest login logins logion logistic logistical logistically logistician logisticians logistics logjam logjams lognormal lognormality lognormally logo logogram logogrammatic logogrammatically logograms logograph logographic logographically logographs logography logogriph logogriphs logoi logomachies logomachy logorrhea logorrheic logos logotype logotypes logout logroll logrolled logroller logrollers logrolling logrollings logrolls logs logwood logwoods logy lohengrin loin loincloth loincloths loins loire loiter loitered loiterer loiterers loitering loiters loki lolita lolitas loll lolland lollapalooza lollapaloozas lollard lollardism lollards lollardy lolled loller lollers lollies lolling lollingly lollipop lollipops lollop lolloped lolloping lollops lollopy lolls lolly lollygag lollygagged lollygagging lollygags lollypop lollypops lombard lombardian lombardic lombards lombardy lombok loment loments lomond lomé london londonderry londoner londoners lone lonelier loneliest lonelily loneliness lonely loneness loner loners lonesome lonesomely lonesomeness lonesomes long longan longanimity longans longboat longboats longbow longbowman longbowmen longbows longcase longed longer longeron longerons longest longevities longevity longevous longfellow longhair longhaired longhairs longhand longhead longheaded longheadedness longheads longhorn longhorns longhouse longhouses longicorn longicorns longing longingly longings longish longitude longitudes longitudinal longitudinally longleaf longlegs longline longlines longman longneck longnecks longness longobard longobardi longobardic longobards longs longship longships longshore longshoreman longshoremen longshoring longsighted longsightedness longsome longsomely longsomeness longspur longspurs longstanding longsuffering longtime longue longues longueur longueurs longwinded longwindedly longwise longyi longyis lonsdale loo loobies looby loofa loofah loofahs loofas look lookalike lookalikes lookdown lookdowns looked looker lookers looking lookout lookouts looks lookup lookups loom loomed looming looms loon looney looneys loonier loonies looniest loonily looniness loons loony loop looped looper loopers loophole loopholes loopier loopiest looping loops loopy loos loose loosed loosely loosen loosened looseness loosening loosens looser looses loosest loosestrife loosestrifes loosey loosing loot looted looter looters looting loots lop lope loped loper lopers lopes lophophore lophophores loping lopped lopper loppers loppier loppiest lopping loppy lops lopsided lopsidedly lopsidedness loquacious loquaciously loquaciousness loquacity loquat loquats loran lorca lord lorded lording lordings lordlier lordliest lordliness lordling lordlings lordly lordoses lordosis lordotic lords lordship lordships lordy lore loreal lorelei loreleis lorentz lorenz lorgnette lorgnettes lorgnon lorgnons lorica loricae loricate loricated lories lorikeet lorikeets loris lorises lorn lorne lornness lorraine lorries lorry lory los losable losableness lose losel losels loser losers loses losing losingest losings loss losses lossless lossy lost lostness lot lota lotah lotahs lotas loth lothario lotharios lothian loti lotic lotion lotions lotos lotoses lots lotte lotted lotteries lottery lotting lotto lottos lotus lotuses lotusland louche loud louden loudened loudening loudens louder loudest loudly loudmouth loudmouthed loudmouths loudness loudspeaker loudspeakers loudun lough loughs louis louise louisiana louisville lounge lounged lounger loungers lounges loungewear lounging loupe loupes lour lourdes loured lourenço louring lours loury louse loused louses lousewort louseworts lousier lousiest lousily lousiness lousing lousy lout louted louting loutish loutishly loutishness louts louvain louver louvered louvers louvre louvred louvres lovability lovable lovableness lovably lovage lovages lovastatin lovat lovats love loveable lovebird lovebirds lovebug lovebugs loved lovelace loveless lovelessly lovelessness lovelier lovelies loveliest lovelily loveliness lovelock lovelocks lovelorn lovelornness lovely lovemaking lover loverly lovers loves loveseat loveseats lovesick lovesickness lovesome lovey loving lovingly lovingness low lowball lowballed lowballing lowballs lowborn lowboy lowboys lowbred lowbrow lowbrowed lowbrows lowdown lowed lower lowercase lowercased lowercases lowercasing lowerclassman lowerclassmen lowered lowering loweringly lowermost lowers lowery lowest lowing lowland lowlander lowlanders lowlands lowlier lowliest lowlife lowlifes lowlight lowlights lowlihead lowliheads lowliness lowlives lowly lown lowness lows lox loxes loxodrome loxodromes loxodromic loxodromical loxodromically loyal loyalism loyalist loyalists loyally loyalties loyalty loyola lozenge lozenges lsd luanda luau luaus luba lubas lubavitcher lubavitchers lubber lubberliness lubberly lubbers lube lubed lubes lubing lubricant lubricants lubricate lubricated lubricates lubricating lubrication lubrications lubricative lubricator lubricators lubricious lubriciously lubriciousness lubricities lubricity lubricous lucania lucarne lucarnes lucca lucency lucent lucently lucerne luces lucia lucian lucians lucid lucida lucidas lucidity lucidly lucidness lucifer luciferase luciferases luciferin luciferins lucina lucinas lucite luck lucked luckier luckiest luckily luckiness lucking luckless lucknow lucks lucky lucrative lucre lucrece lucretian lucretius lucubrate lucubrated lucubrates lucubrating lucubration lucubrations luculent lucullan luddism luddite luddites lude ludes ludicrous ludicrously ludicrousness lues luetic luetically luff luffa luffas luffed luffing luffs lufthansa luftwaffe lug lugano luge luged luger lugers luges luggage lugged lugger luggers lugging luging lugs lugsail lugsails lugubrious lugubriously lugubriousness lugworm lugworms luichow luiseño luiseños luke lukewarm lukewarmly lukewarmness lull lullabied lullabies lullaby lullabying lulled lulling lulls lully lulu lulus lumbago lumbar lumber lumbered lumberer lumberers lumbering lumberingly lumberjack lumberjacks lumberman lumbermen lumbers lumberyard lumberyards lumbricoid lumeloid lumen lumenal lumens lumina luminal luminance luminaria luminarias luminaries luminary luminesce luminesced luminescence luminescent luminesces luminescing luminiferous luminism luminist luminists luminosities luminosity luminous luminously luminousness lumière lummox lummoxes lump lumpectomies lumpectomy lumped lumpen lumpenproletariat lumpenproletariats lumpfish lumpfishes lumpier lumpiest lumpily lumpiness lumping lumpish lumpishly lumpishness lumps lumpur lumpy luna lunacies lunacy lunar lunarscape lunarscapes lunate lunated lunates lunatic lunatics lunation lunch lunched luncheon luncheonette luncheonettes luncheons luncher lunchers lunches lunching lunchmeat lunchmeats lunchroom lunchrooms lunchtime lunchtimes lundy lune lunes lunette lunettes lung lunge lunged lunger lungers lunges lungfish lungfishes lungi lunging lungis lungs lungworm lungworms lungwort lungworts lungyi lungyis lunisolar lunitidal lunker lunkers lunkhead lunkheaded lunkheads lunula lunulae lunular lunulate lunulated lunule lunules luny lupercalia lupercalian lupin lupine lupines lupins lupulin lupulins lupus lurch lurched lurcher lurchers lurches lurching lurchingly lure lured lurer lurers lures lurex lurid luridly luridness luring luringly lurk lurked lurker lurkers lurking lurkingly lurks lusaka lusatia lusatian lusatians luscious lusciously lusciousness lush lushed lusher lushes lushest lushing lushly lushness lusitania lusitanian lusitanians lust lusted luster lustered lustering lusterless lusters lusterware lustful lustfully lustfulness lustier lustiest lustily lustiness lusting lustra lustral lustrate lustrated lustrates lustrating lustration lustrations lustrative lustrous lustrously lustrousness lustrum lustrums lusts lusty lusus lutanist lutanists lute luteal lutecium luted lutefisk lutefisks lutein luteinization luteinizations luteinize luteinized luteinizes luteinizing luteins lutenist lutenists luteous lutes lutetium lutfisk lutfisks luther lutheran lutheranism lutheranize lutheranized lutheranizes lutheranizing lutherans lutherism luthier luthiers luting lutist lutists lutyens lutz lutzes luwian luwians lux luxate luxated luxates luxating luxation luxations luxe luxembourg luxembourger luxembourgers luxemburg luxes luxor luxuriance luxuriant luxuriantly luxuriate luxuriated luxuriates luxuriating luxuries luxurious luxuriously luxuriousness luxury luzon lwei lyam lyase lyases lycanthrope lycanthropes lycanthropies lycanthropy lyceum lyceums lych lychee lychees lychnis lychnises lycia lycian lycians lycopene lycopenes lycopod lycopodium lycopodiums lycopods lycra lycée lycées lyddite lyddites lydia lydian lydians lye lygus lying lyings lyme lymph lymphadenitis lymphadenopathies lymphadenopathy lymphangiogram lymphangiograms lymphangiographic lymphangiographies lymphangiography lymphatic lymphatically lymphatics lymphoblast lymphoblastic lymphoblasts lymphocyte lymphocytes lymphocytic lymphocytosis lymphocytotic lymphogram lymphograms lymphogranuloma lymphogranulomatoses lymphogranulomatosis lymphographic lymphography lymphoid lymphokine lymphokines lymphoma lymphomas lymphomata lymphomatoid lymphomatoses lymphomatosis lymphomatous lymphopoieses lymphopoiesis lymphopoietic lymphosarcoma lymphosarcomas lymphosarcomata lymphotoxin lymphotoxins lymphotropic lynch lynched lyncher lynchers lynches lynching lynchings lynchpin lynchpins lynx lynxes lyon lyonnais lyonnaise lyonnesse lyons lyophile lyophiled lyophilic lyophilization lyophilizations lyophilize lyophilized lyophilizer lyophilizers lyophilizes lyophilizing lyophobic lyra lyrate lyre lyrebird lyrebirds lyres lyric lyrical lyrically lyricalness lyricism lyricist lyricists lyricize lyricized lyricizes lyricizing lyrics lyrism lyrist lyrists lysander lysate lysates lyse lysed lysenko lysenkoism lysergic lyses lysimeter lysimeters lysimetric lysin lysine lysing lysins lysis lysistrata lysithea lysogen lysogenic lysogenicity lysogenies lysogenization lysogenizations lysogenize lysogenized lysogenizes lysogenizing lysogens lysogeny lysol lysolecithin lysolecithins lysosomal lysosome lysosomes lysozyme lysozymes lytic lytically lytta lyttae lytton lázne lésvos lèse límnos lübeck m m1 m16 ma ma'am maar maars maasai maasais maastricht mab mabe mac macabre macabrely macaco macacos macadam macadamia macadamias macadamization macadamizations macadamize macadamized macadamizer macadamizers macadamizes macadamizing macanese macao macaque macaques macaroni macaronic macaronics macaronies macaronis macaroon macaroons macassar macau macaulay macaw macaws macbeth maccabean maccabees macduff mace macebearer macebearers maced macedon macedonia macedonian macedonians macer macerate macerated macerater maceraters macerates macerating maceration macerations macerator macerators macers maces mach machabees mache maches machete machetes machiavelli machiavellian machiavellianism machiavellians machiavellism machiavellist machiavellists machicolate machicolated machicolates machicolating machicolation machicolations machina machinability machinable machinate machinated machinates machinating machination machinations machinator machinators machine machineability machineable machined machineless machinelike machineries machinery machines machining machinist machinists machismo machmeter machmeters macho machoism machos machzor macing macintosh macintoshes mack mackenzie mackerel mackerels mackinac mackinaw mackinaws mackintosh mackintoshes mackle mackled mackles macklin mackling maclaurin macle macled macles macmillan macon macpherson macramé macready macro macroaggregate macroaggregated macroaggregates macrobiotic macrobiotics macrocephalia macrocephalic macrocephalous macrocephaly macroclimate macroclimates macroclimatic macrocode macrocodes macrocosm macrocosmic macrocosmically macrocosms macrocyclic macrocyte macrocytes macrocytic macrocytoses macrocytosis macrocytotic macrodome macrodomes macroeconomic macroeconomics macroeconomist macroeconomists macroevolution macroevolutionary macroevolutions macrofossil macrofossils macrogamete macrogametes macroglobulin macroglobulinemia macroglobulinemias macroglobulinemic macroglobulins macrograph macrographs macrography macroinstruction macroinstructions macrolepidoptera macromere macromeres macromolecular macromolecule macromolecules macron macrons macronuclear macronuclei macronucleus macronutrient macronutrients macrophage macrophages macrophagic macrophotograph macrophotographs macrophotography macrophysics macrophyte macrophytes macrophytic macropterous macros macroscale macroscales macroscopic macroscopical macroscopically macrosporangia macrosporangium macrospore macrospores macrostructural macrostructure macrostructures macs macula maculae macular maculas maculate maculated maculates maculating maculation macule maculed macules maculing macumba macédoine mad madagascan madagascans madagascar madam madame madames madams madcap madcaps madded madden maddened maddening maddeningly maddens madder madders maddest madding maddish made madeira madeiran madeirans madeiras madeleine madeleines mademoiselle mademoiselles madhouse madhouses madhya madison madly madman madmen madness madnesses madonna madonnas madras madrepore madrepores madreporian madreporic madreporite madreporites madrid madrigal madrigalian madrigalist madrigalists madrigals madrilene madrilenes madrilène madrilènes madrona madrone madrones madrono madroña madroñas madroño madroños mads maduro maduros madwoman madwomen madwort madworts mae maecenas maecenases maelstrom maelstroms maenad maenadic maenads maestoso maestri maestro maestros mafeking maffick mafficked mafficking mafficks mafia mafic mafiosi mafioso mafiosos mag magadha magazine magazines magazinist magazinists magdalen magdalene magdalenes magdalenian magdalens magdeburg mage magellan magellanic magen magenta magentas mages maggiore maggot maggots maggoty maghreb maghrib magi magian magianism magic magical magically magician magicians magicked magicking magics maginot magisterial magisterially magisterium magisteriums magistracies magistracy magistral magistrally magistrate magistrates magistratical magistratically magistrature magistratures maglemosian maglev maglevs magma magmas magmata magmatic magna magnanimities magnanimity magnanimous magnanimously magnanimousness magnate magnates magnesia magnesian magnesite magnesites magnesium magnet magnetar magnetars magnetic magnetically magnetism magnetisms magnetite magnetizable magnetization magnetizations magnetize magnetized magnetizer magnetizers magnetizes magnetizing magneto magnetoelectric magnetoelectricity magnetofluiddynamic magnetofluiddynamics magnetogasdynamic magnetogasdynamics magnetograph magnetographs magnetohydrodynamic magnetohydrodynamics magnetometer magnetometers magnetometric magnetometry magnetomotive magneton magnetons magnetopause magnetopauses magnetoplasmadynamic magnetoplasmadynamics magnetoresistance magnetoresistances magnetos magnetosphere magnetospheres magnetospheric magnetostatic magnetostriction magnetostrictions magnetostrictive magnetostrictively magnetron magnetrons magnets magnifiable magnific magnifical magnifically magnificat magnification magnifications magnificats magnificence magnificent magnificently magnifico magnificoes magnified magnifier magnifiers magnifies magnify magnifying magniloquence magniloquent magniloquently magnitude magnitudes magnolia magnolias magnon magnum magnums magnus magot magots magpie magpies mags maguey magueys magus magyar magyars mah mahabharata mahal mahaleb mahalebs mahalo maharaja maharajah maharajahs maharajas maharanee maharanees maharani maharanis maharashtra maharishi maharishis mahatma mahatmas mahayana mahayanas mahayanist mahayanistic mahayanists mahdi mahdis mahdism mahdist mahdists mahi mahican mahicans mahimahi mahis mahjong mahjongg mahjonggs mahjongs mahler mahlstick mahlsticks mahoe mahoes mahoganies mahogany mahomet mahonia mahout mahouts mahrati mahratta mahratti mahuang mahuangs mahzor mahzorim mahzors maia maid maiden maidenhair maidenhairs maidenhead maidenheads maidenhood maidenliness maidenly maidens maidhood maidish maidishness maids maidservant maidservants maidu maidus maieutic maieutical mail mailability mailable mailbag mailbags mailbox mailboxes maile mailed mailer mailers mailgram mailing mailings maillot maillots mailman mailmen mailroom mailrooms mails maim maimed maimer maimers maiming maims main maine mainframe mainframes mainland mainlander mainlanders mainline mainlined mainliner mainliners mainlines mainlining mainly mainmast mainmasts mains mainsail mainsails mainsheet mainsheets mainspring mainsprings mainstay mainstays mainstream mainstreamed mainstreamer mainstreamers mainstreaming mainstreams maintain maintainability maintainable maintained maintainer maintainers maintaining maintains maintenance maintop maintops mainz maiolica maisonette maisonettes maitre maitres maize maizes majeste majestic majestical majestically majesties majesty majesté majeure majolica major majora majorca majorcan majorcans majordomo majordomos majored majorette majorettes majoring majoritarian majoritarianism majoritarians majorities majority majorly majors majuscular majuscule majuscules makable makalu makar makars makassar make makeable makebate makebates makefast makefasts makeover makeovers maker makereadies makeready makers makes makeshift makeshifts makeup makeups makeweight makeweights makimono makimonos making makings mako makos makuta mal malabar malabo malabsorption malabsorptions malacca malaccas malachi malachias malachite malacological malacologist malacologists malacology malacostracan malacostracans maladaptation maladaptations maladapted maladaptive maladies maladjusted maladjustive maladjustment maladjustments maladminister maladministered maladministering maladministers maladministration maladministrations maladroit maladroitly maladroitness maladroits malady malaga malagas malagasies malagasy malagueña malaise malamute malamutes malapert malapertly malapertness malaperts malapportioned malapportionment malapportionments malaprop malapropian malapropism malapropisms malapropist malapropists malapropos malaprops malar malaria malarial malarian malariologist malariologists malariology malarious malarkey malarky malars malassimilation malassimilations malate malates malathion malawi malawian malawians malay malaya malayalam malayalams malayan malayans malays malaysia malaysian malaysians malcontent malcontented malcontentedly malcontentedness malcontents maldistribution maldistributions maldivan maldivans maldive maldives maldivian maldivians male maleate maleates malebranche malecite malecites maledict maledicted maledicting malediction maledictions maledictory maledicts malefaction malefactions malefactor malefactors malefic maleficence maleficent maleic malemute malemutes maleness malentendu malentendus males malevolence malevolent malevolently malfeasance malfeasant malfeasants malfi malformation malformations malformed malfunction malfunctioned malfunctioning malfunctions malgre mali malian malians malic malice malicious maliciously maliciousness malign malignance malignancies malignancy malignant malignantly maligned maligner maligners maligning malignities malignity malignly maligns malihini malihinis maline malines malinger malingered malingerer malingerers malingering malingers malinke malinkes malinois maliseet maliseets malison malisons malkin malkins mall mallard mallards malleability malleable malleableness malleably malled mallee mallees mallei mallemuck mallemucks mallet mallets malleus malling mallorca mallow mallows malls malmsey malmseys malnourish malnourished malnourishes malnourishing malnourishment malnourishments malnutrition malo malocclusion malocclusions malodor malodorous malodorously malodorousness malodors malolactic malonic maloti malpighian malplaquet malposition malpositions malpractice malpractitioner malpractitioners malt malta maltase malted maltese maltha malthas malthus malthusian malthusianism malthusians malting maltose maltreat maltreated maltreater maltreaters maltreating maltreatment maltreatments maltreats malts maltster maltsters malty malvasia malvasias malversation malversations malvinas malvoisie malvoisies mama mamas mamba mambas mamberamo mambo mamboed mamboing mambos mameluke mamelukes mamey mameys mamluk mamluks mamma mammae mammal mammalian mammalians mammalogical mammalogist mammalogists mammalogy mammals mammaplasties mammaplasty mammary mammas mammate mammee mammer mammered mammering mammers mammies mammiferous mammilla mammillae mammillary mammillate mammillated mammillation mammillations mammock mammocked mammocking mammocks mammogram mammograms mammographic mammographies mammography mammon mammonism mammonist mammonists mammoplasties mammoplasty mammoth mammoths mammy mamoré man mana manacle manacled manacles manacling manage manageability manageable manageableness manageably managed management managemental managements manager manageress manageresses managerial managerially managers managership managerships manages managing managua managuan managuans manakin manakins manama manamah manas manasseh manatee manatees manchester manchineel manchineels manchu manchuguo manchukuo manchuria manchurian manchurians manchus manciple manciples mancunian mancunians mandaean mandaeans mandala mandalas mandalay mandalic mandamus mandamused mandamuses mandamusing mandan mandans mandarin mandarinate mandarinates mandarinic mandarinism mandarins mandataries mandatary mandate mandated mandates mandating mandator mandatories mandatorily mandators mandatory mande mandean mandeans mandekan mandekans mandelbrot mandes mandible mandibles mandibular mandibulate mandibulates mandingo mandingoes mandingos mandinka mandinkas mandioca mandola mandolas mandolin mandoline mandolines mandolinist mandolinists mandolins mandragora mandragoras mandrake mandrakes mandrel mandrels mandril mandrill mandrills mandrils mane maned manege maneges manes manet maneuver maneuverability maneuverable maneuvered maneuverer maneuverers maneuvering maneuverings maneuvers manful manfully manfulness mangabey mangabeys manganate manganates manganese manganesian manganic manganite manganites manganous mange mangel manger mangers mangier mangiest mangily manginess mangle mangled mangler manglers mangles mangling mango mangoes mangonel mangonels mangos mangosteen mangosteens mangrove mangroves mangy manhandle manhandled manhandles manhandling manhattan manhattanite manhattanites manhattanization manhattanizations manhattanize manhattanized manhattanizes manhattanizing manhattans manhole manholes manhood manhunt manhunts mania maniac maniacal maniacally maniacs manias manic manically manichaean manichaeanism manichaeanisms manichaeans manichaeism manichaeisms manichean manicheans manichee manichees manicheism manicotti manics manicure manicured manicures manicuring manicurist manicurists manifest manifestant manifestants manifestation manifestations manifested manifester manifesters manifesting manifestly manifesto manifestoed manifestoes manifestoing manifestos manifests manifold manifolded manifolding manifoldly manifoldness manifolds manikin manikins manila manilas manilla manillas manille maninka maninkas manioc manioca maniocas maniocs maniple maniples manipulability manipulable manipular manipulars manipulatable manipulate manipulated manipulates manipulating manipulation manipulations manipulative manipulatively manipulativeness manipulator manipulators manipulatory manipur manito manitoba manitoban manitobans manitos manitou manitoulin manitous manitu manitus mankind manless manlier manliest manlike manliness manly manmade manna mannan mannans mannar manned mannequin mannequins manner mannered mannerism mannerisms mannerist manneristic mannerists mannerless mannerliness mannerly manners mannheim mannikin mannikins manning mannish mannishly mannishness mannite mannites mannitol mannitols mannose mannoses mano manometer manometers manometric manometrical manometrically manometry manor manorial manorialism manors manos manpack manpower manqué manrope manropes mans mansard mansarded mansards manse manservant manses mansfield mansion mansions manslaughter manslayer manslayers mansuetude mansuetudes manta mantas manteau manteaus manteaux mantegna mantel mantelet mantelets mantelletta mantellettas mantelpiece mantelpieces mantels mantelshelf mantelshelfs manteltree manteltrees mantes mantic mantically manticore mantid mantids mantilla mantillas mantis mantises mantissa mantissas mantle mantled mantles mantlet mantlets mantling mantoux mantova mantra mantrap mantraps mantras mantric mantua mantuan mantuans mantuas manu manual manually manuals manubria manubrium manufactories manufactory manufacturable manufactural manufacture manufactured manufacturer manufacturers manufactures manufacturing manumission manumissions manumit manumits manumitted manumitter manumitters manumitting manure manured manurer manurers manures manurial manuring manus manuscript manuscripts manward manwards manwise manx manxman manxmen manxwoman manxwomen many manyfold manyplies manzanilla manzanillas manzanita manzanitas manzoni manège manèges mao maoism maoist maoists maori maoris map maple maples maplike mapmaker mapmakers mapmaking mappable mapped mapper mappers mapping mappings maps maputo maquette maquettes maqui maquila maquiladora maquiladoras maquilas maquillage maquillages maquis maquisard maquisards mar mara marabou marabous marabout marabouts maraca maracaibo maracas maraging marajó maranta marantas maras marasca marascas maraschino maraschinos marasmic marasmus marat maratha marathas marathi marathon marathoner marathoners marathoning marathons marattas maraud marauded marauder marauders marauding marauds marañón marbella marble marbled marbleize marbleized marbleizes marbleizing marbles marblewood marblewoods marbling marbly marburg marc marcasite marcasites marcasitical marcato marcatos marcel marcelled marcelling marcels marcescent march marchand marche marched marchen marcher marchers marches marchesa marchese marchesi marching marchioness marchionesses marchland marchlands marchlike marchpane marchpanes marcionism marcionite marcionites marconi marcs mardi marduk mare marek marengo mares marfan margarine margarines margarita margaritas margarite margarites margay marge margent margents margin marginal marginalia marginality marginalization marginalizations marginalize marginalized marginalizes marginalizing marginally marginate marginated marginates marginating margination marginations margined margining margins margravate margravates margrave margraves margravial margraviate margraviates margravine margravines marguerite marguerites maria mariachi mariachis marian mariana marianas marianist marianists maricopa maricopas maricultural mariculture maricultures mariculturist mariculturists marie marienberg marienbourg marienburg marigold marigolds marihuana marijuana marimba marimbas marimbist marimbists marina marinade marinaded marinades marinading marinara marinaras marinas marinate marinated marinates marinating marination marinations marine mariner mariners marines marino mariolater mariolaters mariolatrous mariolatry mariological mariology marionette marionettes mariposa marish marishes marist marists marital maritally maritime mariánské marjoram mark markdown markdowns marked markedly markedness marker markers market marketability marketable marketed marketeer marketeering marketeers marketer marketers marketing marketings marketplace marketplaces markets marketwise markham markhor markhors marking markings markka markkaa markkas markoff markov markovian marks marksman marksmanship marksmen markswoman markswomen markup markups marl marled marlin marline marlines marlinespike marlinespikes marling marlingspike marlingspikes marlins marlinspike marlinspikes marlite marlites marlitic marls marlstone marlstones marly marmalade marmalades marmara marmite marmites marmolada marmoreal marmoreally marmorean marmoset marmosets marmot marmots marne marocain marocains maronite maronites maroon marooned marooning maroons marplot marplots marque marquee marquees marques marquesan marquesans marquess marquessate marquessates marquesses marqueterie marqueteries marquetries marquetry marquette marquis marquisate marquisates marquise marquises marquisette marquisettes marrakech marrakesh marram marrams marrano marranos marred marriage marriageability marriageable marriageableness marriages married marrieds marries marring marron marrons marrow marrowbone marrowbones marrowfat marrowfats marrowy marry marrying mars marsala marsalas marse marseillaise marseille marseilles marsh marshal marshalcy marshaled marshaling marshall marshalled marshalling marshals marshalship marshalships marshes marshier marshiest marshiness marshland marshlands marshmallow marshmallows marshmallowy marshy marston marsupia marsupial marsupials marsupium mart martaban martagon martagons marted martel martello marten martens martensite martensites martensitic martensitically martha martial martialed martialing martialism martialist martialists martialled martialling martially martials martian martians martin martinet martinets marting martingal martingale martingales martingals martini martinique martinis martinmas martinmases martins martlet martlets marts martyr martyrdom martyred martyries martyring martyrization martyrizations martyrize martyrized martyrizes martyrizing martyrologies martyrologist martyrologists martyrology martyrs martyry martí marvel marveled marveling marvelled marvelling marvellous marvelous marvelously marvelousness marvels marx marxian marxianism marxians marxism marxist marxists mary maryknoller maryknollers maryland marylander marylanders maryology marys marzipan mas masaccio masachusetts masada masai masais masala masalas masbate mascara mascaraed mascaraing mascaras mascarpone mascarpones mascon mascons mascot mascots masculine masculinely masculineness masculines masculinities masculinity masculinization masculinizations masculinize masculinized masculinizes masculinizing masefield maser masers maseru mash mashed masher masherbrum mashers mashes mashgiach mashgiah mashgichim mashgihim mashie mashies mashing mashy masjid masjids mask maskable masked maskeg maskegs masker maskers masking maskings maskinonge maskinonges masklike masks masochism masochist masochistic masochistically masochists mason masoned masonic masoning masonite masonries masonry masons masora masorah masorahs masoras masorete masoretes masoretic masque masquer masquerade masqueraded masquerader masqueraders masquerades masquerading masquers masques mass massachuset massachusets massachusett massachusetts massacre massacred massacrer massacrers massacres massacring massage massaged massager massagers massages massaging massasauga massasaugas masscult masscults masse massed massena masses masseter masseteric masseters masseur masseurs masseuse masseuses massicot massicots massier massiest massif massifs massing massinger massive massively massiveness massless massorete massoretes massy massé mast mastaba mastabah mastabahs mastabas mastectomies mastectomy masted master masterdom mastered masterful masterfully masterfulness masteries mastering masterliness masterly mastermind masterminded masterminding masterminds masterpiece masterpieces masters mastership masterships mastersinger mastersingers masterstroke masterstrokes masterwork masterworks mastery masthead mastheads mastic masticate masticated masticates masticating mastication mastications masticator masticatories masticators masticatory mastics mastiff mastiffs mastigophoran mastigophorans mastitic mastitis mastodon mastodonic mastodons mastodont mastoid mastoidectomies mastoidectomy mastoiditis mastoids masts masturbate masturbated masturbates masturbating masturbation masturbational masturbator masturbators masturbatory masuria masurian mat matabele matabeleland matabeles matador matadors matagorda matapan match matchability matchable matchboard matchboards matchbook matchbooks matchbox matchboxes matched matcher matchers matches matching matchless matchlessly matchlessness matchlock matchlocks matchmaker matchmakers matchmaking matchstick matchsticks matchup matchups matchwood matchwoods mate mated matelot matelote matelotes matelots matelotte matelottes mater materfamilias materfamiliases materia material materialism materialist materialistic materialistically materialists materialities materiality materialization materializations materialize materialized materializer materializers materializes materializing materially materialness materials materiel maternal maternalism maternally maternities maternity maters mates matey mateyness math mathematic mathematical mathematically mathematician mathematicians mathematics mathematization mathematizations mathematize mathematized mathematizes mathematizing maths matilda matilija matin matinal matinee matinees mating matins matinée matinées matisse matjes matriarch matriarchal matriarchalism matriarchate matriarchates matriarchic matriarchies matriarchs matriarchy matrices matricidal matricide matricides matriclinous matriculant matriculants matriculate matriculated matriculates matriculating matriculation matriculations matrilineage matrilineages matrilineal matrilineally matrilocal matrilocally matrimonial matrimonially matrimonies matrimony matrix matrixes matron matronal matronliness matronly matrons matronymic matronymics mats matsu matte matted matter mattered matterhorn mattering matters mattery mattes matthaean matthean matthew matthias matting mattings mattock mattocks mattress mattresses maturate maturated maturates maturating maturation maturational maturations maturative mature matured maturely matureness maturer matures maturest maturing maturities maturity matutinal matutinally matzo matzoh matzohs matzos matzot matzoth maté matériel mau maud maudlin maudlinly maudlinness maued maugham maugre maui mauing maul mauled mauler maulers mauling mauls maulstick maulsticks maund maunder maundered maunderer maunderers maundering maunders maunds maundy maupassant mauretania mauretanian mauretanians maurice mauritania mauritanian mauritanians mauritian mauritians mauritius mauser mausolea mausolean mausoleum mausoleums mauve mauves maven mavens maverick mavericks mavin mavins mavis mavises mavourneen mavourneens mavournin mavournins maw mawkish mawkishly mawkishness maws max maxed maxes maxi maxilla maxillae maxillaries maxillary maxillas maxilliped maxillipeds maxillofacial maxim maxima maximal maximalist maximalists maximally maximals maximi maximilian maximin maximization maximizations maximize maximized maximizer maximizers maximizes maximizing maxims maximum maximums maximus maxing maxis maxixe maxixes maxwell may maya mayagüez mayan mayanist mayanists mayans mayapple mayapples mayas maybe maybes mayday maydays mayest mayflies mayflower mayflowers mayfly mayhap mayhem mayhems maying mayings maymyo mayn mayn't mayo mayon mayonnaise mayor mayoral mayoralties mayoralty mayoress mayoresses mayors mayorship mayorships mayos mayotte maypole maypoles maypop maypops mays mayst maytime mayweed mayweeds mazaedia mazaedium mazal mazard mazards mazatlán mazda mazdaism mazdeism maze mazed mazel mazelike mazer mazers mazes mazier maziest mazily maziness mazing mazourka mazourkas mazuma mazumas mazurka mazurkas mazy mazzard mazzards maître mañana mbabane mbira mbiras mbundu mbundus mccarthyism mccarthyist mccarthyists mccarthyite mccarthyites mcclure mccoy mccoys mcintosh mcintoshes mckinley mdewakanton mdewakantons me mea mead meadow meadowfoam meadowland meadowlands meadowlark meadowlarks meadows meadowsweet meadowsweets meadowy meager meagerly meagerness meagre meal mealie mealier mealies mealiest mealiness meals mealtime mealtimes mealworm mealworms mealy mealybug mealybugs mealymouthed mean meander meandered meanderer meanderers meandering meanderingly meanders meandrous meaner meanest meanie meanies meaning meaningful meaningfully meaningfulness meaningless meaninglessly meaninglessness meaningly meanings meanly meanness means meant meantime meanwhile meany measle measles measlier measliest measly measurability measurable measurably measure measured measuredly measuredness measureless measurelessly measurelessness measurement measurements measurer measurers measures measuring meat meatball meatballs meated meathead meatheads meatier meatiest meatiness meatless meatloaf meatloaves meatpacker meatpackers meatpacking meatpackings meats meatus meatuses meaty mecamylamine mecamylamines mecca meccas mechanic mechanical mechanically mechanicalness mechanicals mechanician mechanicians mechanics mechanism mechanisms mechanist mechanistic mechanistically mechanists mechanizable mechanization mechanizations mechanize mechanized mechanizer mechanizers mechanizes mechanizing mechanochemical mechanochemistry mechanoreception mechanoreceptions mechanoreceptive mechanoreceptor mechanoreceptors mechanotherapies mechanotherapist mechanotherapists mechanotherapy mechlin mechlins mecklenburg meclizine meclizines meconium meconiums mecopteran mecopterans mecopterous mecum mecums med medaillon medaillons medaka medakas medal medaled medaling medalist medalists medalled medallic medalling medallion medallions medallist medallists medals meddle meddled meddler meddlers meddles meddlesome meddlesomely meddlesomeness meddling mede medea medellín medes medevac medevaced medevacing medevacs medflies medfly media mediacy mediad mediae mediaeval mediaevalism mediaevalisms mediaevalist mediaevalists mediagenic medial medially medials median medianly medians mediant mediants medias mediastina mediastinal mediastinum mediate mediated mediately mediates mediating mediation mediational mediations mediative mediatization mediatizations mediatize mediatized mediatizes mediatizing mediator mediators mediatory mediatrix medic medica medicable medicaid medical medically medicals medicament medicamentous medicaments medicare medicate medicated medicates medicating medication medications medicative medicatrix medicean medici medicinable medicinal medicinally medicine medicines medick medicks medico medicolegal medicos medics medieval medievalism medievalisms medievalist medievalists medievally medina medinas mediocre mediocrities mediocritization mediocritizations mediocritize mediocritized mediocritizes mediocritizing mediocrity meditate meditated meditates meditating meditation meditational meditations meditative meditatively meditativeness meditator meditators mediterranean mediterraneans medium mediumistic mediums mediumship medlar medlars medley medleys medoc medocs medulla medullae medullar medullary medullas medullated medullization medullizations medulloblastoma medulloblastomas medulloblastomata medusa medusae medusan medusans medusas medusoid medusoids meed meeds meek meeker meekest meekly meekness meemies meerkat meerkats meerschaum meerschaums meet meeter meeters meeting meetinghouse meetinghouses meetings meetly meets mefenamic megaampere megaamperes megabar megabars megabecquerel megabecquerels megabit megabits megabuck megabucks megabyte megabytes megacandela megacandelas megacephalic megacephalies megacephalous megacephaly megacities megacity megacorporation megacorporations megacoulomb megacoulombs megacycle megacycles megadeal megadeals megadeath megadeaths megadose megadoses megaera megafarad megafarads megafauna megafaunal megaflop megaflops megagamete megagametes megagametophyte megagametophytes megagram megagrams megahenries megahenry megahenrys megahertz megahit megahits megajoule megajoules megakaryocyte megakaryocytes megakaryocytic megakelvin megakelvins megalith megalithic megaliths megaloblast megaloblastic megaloblasts megalocardia megalocardias megalocephalic megalocephalies megalocephalous megalocephaly megalomania megalomaniac megalomaniacal megalomaniacally megalomaniacs megalomanic megalopolis megalopolises megalopolistic megalopolitan megalosaur megalosaurian megalosaurians megalosaurs megalumen megalumens megalux megameter megameters megamole megamoles meganewton meganewtons megaohm megaohms megaparsec megaparsecs megapascal megapascals megaphone megaphoned megaphones megaphonic megaphonically megaphoning megapode megapodes megapolis megaproject megaprojects megara megaradian megaradians megarian megarians megaric megarics megaron megarons megascopic megascopically megasecond megaseconds megasiemens megasievert megasieverts megasporangia megasporangium megaspore megaspores megasporic megasporocyte megasporocytes megasporogeneses megasporogenesis megasporophyll megasporophylls megastar megastars megasteradian megasteradians megastructure megastructures megatesla megateslas megathere megatheres megatherian megaton megatonnage megatons megavitamin megavitamins megavolt megavoltage megavoltages megavolts megawatt megawattage megawattages megawatts megaweber megawebers meghalaya megillah megillahs megilp megilps megohm megohms megrez megrim megrims meiji mein meioses meiosis meiotic meiotically meissen meissens meistersinger meistersingers meitnerium mekong melamine melancholia melancholiac melancholiacs melancholic melancholically melancholics melancholily melancholiness melancholy melanchthon melanesia melanesian melanesians melange melanges melanic melanin melanism melanistic melanite melanites melanitic melanization melanizations melanize melanized melanizes melanizing melanoblast melanoblastic melanoblasts melanocyte melanocytes melanogenesis melanoid melanoids melanoma melanomas melanomata melanophore melanophores melanoses melanosis melanosity melanosome melanosomes melanotic melanous melaphyre melaphyres melatonin melatonins melba melbourne melchior melchite melchites melchizedek melchizedeks meld melded melding melds melee melees melena melenas melic melilot melilots meliorable meliorate meliorated meliorates meliorating melioration meliorations meliorative melioratives meliorator meliorators meliorism meliorist melioristic meliorists melisma melismas melismata melismatic melkite melkites mell melled melliferous mellific mellifluence mellifluent mellifluently mellifluous mellifluously mellifluousness melling mellitus mellophone mellophones mellotron mellotrons mellow mellowed mellower mellowest mellowing mellowly mellowness mellows mells melodeon melodeons melodic melodically melodies melodious melodiously melodiousness melodist melodists melodize melodized melodizer melodizers melodizes melodizing melodrama melodramas melodramatic melodramatically melodramatics melodramatist melodramatists melodramatization melodramatizations melodramatize melodramatized melodramatizes melodramatizing melody meloid meloids melon melongene melongenes melons melos melphalan melphalans melpomene melt meltability meltable meltage meltages meltdown meltdowns melted melter melters melting meltingly melton meltons melts meltwater melty melville mem member membered members membership memberships membranal membrane membraned membranes membranous membranously memento mementoes mementos memnon memo memoir memoire memoirist memoirists memoirs memorabilia memorability memorable memorableness memorably memoranda memorandum memorandums memorial memorialist memorialists memorialization memorializations memorialize memorialized memorializer memorializers memorializes memorializing memorially memorials memoriam memories memoriter memorizable memorization memorizations memorize memorized memorizer memorizers memorizes memorizing memory memos memphis memsahib memsahibs men menace menaced menacer menacers menaces menacing menacingly menad menadione menadiones menads menage menagerie menageries menages menander menarche menarcheal menazon menazons mencken menckenian mend mendable mendacious mendaciously mendaciousness mendacities mendacity mende mended mendel mendeleev mendelevium mendelian mendelianism mendelianisms mendelians mendelism mendelisms mendelist mendelists mendelssohn mender menders mendes mendicancy mendicant mendicants mendicity mending mendings mends meneer meneers menelaus menenius menfolk menfolks menhaden menhadens menhir menhirs menial menially menials meniere meningeal meninges meningioma meningiomas meningiomata meningitic meningitides meningitis meningococcal meningococci meningococcic meningococcus meningoencephalitic meningoencephalitis meninx meniscal meniscate meniscectomy menisci meniscoid meniscoidal meniscus meniscuses mennonite mennonites meno menology menominee menominees menopausal menopause menorah menorahs menorca menorrhagia menorrhagias menorrhagic mens mensa mensal mensch menschen mensches mensem menservants menses mensh menshevik mensheviki mensheviks menshevism menshevist menshevists menstrua menstrual menstruate menstruated menstruates menstruating menstruation menstruous menstruum menstruums mensurability mensurable mensurableness mensural mensuration mensurations mensurative menswear menta mental mentalism mentalisms mentalist mentalistic mentalists mentalities mentality mentally mentation mentations menthe menthol mentholated menthols mention mentionable mentioned mentioner mentioners mentioning mentions mentis mentor mentored mentoring mentors mentorship mentorships mentum menu menuhin menus meo meos meow meowed meowing meows meperidine meperidines mephistophelean mephistopheles mephistophelian mephitic mephitical mephitically mephitis mephitises meprobamate meprobamates mer meramec merbromin merbromins mercalli mercantile mercantilism mercantilist mercantilistic mercantilists mercaptan mercaptans mercaptopurine mercaptopurines mercator mercedario mercedes mercenaries mercenarily mercenariness mercenary mercer merceries mercerization mercerizations mercerize mercerized mercerizes mercerizing mercers mercery merchandisable merchandise merchandised merchandiser merchandisers merchandises merchandising merchandisings merchandize merchandized merchandizes merchandizing merchandizings merchant merchantability merchantable merchantman merchantmen merchants mercia mercian mercians mercies merciful mercifully mercifulness merciless mercilessly mercilessness mercurate mercurated mercurates mercurating mercuration mercurations mercurial mercurialism mercurialisms mercurially mercurialness mercurials mercuric mercurochrome mercurous mercury mercutio mercy merde mere meredith merely merengue merengues merest meretricious meretriciously meretriciousness merganser mergansers merge merged mergence merger mergers merges merging meridian meridians meridiem meridional meridionally meridionals meringue meringues merino merinos meristem meristematic meristematically meristems meristic meristically merit merited meriting meritless meritocracies meritocracy meritocrat meritocratic meritocrats meritorious meritoriously meritoriousness merits merl merle merles merlin merlins merlon merlons merlot merlots merls mermaid mermaids merman mermen meroblastic meroblastically merocrine meromorphic meromyosin meromyosins merope meropia meropic meroplankton meroplanktonic meroplanktons merovingian merovingians merowe merozoite merozoites meroë merrier merriest merrily merrimack merriment merriness merry merrymaker merrymakers merrymaking merrythought merrythoughts merseyside merthiolate mesa mesabi mesarch mesas mescal mescalero mescaleros mescaline mescals mesdames mesdemoiselles meseemed meseems mesembryanthemum mesembryanthemums mesencephalic mesencephalon mesenchymal mesenchymatous mesenchyme mesenchymes mesenteric mesenteries mesenteritis mesenteritises mesenteron mesenteronic mesenterons mesentery mesh meshach meshed meshes meshing meshuga meshugaas meshugah meshugga meshuggah meshugge meshuggener meshuggeners meshwork meshy mesial mesially mesic mesityl mesitylene mesitylenes mesmer mesmeric mesmerically mesmerism mesmerist mesmerists mesmerization mesmerizations mesmerize mesmerized mesmerizer mesmerizers mesmerizes mesmerizing mesne mesoamerica mesoamerican mesoamericans mesoblast mesoblastic mesoblasts mesocarp mesocarps mesocephalic mesocephally mesocyclone mesocyclones mesoderm mesodermal mesodermic mesogastria mesogastric mesogastrium mesoglea mesogleal mesogloea mesolithic mesomere mesomeres mesomorph mesomorphic mesomorphism mesomorphous mesomorphs mesomorphy meson mesonephric mesonephros mesonephroses mesonic mesons mesopause mesopauses mesopelagic mesophyll mesophyllic mesophyllous mesophylls mesophyte mesophytes mesophytic mesopotamia mesopotamian mesopotamians mesoscale mesosome mesosomes mesosphere mesospheric mesothelia mesothelial mesothelioma mesotheliomas mesotheliomata mesothelium mesothoraces mesothoracic mesothorax mesothoraxes mesothorium mesothoriums mesotrophic mesozoic mesquite mesquites mess message messaged messages messaging messaline messalines messed messeigneurs messenger messengered messengering messengers messenia messenian messenians messes messiah messiahs messiahship messianic messianism messianisms messianist messianists messias messier messiest messieurs messily messina messiness messing messmate messmates messrs messuage messuages messy mestiza mestizas mestizo mestizoes mestizos mestranol mestranols met metabolic metabolically metabolism metabolisms metabolite metabolites metabolizable metabolize metabolized metabolizes metabolizing metacarpal metacarpally metacarpals metacarpi metacarpus metacenter metacenters metacentric metacentricity metacentrics metacercaria metacercarial metacercarias metachromatic metachromatism metachromatisms metaethical metaethics metafiction metafictional metafictionist metafictionists metafictions metagalactic metagalaxies metagalaxy metagenesis metagenetic metagnathism metagnathous metal metalanguage metalanguages metaled metaling metalinguistic metalinguistics metalize metalized metalizes metalizing metalled metallic metallically metallics metalliferous metalline metalling metallization metallizations metallize metallized metallizes metallizing metallographer metallographers metallographic metallographically metallography metalloid metalloidal metalloids metallophone metallophones metallurgic metallurgical metallurgically metallurgist metallurgists metallurgy metalmark metalmarks metals metalsmith metalsmiths metalware metalwork metalworker metalworkers metalworking metamathematical metamathematician metamathematicians metamathematics metamere metameres metameric metamerically metamerism metamerisms metamorphic metamorphically metamorphism metamorphose metamorphosed metamorphoses metamorphosing metamorphosis metamorphous metanalyses metanalysis metanephric metanephros metanephroses metaphase metaphases metaphor metaphoric metaphorical metaphorically metaphors metaphosphate metaphosphates metaphosphoric metaphrase metaphrased metaphrases metaphrasing metaphrast metaphrastic metaphrasts metaphysic metaphysical metaphysically metaphysician metaphysicians metaphysics metaplasia metaplasias metaplasm metaplasmic metaplasms metaplastic metapontum metaprotein metaproteins metapsychological metapsychology metasequoia metasilicate metasomatic metasomatically metasomatism metasomatosis metastability metastable metastably metastases metastasis metastasize metastasized metastasizes metastasizing metastatic metastatically metatarsal metatarsally metatarsals metatarsi metatarsus metate metates metatheses metathesis metathesize metathesized metathesizes metathesizing metathetic metathetical metathetically metathoraces metathoracic metathorax metathoraxes metaxylem metaxylems metazoal metazoan metazoans metazoic mete meted metempsychoses metempsychosis metencephala metencephalic metencephalon meteor meteoric meteorically meteorite meteorites meteoritic meteoritical meteoriticist meteoriticists meteoritics meteorograph meteorographs meteoroid meteoroidal meteoroids meteorologic meteorological meteorologically meteorologist meteorologists meteorology meteors meter metered metering meters meterstick metersticks metes metestrous metestrus metestruses meth methacrylate methacrylates methacrylic methadon methadone methamphetamine methamphetamines methanation methanations methane methanol methaqualone methaqualones methedrine metheglin metheglins methemoglobin methemoglobinemia methemoglobins methenamine methenamines methicillin methicillins methinks methionine methionines method methodic methodical methodically methodicalness methodism methodist methodistic methodistical methodists methodization methodizations methodize methodized methodizer methodizers methodizes methodizing methodological methodologically methodologies methodologist methodologists methodology methods methotrexate methotrexates methought methoxychlor methoxychlors methoxyflurane methuen methuselah methyl methylal methylals methylamine methylamines methylase methylases methylate methylated methylates methylating methylation methylations methylator methylators methylbenzene methylbenzenes methylcellulose methylcelluloses methylcholanthrene methyldopa methyldopas methylene methylenes methylic methylmercury methylnaphthalene methylnaphthalenes methylphenidate methylphenidates methylprednisolone methylxanthine methylxanthines methysergide methysergides meticais metical meticals meticulosity meticulous meticulously meticulousness metier metiers meting metis metonic metonym metonymic metonymical metonymically metonymies metonyms metonymy metoo metope metopes metopic metopon metopons metralgia metralgias metrazol metric metrical metrically metricate metricated metricates metricating metrication metricize metricized metricizes metricizing metrics metrification metrifications metrified metrifies metrify metrifying metrist metrists metritis metritises metro metrological metrologically metrologies metrologist metrologists metrology metronidazole metronidazoles metronome metronomes metronomic metronomical metronomically metronymic metroplex metroplexs metropolis metropolises metropolitan metropolitans metrorrhagia metrorrhagias metrorrhagic metros metternich mettle mettled mettles mettlesome metz meunière meursault meuse mew mewed mewing mewl mewled mewling mewls mews mex mexicali mexican mexicans mexico meyerbeer meze mezereon mezereons mezereum mezereums mezes mezuza mezuzah mezuzahs mezuzas mezuzot mezza mezzanine mezzanines mezzo mezzos mezzotint mezzotints mi miami miamis miao miaos miaow miasma miasmal miasmas miasmata miasmatic miasmic miasmically mica micaceous micah micas micawber micawberish micawbers miccosukee miccosukees mice micellar micelle micelles mich michael michaelis michaelmas michaelmases micheas michelangelo michelin michigan michigander michiganders mick mickey mickeys mickle micks micmac micmacs micra micro microampere microamperes microanalyses microanalysis microanalyst microanalysts microanalytic microanalytical microanatomical microanatomy microbalance microbalances microbar microbarograph microbarographs microbars microbe microbeam microbeams microbecquerel microbecquerels microbes microbial microbic microbiologic microbiological microbiologically microbiologist microbiologists microbiology microbrewer microbreweries microbrewers microbrewery microbrewing microburst microbursts microbus microbuses microbusses microcalorimeter microcalorimeters microcalorimetric microcalorimetry microcandela microcandelas microcapsule microcapsules microcassette microcassettes microcavity microcephalic microcephalics microcephalies microcephalous microcephaly microchemical microchemist microchemistries microchemistry microchemists microchip microchips microcircuit microcircuitry microcircuits microcirculation microcirculations microcirculatory microclimate microclimates microclimatic microclimatologic microclimatological microclimatology microcline microclines micrococcal micrococci micrococcus microcode microcomputer microcomputers microcopied microcopies microcopy microcopying microcosm microcosmic microcosmical microcosmically microcosmos microcosms microcoulomb microcoulombs microcrystal microcrystalline microcrystallinity microcrystals microcultural microculture microcultures microcurie microcuries microcyte microcytes microcytic microdensitometer microdensitometers microdensitometric microdensitometry microdissection microdissections microdot microdots microearthquake microearthquakes microeconomic microeconomics microelectrode microelectrodes microelectromechanical microelectronic microelectronically microelectronics microelectrophoresis microelectrophoretic microelectrophoretically microelement microelements microencapsulate microencapsulated microencapsulates microencapsulating microencapsulation microencapsulations microenvironment microenvironmental microenvironments microevolution microevolutionary microevolutions microfabrication microfarad microfarads microfauna microfaunal microfibril microfibrillar microfibrils microfiche microfiches microfilament microfilamentous microfilaments microfilaria microfilariae microfilarial microfilm microfilmable microfilmed microfilmer microfilmers microfilming microfilms microfloppies microfloppy microflora microfloral microform microforms microfossil microfossils microfungi microfungus microfunguses microgamete microgametes microgametocyte microgametocytes microgram micrograms micrograph micrographic micrographically micrographics micrographs micrography microgravity microgroove microgrooves microhabitat microhabitats microhenries microhenry microhenrys microhertz microimage microimages microinch microinches microinject microinjected microinjecting microinjection microinjections microinjects microinstruction microinstructions microjet microjets microjoule microjoules microkelvin microkelvins microlepidoptera microlepidopterous microliter microliters microlith microlithic microlithography microliths microlumen microlumens microlux micromachining micromanage micromanaged micromanagement micromanager micromanagers micromanages micromanaging micromanipulation micromanipulations micromanipulative micromanipulator micromanipulators micromere micromeres micrometeorite micrometeorites micrometeoritic micrometeoroid micrometeoroids micrometeorological micrometeorologist micrometeorologists micrometeorology micrometer micrometers micromethod micromethods micrometric micrometrical micrometrically micrometry micromini microminiature microminiaturization microminiaturizations microminiaturize microminiaturized microminiaturizes microminiaturizing microminis micromolar micromole micromoles micromorphological micromorphology micron microneedle microneedles micronesia micronesian micronesians micronewton micronewtons micronize micronized micronizes micronizing microns micronuclear micronuclei micronucleus micronucleuses micronutrient micronutrients microohm microohms microorganism microorganisms micropaleontologic micropaleontological micropaleontologist micropaleontologists micropaleontology microparticle microparticles micropascal micropascals microphage microphages microphagic microphone microphones microphonic microphonics microphotograph microphotographer microphotographers microphotographic microphotographs microphotography microphotometer microphotometers microphotometric microphotometrically microphotometry microphyll microphyllous microphylls microphysical microphysically microphysicist microphysicists microphysics microphyte microphytes microphytic micropipet micropipets micropipette micropipettes microplankton microplanktons micropore micropores microporosity microporous microprint microprints microprism microprisms microprobe microprobes microprocessor microprocessors microprogram microprogramming microprogrammings microprograms microprojection microprojections microprojector microprojectors micropublisher micropublishers micropublishing micropublishings micropulsation micropulsations micropuncture micropunctures micropylar micropyle micropyles microquake microquakes microradian microradians microradiograph microradiographic microradiographs microradiography microreader microreaders microreproduction microreproductions micros microscale microscales microscope microscopes microscopic microscopical microscopically microscopies microscopist microscopists microscopium microscopy microsecond microseconds microseism microseismic microseismicity microseisms microsensor microsensors microsiemens microsievert microsieverts microsoft microsomal microsome microsomes microsomic microspectrophotometer microspectrophotometers microspectrophotometric microspectrophotometry microsphere microspheres microspherical microsporangia microsporangiate microsporangium microspore microspores microsporic microsporocyte microsporocytes microsporogenesis microsporophyll microsporophylls microsporous microstate microstates microsteradian microsteradians microstructural microstructure microstructures microsurgeries microsurgery microsurgical microswitch microswitches microsystems microteaching microteachings microtechnic microtechnics microtechnique microtechniques microtesla microteslas microtome microtomes microtomic microtomies microtomy microtonal microtonality microtonally microtone microtones microtubular microtubule microtubules microvascular microvasculature microvasculatures microvillar microvilli microvillous microvillus microvolt microvolts microwatt microwatts microwavable microwave microwaveable microwaved microwaves microwaving microweber microwebers microworld microworlds micturate micturated micturates micturating micturition micturitions mid midair midas midbrain midbrains midcourse midcult midcults midday midden middens middies middle middlebrow middlebrows middled middleman middlemen middlemost middler middlers middles middleton middleweight middleweights middling middlingly middlings middorsal middy mideast mideasterner mideasterners midfield midfielder midfielders midfields midgard midge midges midget midgets midgut midguts midi midianite midianites midiron midirons midis midland midlander midlanders midlands midlatitude midlatitudes midlevel midlevels midlife midline midlines midlives midlothian midmonth midmorning midmost midnight midnightly midpoint midpoints midrange midranges midrash midrashic midrashim midrib midribs midriff midriffs midsagittal midseason midsection midsections midship midshipman midshipmen midships midsize midsized midsole midsoles midst midstream midsummer midterm midterms midtown midtowns midway midways midweek midweekly midwest midwestern midwesterner midwesterners midwife midwifed midwifery midwifes midwifing midwinter midwinters midwived midwives midwiving midyear midyears mien miens mieux miff miffed miffier miffiest miffiness miffing miffs miffy might mightier mightiest mightily mightiness mightn't mighty mignon mignonette mignonettes mignons migraine migraines migrainous migrant migrants migrate migrated migrates migrating migration migrational migrations migrator migrators migratory mihrab mihrabs mikado mikados mikasuki mikasukis mike miked mikes miking mikra mikron mikrons mikvah mikvos mikvot mikvoth mil miladies milady milage milages milah milan milanese milano milch milchig mild milder mildest mildew mildewed mildewing mildews mildewy mildly mildness mile mileage mileages milepost mileposts miler milers miles milesian milesians milestone milestones miletus milfoil milfoils milia miliaria miliarial miliarias miliary milieu milieus milieux militance militancy militant militantly militantness militants militaria militaries militarily militarism militarist militaristic militaristically militarists militarization militarizations militarize militarized militarizes militarizing military militate militated militates militating milites militia militiaman militiamen militias milium milk milked milker milkers milkfish milkfishes milkier milkiest milkiness milking milkmaid milkmaids milkman milkmen milks milkshake milkshakes milksop milksoppy milksops milkweed milkweeds milkwort milkworts milky mill millage millages millais millboard millboards milldam milldams mille milled millefiori millefleur millefleurs millenarian millenarianism millenarians millenaries millenary millennia millennial millennialism millennialist millennialists millennially millennium millenniums millepede millepedes millepore millepores miller millerite millerites millers millesimal millesimally millesimals millet millets millhouse millhouses milliammeter milliammeters milliampere milliamperes milliard milliards milliary millibar millibars millibecquerel millibecquerels millicandela millicandelas millicoulomb millicoulombs millicurie millicuries millidegree millidegrees millieme milliemes millifarad millifarads milligal milligals milligram milligrams millihenries millihenry millihenrys millihertz millijoule millijoules millikelvin millikelvins millilambert millilamberts milliliter milliliters millilitre millilitres millilumen millilumens millilux millime millimeter millimeters millimetre millimetres millimicron millimicrons millimolar millimole millimoles milline milliner millineries milliners millinery millines millinewton millinewtons milling millings milliohm milliohms million millionaire millionaires millionairess millionairesses millionfold millions millionth millionths milliosmol milliosmols millipascal millipascals millipede millipedes milliradian milliradians millirem millirems milliroentgen milliroentgens millisecond milliseconds millisiemens millisievert millisieverts millisteradian millisteradians millitesla milliteslas millivolt millivoltmeter millivoltmeters millivolts milliwatt milliwatts milliweber milliwebers millpond millponds millrace millraces millrun millruns mills millstone millstones millstream millstreams millwork millworks millwright millwrights milo milord milos milpa milpas milquetoast milquetoasts milquetoasty milreis milrinone mils milt milted milter milters miltiades milting milton miltonian miltonic milts milwaukee mim mimas mimbres mime mimed mimeo mimeoed mimeograph mimeographed mimeographing mimeographs mimeoing mimeos mimer mimers mimes mimeses mimesis mimetic mimetically mimic mimicked mimicker mimickers mimicking mimicries mimicry mimics miming mimosa mimosas min mina minable minacious minaciously minaciousness minacity minae minamata minaret minarets minas minatorial minatorily minatory minaudière minaudières mince minced mincemeat mincer mincers minces minch mincing mincingly mind mindanao mindblower mindblowers minded mindedly mindedness minden minder minders mindful mindfully mindfulness minding mindless mindlessly mindlessness mindoro minds mindscape mindscapes mindset mindsets mine mineable mined minefield minefields minelayer minelayers miner mineral mineralizable mineralization mineralizations mineralize mineralized mineralizer mineralizers mineralizes mineralizing mineralocorticoid mineralocorticoids mineralogic mineralogical mineralogically mineralogies mineralogist mineralogists mineralogy minerals miners minerva mines mineshaft mineshafts minestrone minestrones minesweeper minesweepers minesweeping mineworker mineworkers ming mingier mingiest mingle mingled mingler minglers mingles mingling mingy minho mini miniature miniatures miniaturist miniaturistic miniaturists miniaturization miniaturizations miniaturize miniaturized miniaturizes miniaturizing minibar minibars minibike minibiker minibikers minibikes minibus minibuses minibusses minicab minicabs minicam minicamp minicamps minicams minicar minicars minicomputer minicomputers miniconjou miniconjous miniconvention miniconventions minicourse minicourses minicoy minicycle minicycles minidisk minidisks minie minified minifies minify minifying minikin minikins minilab minilabs minim minima minimal minimalism minimalist minimalists minimality minimalization minimalizations minimalize minimalized minimalizes minimalizing minimally minimax minimill minimills minimization minimizations minimize minimized minimizer minimizers minimizes minimizing minims minimum minimums mining minings minion minions minipark miniparks minis minischool minischools miniscule miniseries miniski miniskirt miniskirted miniskirts miniskis ministate ministates minister ministered ministerial ministerially ministering ministers ministership ministrant ministrants ministration ministrations ministrative ministries ministroke ministrokes ministry minitrack minitracks minium miniums minivan minivans miniver minivers minié mink minke minks minn minnan minneapolis minneconjou minneconjous minnesinger minnesingers minnesota minnesotan minnesotans minnow minnows minoan minoans minor minora minorca minorcan minorcans minored minoring minorite minorites minorities minority minors minos minotaur minoxidil minsk minster minsters minstrel minstrels minstrelsies minstrelsy mint mintage minted minter minters minting mintmark mintmarks minton mints minty minuend minuends minuet minuets minus minuscular minuscule minuses minute minuted minutely minuteman minutemen minuteness minuter minutes minutest minutia minutiae minuting minx minxes minxish minyan minyanim minyans miocene mioses miosis miotic miotics miquelet miquelets miquelon mir mirabile mirabiles mirabilia mirabilis miracidia miracidial miracidium miracle miracles miraculous miraculously miraculousness mirador miradors mirage mirages miranda mirandize mirandized mirandizes mirandizing mire mired mirepoix mirepoixs mires mirex mirexes mirier miriest mirin miriness miring mirins mirk mirks mirky mirliton mirlitons mirror mirrored mirroring mirrorlike mirrors mirs mirth mirthful mirthfully mirthfulness mirthless mirthlessly mirthlessness mirv mirved mirving mirvs miry miró misact misacts misaddress misaddressed misaddresses misaddressing misadjust misadjusted misadjusting misadjusts misadministration misadministrations misadventure misadventures misadvise misadvised misadvises misadvising misaim misaimed misaiming misaims misalign misaligned misaligning misalignment misalignments misaligns misalliance misalliances misallied misallies misallocate misallocated misallocates misallocating misallocation misallocations misally misallying misanalyses misanalysis misanthrope misanthropes misanthropic misanthropically misanthropist misanthropists misanthropy misapplication misapplications misapplied misapplies misapply misapplying misappraisal misappraisals misapprehend misapprehended misapprehending misapprehends misapprehension misapprehensions misappropriate misappropriated misappropriates misappropriating misappropriation misappropriations misarrange misarranged misarranges misarranging misarticulate misarticulated misarticulates misarticulating misassemble misassembled misassembles misassembling misassumption misassumptions misattribute misattributed misattributes misattributing misattribution misattributions misbalance misbalanced misbalances misbalancing misbecame misbecome misbecomes misbecoming misbegotten misbehave misbehaved misbehaver misbehavers misbehaves misbehaving misbehavior misbehaviors misbelief misbeliefs misbelieve misbelieved misbeliever misbelievers misbelieves misbelieving misbound misbrand misbranded misbranding misbrands misbutton misbuttoned misbuttoning misbuttons misc miscalculate miscalculated miscalculates miscalculating miscalculation miscalculations miscall miscalled miscalling miscalls miscaption miscaptioned miscaptioning miscaptions miscarriage miscarriages miscarried miscarries miscarry miscarrying miscast miscasting miscasts miscatalog miscataloged miscataloging miscatalogs miscegenation miscegenational miscegenations miscellanea miscellaneous miscellaneously miscellaneousness miscellanies miscellanist miscellanists miscellany misch mischance mischannel mischanneled mischanneling mischannels mischaracterization mischaracterizations mischaracterize mischaracterized mischaracterizes mischaracterizing mischarge mischarged mischarges mischarging mischief mischievous mischievously mischievousness mischoice mischoices miscibility miscible miscitation miscitations misclassification misclassifications misclassified misclassifies misclassify misclassifying miscode miscoded miscodes miscoding miscommunication miscommunications miscomprehend miscomprehended miscomprehending miscomprehends miscomprehension miscomprehensions miscomputation miscomputations miscompute miscomputed miscomputes miscomputing misconceive misconceived misconceiver misconceivers misconceives misconceiving misconception misconceptions misconduct misconducted misconducting misconducts misconnect misconnected misconnecting misconnection misconnections misconnects misconstruction misconstructions misconstrue misconstrued misconstrues misconstruing miscopied miscopies miscopy miscopying miscorrelation miscorrelations miscount miscounted miscounting miscounts miscreant miscreants miscreate miscreated miscreates miscreating miscreation miscreations miscue miscued miscueing miscues miscuing miscut misdate misdated misdates misdating misdeal misdealer misdealers misdealing misdeals misdealt misdeed misdeeds misdeem misdeemed misdeeming misdeems misdefine misdefined misdefines misdefining misdemeanant misdemeanants misdemeanor misdemeanors misdemeanour misdemeanours misdescribe misdescribed misdescribes misdescribing misdescription misdescriptions misdevelop misdeveloped misdeveloping misdevelops misdiagnose misdiagnosed misdiagnoses misdiagnosing misdiagnosis misdial misdialed misdialing misdialled misdialling misdials misdid misdirect misdirected misdirecting misdirection misdirects misdistribution misdistributions misdivision misdivisions misdo misdoer misdoers misdoes misdoing misdone misdoubt misdoubted misdoubting misdoubts misdraw misdrawing misdrawn misdrew mise miseducate miseducated miseducates miseducating miseducation miseducations misemphases misemphasis misemphasize misemphasized misemphasizes misemphasizing misemploy misemployed misemploying misemployment misemployments misemploys miser miserable miserableness miserably miserere misereres misericord misericorde misericordes misericords miseries miserliness miserly misers misery misesteem misesteemed misesteeming misesteems misestimate misestimated misestimates misestimating misestimation misestimations misevaluate misevaluated misevaluates misevaluating misevaluation misevaluations misfeasance misfeasor misfeasors misfield misfielded misfielding misfields misfile misfiled misfiles misfiling misfire misfired misfires misfiring misfit misfits misfocus misfocused misfocuses misfocusing misfortune misfortunes misfuel misfueled misfueling misfuelled misfuelling misfuels misfunction misfunctioned misfunctioning misfunctions misgauge misgauged misgauges misgauging misgave misgive misgiven misgives misgiving misgivings misgovern misgoverned misgoverning misgovernment misgovernments misgovernor misgovernors misgoverns misgrade misgraded misgrades misgrading misguidance misguide misguided misguidedly misguidedness misguider misguiders misguides misguiding mishandle mishandled mishandles mishandling mishanter mishanters mishap mishaps mishear misheard mishearing mishears mishegaas mishegoss mishit mishits mishitting mishmash mishmashes mishna mishnah mishnaic misidentification misidentifications misidentified misidentifies misidentify misidentifying misimpression misimpressions misinform misinformant misinformants misinformation misinformed misinformer misinformers misinforming misinforms misinterpret misinterpretation misinterpretations misinterpreted misinterpreter misinterpreters misinterpreting misinterprets misjoinder misjoinders misjudge misjudged misjudges misjudging misjudgment misjudgments miskick miskicked miskicking miskicks miskito miskitos misknew misknow misknowing misknowledge misknown misknows mislabel mislabeled mislabeling mislabelled mislabelling mislabels mislaid mislay mislayer mislayers mislaying mislays mislead misleader misleaders misleading misleadingly misleads mislearn mislearned mislearning mislearns mislearnt misled mislike misliked mislikes misliking mislocate mislocated mislocates mislocating mislocation mislocations mismanage mismanaged mismanagement mismanages mismanaging mismark mismarked mismarking mismarks mismarriage mismarriages mismatch mismatched mismatches mismatching mismate mismated mismates mismating misname misnamed misnames misnaming misnomer misnomered misnomers miso misogamic misogamist misogamists misogamy misogynic misogynist misogynistic misogynists misogynous misogyny misologist misologists misology misoneism misoneist misoneists misorder misordered misordering misorders misorient misorientation misoriented misorienting misorients misos mispackage mispackaged mispackages mispackaging misperceive misperceived misperceives misperceiving misperception misperceptions mispickel mispickels misplace misplaced misplacement misplacements misplaces misplacing misplan misplanned misplanning misplans misplay misplayed misplaying misplays misposition mispositioned mispositioning mispositions misprint misprinted misprinting misprints misprision misprisions misprize misprized misprizer misprizers misprizes misprizing misprogram misprogramed misprograming misprogrammed misprogramming misprograms mispronounce mispronounced mispronounces mispronouncing mispronunciation mispronunciations misquotation misquotations misquote misquoted misquoter misquoters misquotes misquoting misread misreading misreads misreckon misreckoned misreckoning misreckons misrecollection misrecollections misrecord misrecorded misrecording misrecords misreference misreferenced misreferences misreferencing misregister misregistered misregistering misregisters misregistration misregistrations misrelate misrelated misrelates misrelating misremember misremembered misremembering misremembers misrender misrendered misrendering misrenders misreport misreported misreporter misreporters misreporting misreports misrepresent misrepresentation misrepresentations misrepresentative misrepresented misrepresenter misrepresenters misrepresenting misrepresents misroute misrouted misroutes misrouting misrule misruled misrules misruling miss missa missable missal missals missed missend missending missends missense missenses missent misses misset missets missetting misshape misshaped misshapen misshapenly misshaper misshapers misshapes misshaping missies missile missileer missileers missileman missilemen missileries missilery missiles missilries missilry missing missiol mission missional missionaries missionary missioned missioner missioners missioning missionization missionizations missionize missionized missionizer missionizers missionizes missionizing missions missis missises mississippi mississippian mississippians missive missives missolonghi missort missorted missorting missorts missouri missourian missourians missouris missout missouts misspeak misspeaking misspeaks misspell misspelled misspelling misspellings misspells misspelt misspend misspending misspends misspent misspoke misspoken misstate misstated misstatement misstatements misstates misstating misstep missteps misstricken misstrike misstrikes misstriking misstruck missus missuses missy mist mistakable mistakably mistake mistaken mistakenly mistaker mistakers mistakes mistaking mistassini misted mister misters mistflower mistflowers misthink misthinking misthinks misthought misthrew misthrow misthrowing misthrown misthrows mistier mistiest mistily mistime mistimed mistimes mistiming mistiness misting mistitle mistitled mistitles mistitling mistletoe mistletoes misto mistook mistrain mistrained mistraining mistrains mistral mistrals mistranscribe mistranscribed mistranscribes mistranscribing mistranscription mistranscriptions mistranslate mistranslated mistranslates mistranslating mistranslation mistranslations mistreat mistreated mistreating mistreatment mistreatments mistreats mistress mistresses mistrial mistrials mistrust mistrusted mistrustful mistrustfully mistrustfulness mistrusting mistrusts mistruth mistruths mists mistune mistuned mistunes mistuning misty mistype mistyped mistypes mistyping misunderstand misunderstanding misunderstandings misunderstands misunderstood misusage misusages misuse misused misuser misusers misuses misusing misutilization misutilizations misvalue misvalued misvalues misvaluing misvocalization misvocalizations misword misworded miswording miswords miswrite miswrites miswriting miswritten miswrote mitanni mitannian mitannians mitchell mite miter mitered miterer miterers mitering miters miterwort miterworts mites mithraic mithraism mithraist mithraists mithras mithridate mithridates mithridatic mithridatism mithridatisms miticidal miticide miticides mitigable mitigate mitigated mitigates mitigating mitigation mitigations mitigative mitigator mitigators mitigatory mitochondria mitochondrial mitochondrion mitogen mitogenic mitogenicity mitogens mitomycin mitomycins mitoses mitosis mitotic mitotically mitral mitre mitred mitres mitrewort mitreworts mitring mitsubishi mitsubishis mitt mitten mittens mittimus mitts mitty mittyish mitzvah mitzvahed mitzvahing mitzvahs mitzvoth miwok miwoks mix mixable mixed mixer mixers mixes mixing mixologist mixologists mixology mixt mixtec mixtecs mixture mixtures mizar mizen mizenmast mizenmasts mizens mizoram mizzen mizzenmast mizzenmasts mizzens mizzle mizzled mizzles mizzling mizzly miño ml mlle mlles mm mme mmes mnemonic mnemonically mnemonics mnemosyne moa moab moabite moabites moabitish moan moaned moaner moaners moaning moans moas moat moated moating moatlike moats mob mobbed mobbing mobbish mobbishly mobcap mobcaps mobe mobil mobile mobiles mobility mobilization mobilizations mobilize mobilized mobilizes mobilizing mobled mobocracies mobocracy mobocrat mobocratic mobocratical mobocrats mobs mobster mobsters mobuto moc moccasin moccasins mocha mochas moche mochica mock mocked mocker mockeries mockers mockery mocking mockingbird mockingbirds mockingly mocks mockup mockups mocs mod modacrylic modacrylics modal modalities modality modally mode model modeled modeler modelers modeless modeling modelings modelled modelling models modem modems modena moderate moderated moderately moderateness moderates moderating moderation moderations moderato moderator moderators moderatorship moderatorships moderatos modern moderne modernism modernisms modernist modernistic modernists modernities modernity modernization modernizations modernize modernized modernizer modernizers modernizes modernizing modernly modernness moderns modes modest modesties modestly modesty modi modica modicum modicums modifiability modifiable modification modifications modificative modificator modificators modificatory modified modifier modifiers modifies modify modifying modigliani modillion modillions modioli modiolus modish modishly modishness modiste modistes modoc modocs modred mods modulability modular modularity modularization modularizations modularize modularized modularizes modularizing modularly modulars modulate modulated modulates modulating modulation modulations modulative modulator modulators modulatory module modules moduli modulo modulus modus moesia mofette mofettes moffette moffettes mogadishu mogen moggie moggies moggy moghul moghuls mogollon mogul moguls mohair mohammed mohammedan mohammedanism mohammedanisms mohammedans moharram mohave mohaves mohawk mohawks mohegan mohegans mohenjo mohican mohicans moho mohock mohockism mohorovicic mohos mohs mohur mohurs moidore moidores moieties moiety moil moiled moiler moilers moiling moilingly moils moines moirai moire moires moiré moist moisten moistened moistener moisteners moistening moistens moister moistest moistly moistness moisture moistures moisturize moisturized moisturizer moisturizers moisturizes moisturizing mojarra mojarras mojave mojaves mojo mojoes mojos moke mokes mol mola molal molalities molality molar molarities molarity molars molas molasses mold moldable moldavia moldavian moldavians moldboard moldboards molded molder moldered moldering molders moldier moldiest moldiness molding moldings moldova moldovan moldovans molds moldy mole molecular molecularity molecularly molecule molecules molehill molehills moles moleskin moleskins molest molestation molestations molested molester molesters molesting molests molies moline molise molière moll mollie mollies mollifiable mollification mollifications mollified mollifier mollifiers mollifies mollify mollifying mollifyingly molls mollusc mollusca molluscan molluscicidal molluscicide molluscicides molluscoid molluscous molluscs molluscum mollusk molluskan mollusks molly mollycoddle mollycoddled mollycoddler mollycoddlers mollycoddles mollycoddling moloch molokai molopo molotov mols molt molted molten molter molters molting molto molts moluccan moluccans moluccas moly molybdate molybdates molybdenite molybdenites molybdenum molybdic molybdous mom mombasa mome moment momenta momentarily momentariness momentary momently momento momentous momentously momentousness moments momentum momentums momes momma mommas mommies mommy moms momus mon mona monacan monacans monachal monachism monachisms monaco monad monadelphous monadic monadical monadically monadism monadnock monadnocks monads monandries monandrous monandry monanthous monarch monarchal monarchally monarchial monarchian monarchianism monarchic monarchical monarchically monarchies monarchism monarchist monarchistic monarchists monarchs monarchy monarda monardas monasterial monasteries monasterries monastery monastic monastical monastically monasticism monastics monatomic monatomically monaural monaurally monaxial monazite monazites monday mondays monde mondrian monecious monel monensin monensins moneran monerans monestrous monet monetarily monetarism monetarist monetarists monetary monetization monetizations monetize monetized monetizes monetizing money moneybag moneybags moneybox moneyboxes moneychanger moneychangers moneyed moneyer moneyers moneygrubber moneygrubbers moneygrubbing moneylender moneylenders moneymaker moneymakers moneymaking moneyman moneymen moneys moneysaving moneywort moneyworts mongeese monger mongered mongering mongers mongo mongol mongolia mongolian mongolians mongolic mongolism mongoloid mongoloids mongols mongoose mongooses mongrel mongrelism mongrelization mongrelizations mongrelize mongrelized mongrelizes mongrelizing mongrelly mongrels monicker monickers monied monies moniker monikers monilial moniliasis moniliform moniliformly monish monished monishes monishing monism monist monistic monistically monists monition monitions monitor monitored monitorial monitorially monitories monitoring monitors monitorship monitorships monitory monk monkeries monkery monkey monkeyed monkeying monkeylike monkeypod monkeypods monkeys monkeyshine monkeyshines monkfish monkfishes monkhood monkhoods monkish monkishly monkishness monks monkshood monkshoods mono monoacid monoacidic monoacids monoamine monoaminergic monoamines monobasic monocarboxylic monocarp monocarpellary monocarpic monocarpous monocarps monocausal monocephalic monocephalous monoceros monochasia monochasial monochasium monochord monochords monochromat monochromatic monochromatically monochromaticity monochromatism monochromator monochromators monochromats monochrome monochromes monochromic monochromist monochromists monocle monocled monocles monoclinal monocline monoclines monoclinic monoclinous monoclonal monocoque monocoques monocot monocots monocotyledon monocotyledonous monocotyledons monocracies monocracy monocrat monocratic monocrats monocrystal monocrystalline monocrystals monocular monocularly monocultural monoculture monocultures monocycle monocycles monocyclic monocyte monocytes monocytic monocytoid monocytoses monocytosis monodactyl monodactylous monodactyls monodic monodical monodically monodies monodisperse monodist monodists monodrama monodramas monodramatic monody monoecious monoeciously monoecism monoester monoesters monofilament monofilaments monogamic monogamist monogamists monogamous monogamously monogamy monogastric monogenean monogeneans monogenesis monogenetic monogenic monogenically monogenism monogenist monogenistic monogenists monogenous monogerm monoglot monoglots monoglyceride monoglycerides monogram monogramed monograming monogrammatic monogrammed monogrammer monogrammers monogramming monograms monograph monographed monographer monographers monographic monographically monographing monographs monogynist monogynists monogynous monogyny monohull monohulls monohybrid monohybrids monohydrate monohydrated monohydrates monohydric monohydroxy monoicous monolayer monolayers monolingual monolingualism monolinguals monolith monolithic monolithically monoliths monolog monologged monologging monologic monological monologist monologists monologize monologized monologizes monologizing monologs monologue monologued monologues monologuing monologuist monologuists monomania monomaniac monomaniacal monomaniacally monomaniacs monomer monomeric monomers monometallic monometallism monometallist monometallists monometer monometers monomial monomials monomolecular monomolecularly monomorphemic monomorphic monomorphism monomorphous monongahela mononuclear mononucleate mononucleated mononucleosis mononucleotide mononucleotides monopetalous monophagous monophagy monophobia monophobias monophobic monophonic monophonically monophonies monophony monophosphate monophthong monophthongal monophthongs monophyletic monophyletically monophyly monophysite monophysites monophysitic monophysitism monoplane monoplanes monoplegia monoplegias monoplegic monoploid monoploids monopod monopode monopodes monopodia monopodial monopodially monopodium monopods monopole monopoles monopolies monopolism monopolist monopolistic monopolistically monopolists monopolization monopolizations monopolize monopolized monopolizer monopolizers monopolizes monopolizing monopoly monopropellant monopropellants monoprotic monopsonies monopsonist monopsonistic monopsonists monopsony monorail monorails monorchid monorchidism monorchids monorhyme monorhymed monorhymes monos monosaccharide monosaccharides monosepalous monosodium monosome monosomes monosomic monosomy monospecific monospecificity monospermal monospermous monostele monosteles monostelic monostely monostich monostiches monostichous monostome monostomous monostylous monosyllabic monosyllabically monosyllabicity monosyllable monosyllables monosynaptic monosynaptically monoterpene monoterpenes monotheism monotheist monotheistic monotheistical monotheistically monotheists monothematic monotint monotints monotone monotones monotonic monotonically monotonicity monotonies monotonous monotonously monotonousness monotony monotrematous monotreme monotremes monotrichate monotrichic monotrichous monotype monotypes monotypic monounsaturate monounsaturated monounsaturates monovalence monovalency monovalent monovular monoxide monoxides monozygotic monroe monrovia mons monseigneur monsieur monsignor monsignori monsignorial monsignors monsoon monsoonal monsoons monster monsters monstrance monstrances monstrosities monstrosity monstrous monstrously monstrousness montadale montadales montage montaged montages montaging montagnais montagnard montagnards montague montagues montaigne montan montana montanan montanans montane montanism montanist montanists montargis montauk montauks monte montecristo montego monteith monteiths montenegrin montenegrins montenegro monterey montero monteros monterrey montes montesquieu montessori montessorian monteverdi montevideo montezuma montferrat montfort montgolfier montgomery month monthlies monthlong monthly months monticello monticule monticules montmartre montmorency montmorillonite montmorillonites montmorillonitic montparnasse montpelier montpellier montrachet montreal montreux montréal montserrat monument monumental monumentality monumentalize monumentalized monumentalizes monumentalizing monumentally monuments monuron monurons monzonite monzonites monzonitic monégasque monégasques moo mooch mooched moocher moochers mooches mooching mood moodier moodiest moodily moodiness moods moody mooed mooing moola moolah moon moonbeam moonbeams moonblind mooncalf mooncalves moonchild moonchildren moondust mooned mooneye mooneyed mooneyes moonfaced moonfish moonfishes moonflower moonflowers moonie moonier moonies mooniest mooning moonish moonishly moonless moonlet moonlets moonlight moonlighted moonlighter moonlighters moonlighting moonlights moonlike moonlit moonquake moonquakes moonrise moonrises moons moonscape moonscapes moonseed moonseeds moonset moonsets moonshine moonshined moonshiner moonshiners moonshines moonshining moonstone moonstones moonstricken moonstruck moonwalk moonwalked moonwalker moonwalkers moonwalking moonwalks moonward moonwort moonworts moony moor moorage moore moorea moored moorfowl moorfowls moorhen moorhens mooring moorings moorish moorland moorlands moors moos moose moosebird moosebirds moosehead mooser moosewood moosewoods moot mooted mooting mootness moots mop mopboard mopboards mope moped mopeds moper mopers mopes mopey moping mopish mopishly mopped mopper moppers moppet moppets mopping mops moquette moquettes mor mora morae morainal moraine moraines morainic moral morale moralism moralisms moralist moralistic moralistically moralists moralities morality moralization moralizations moralize moralized moralizer moralizers moralizes moralizing morally morals moras morass morasses morassy moratoria moratorium moratoriums moratory moravia moravian moravians moray morays morbid morbidities morbidity morbidly morbidness morbific morbus morceau morceaux mordacious mordaciously mordacity mordancy mordant mordanted mordanting mordantly mordants mordecai mordent mordents mordovia mordvinia more moreen moreens morel morello morellos morels moreover mores moresque moresques morgan morgana morganatic morganatically morganite morganites morgans morgen morgens morgue morgues mori moribund moribundity moribundly morion morions morisco moriscoes moriscos moritz mormon mormonism mormons morn mornay morning mornings morns morny moro moroccan moroccans morocco moroccos moron moronic moronically moronism moronity morons moros morose morosely moroseness morosity morph morphactin morphactins morphallaxes morphallaxis morphean morpheme morphemes morphemic morphemically morphemics morpheus morphia morphias morphine morphing morphinism morphinisms morphinist morphinists morpho morphogen morphogenesis morphogenetic morphogenetically morphogenic morphogens morphologic morphological morphologically morphologies morphologist morphologists morphology morphometric morphometrically morphometry morphophonemic morphophonemics morphos morphoses morphosis morphs morris morrow morrows morse morsel morsels mort mortadella mortadellas mortal mortalities mortality mortally mortals mortar mortarboard mortarboards mortared mortaring mortarless mortars mortem mortems mortgage mortgaged mortgagee mortgagees mortgager mortgagers mortgages mortgaging mortgagor mortgagors mortice morticed mortices mortician morticians morticing mortification mortifications mortified mortifier mortifiers mortifies mortify mortifying mortifyingly mortimer mortis mortise mortised mortises mortising mortmain mortola morton morts mortuaries mortuary morula morulae morular morulation morulations mosaic mosaically mosaicism mosaicisms mosaicist mosaicists mosaicked mosaicking mosaiclike mosaics mosasaur mosasaurs moschatel moschatels moscow moselle moselles moses mosey moseyed moseying moseys mosfet moshav moshavim moslem moslems mosotho mosque mosques mosquito mosquitoes mosquitoey mosquitos moss mossback mossbacked mossbacks mossbunker mossbunkers mossed mosses mossgrown mossier mossiest mossiness mossing mosslike mosso mossy most mostaccioli mostly mot mote motel motels motes motet motets moth mothball mothballed mothballing mothballs mother motherboard motherboards mothered motherfucker motherfuckers motherfucking motherhood motherhouse motherhouses mothering motherings motherland motherlands motherless motherlessness motherliness motherly mothers motherwort motherworts mothier mothiest mothlike mothproof mothproofed mothproofer mothproofers mothproofing mothproofs moths mothy motif motific motifs motile motility motion motional motioned motioning motionless motionlessly motionlessness motions motivate motivated motivates motivating motivation motivational motivationally motivations motivative motivator motivators motive motived motiveless motivelessly motives motivic motiving motivities motivity motley motleys motmot motmots motocross motocrosses motoneuron motoneurons motor motorbike motorbikes motorboat motorboater motorboaters motorboating motorboats motorbus motorbuses motorbusses motorcade motorcaded motorcades motorcading motorcar motorcars motorcycle motorcycled motorcycles motorcycling motorcyclist motorcyclists motordom motored motoric motorically motoring motorist motorists motorization motorizations motorize motorized motorizes motorizing motorless motorman motormen motormouth motormouths motorola motors motortruck motortrucks motorway motorways mots mott motte mottes mottle mottled mottler mottlers mottles mottling motto mottoes mottos motts moue moues moufflon moufflons mouflon mouflons mouillé moujik moujiks moulage moulages moulin moulins mound moundbird moundbirds mounded mounding mounds mount mountable mountain mountaineer mountaineered mountaineering mountaineers mountainous mountainously mountainousness mountains mountainside mountainsides mountaintop mountaintops mountainy mountbatten mountebank mountebanked mountebankery mountebanking mountebanks mounted mounter mounters mountie mounties mounting mountings mounts mounty mourn mourned mourner mourners mournful mournfully mournfulness mourning mourningly mourns mouse moused mouser mousers mouses mousetrap mousetrapped mousetrapping mousetraps mousey mousier mousiest mousily mousiness mousing mousings mousquetaire mousquetaires moussaka mousse moussed mousseline mousselines mousses moussing moustache moustaches moustachio moustachioed moustachios mousterian mousy mouth mouthbreeder mouthbreeders mouthed mouther mouthers mouthful mouthfuls mouthier mouthiest mouthiness mouthing mouthings mouthlike mouthpart mouthparts mouthpiece mouthpieces mouths mouthwash mouthwashes mouthwatering mouthwateringly mouthy mouton moutonnée moutonnéed moutonnées moutons movability movable movableness movables movably move moveable moved moveless movelessly movelessness movement movements mover movers moves movie moviedom moviedoms moviegoer moviegoers moviegoing moviemaker moviemakers moviemaking movies moving movingly moviola moviolas mow mowed mower mowers mowing mown mows moxie moyen mozambican mozambicans mozambique mozarab mozarabic mozarabs mozart mozartian mozartians mozetta mozettas mozo mozos mozzarella mozzetta mozzettas mpg mph mr mri mridanga mridangam mrs ms msg mu much muchacho muchachos muchness muciferous mucilage mucilaginous mucilaginously mucin mucinous mucins muck muckamuck muckamucks mucked mucker muckers muckety muckier muckiest muckily mucking muckluck mucklucks muckrake muckraked muckraker muckrakers muckrakes muckraking mucks muckworm muckworms mucky mucocutaneous mucoid mucoids mucolytic mucopeptide mucopeptides mucopolysaccharide mucopolysaccharides mucoprotein mucoproteins mucopurulent mucosa mucosae mucosal mucosas mucous mucoviscidosis mucro mucronate mucronation mucronations mucrones mucus mud mudbug mudbugs mudded mudder mudders muddied muddier muddies muddiest muddily muddiness mudding muddle muddled muddleheaded muddleheadedly muddleheadedness muddler muddlers muddles muddling muddly muddy muddying mudfish mudfishes mudflat mudflats mudflow mudflows mudguard mudguards mudpack mudpacks mudra mudras mudroom mudrooms muds mudsill mudsills mudskipper mudskippers mudslide mudslides mudslinger mudslingers mudslinging mudstone mudstones mudéjar mudéjares muenster muensters muesli mueslis muezzin muezzins muff muffed muffin muffing muffins muffle muffled muffler mufflered mufflers muffles muffling muffs muffuletta muffulettas mufti muftis mug mugful mugged muggee muggees mugger muggers muggier muggiest mugginess mugging muggings muggy mughal mughals mugho mugo mugs mugwump mugwumpery mugwumps muhammad muhammadan muhammadanism muhammadanisms muhammadans muhammedan muhammedans muharram muharrum mujahedeen mujahedeens mujahedin mujahedins mujahideen mujahideens mujahidin mujahidins mujik mujiks mukluk mukluks muktuk mulatto mulattoes mulattos mulberries mulberry mulch mulched mulches mulching mulct mulcted mulcting mulcts mule mules muleskinner muleskinners muleta muletas muleteer muleteers muley muleys mulhacén muliebrity mulish mulishly mulishness mull mulla mullah mullahism mullahs mullas mulled mullein mulleins mullen mullens muller mullerian mullers mullet mullets mulligan mulligans mulligatawnies mulligatawny mulling mullion mullioned mullions mullite mullites mulls multi multiaddress multiage multiagency multiarmed multiatom multiauthor multiaxial multiband multibank multibarrel multibarreled multibillion multibillionaire multibillionaires multibladed multibranched multibuilding multicampus multicar multicarbon multicausal multicell multicelled multicellular multicellularity multicellulocentric multicenter multichain multichambered multichannel multicharacter multicity multiclient multicoated multicolor multicolored multicolumn multicomponent multiconductor multicopy multicounty multicourse multicultural multiculturalism multicurie multicurrency multidentate multidialectal multidimensional multidimensionality multidirectional multidisciplinary multidiscipline multidivisional multidomain multidrug multielectrode multielement multiemployer multiengine multienzyme multiethnic multifaceted multifactor multifactorial multifactorially multifamily multifarious multifariously multifariousness multifid multifilament multiflash multiflora multiflorous multifocal multifoil multifoils multifold multiform multiformity multifrequency multifunction multifunctional multigenerational multigenic multigerm multigrade multigrain multigravida multigravidas multigrid multigrooved multigroup multihandicapped multiheaded multihospital multihued multihull multilane multilateral multilateralism multilateralist multilateralists multilaterally multilayer multilayered multilevel multileveled multiline multilingual multilingualism multilingually multilobed multilocular multimanned multimedia multimegaton multimegawatt multimember multimetallic multimillennial multimillion multimillionaire multimillionaires multimodal multimode multimolecular multination multinational multinationalism multinationals multinomial multinomials multinuclear multinucleate multinucleated multiorgasmic multipack multipacks multipage multipaned multipara multiparae multiparameter multiparas multiparity multiparous multipart multiparticle multipartite multiparty multipath multiped multipede multiphase multiphasic multiphoton multipicture multipiece multipion multipiston multiplant multiplayer multiple multiples multiplet multiplets multiplex multiplexed multiplexer multiplexers multiplexes multiplexing multiplexor multiplexors multipliable multiplicable multiplicand multiplicands multiplicate multiplication multiplicational multiplications multiplicative multiplicatively multiplicities multiplicity multiplied multiplier multipliers multiplies multiply multiplying multipoint multipolar multipolarity multipole multiport multipotential multipower multiproblem multiprocessing multiprocessor multiprocessors multiproduct multiprogramming multipronged multipurpose multiracial multiracialism multiracialisms multirange multiregional multireligious multiroom multiscreen multisense multisensory multiservice multisided multisite multisize multiskilled multisource multispecies multispectral multispeed multisport multisports multistage multistate multistemmed multistep multistoried multistory multistranded multisyllabic multisystem multitalented multitask multitasked multitasking multitasks multiterminal multithreaded multitiered multiton multitone multitowered multitrack multitracked multitracking multitrillion multitude multitudes multitudinous multitudinously multitudinousness multiunion multiunit multiuse multiuser multivalence multivalent multivariable multivariate multiversities multiversity multivitamin multivitamins multivoltine multivolume multiwall multiwarhead multiwavelength multiword multiyear multnomah multure multures mum mumble mumbled mumbler mumblers mumbles mumblety mumbling mumbly mumbo mummed mummer mummeries mummers mummery mummichog mummichogs mummies mummification mummifications mummified mummifies mummify mummifying mumming mummy mump mumped mumps mums munch munchausen munched muncher munchers munches munchhausen munchies munching munchkin munchkins munda mundane mundanely mundaneness mundanity mundungus mung mungo mungos muni munich municipal municipalities municipality municipalization municipalizations municipalize municipalized municipalizes municipalizing municipally municipals munificence munificent munificently muniment muniments munis munition munitioned munitioning munitions munsee munsees munster munsters muntin muntins muntjac muntjacs muntjak muntjaks muon muonic muonium muons muppie muppies mural muraled muralist muralists muralled murals muramic murat murchison murder murdered murderee murderees murderer murderers murderess murderesses murdering murderous murderously murderousness murders murein mureins murex murexes muriate muriates muriatic muricate muricated murices murid murids murine murines murk murkier murkiest murkily murkiness murks murky murmansk murmur murmured murmurer murmurers murmuring murmuringly murmurous murmurously murmurs murphies murphy murrain murrains murray murre murres murrey murreys murrumbidgee murther murthered murthering murthers musca muscadet muscadets muscadine muscadines muscae muscarine muscarines muscarinic muscat muscatel muscatels muscats muscid muscids muscle musclebound muscled muscleman musclemen muscles muscling muscly muscovite muscovites muscovy muscular muscularity muscularly musculature musculoskeletal muse mused museological museologically museologist museologists museology muser musers muses musette musettes museum museumgoer museumgoers museums mush mushed musher mushers mushes mushier mushiest mushily mushiness mushing mushroom mushroomed mushrooming mushrooms mushy music musical musicale musicales musicality musicalization musicalizations musicalize musicalized musicalizes musicalizing musically musicals musician musicianly musicians musicianship musicological musicologically musicologist musicologists musicology musing musingly musings musique musk muskeg muskegs muskellunge muskellunges muskelunge muskelunges musket musketeer musketeers musketry muskets muskhogean muskhogeans muskie muskier muskies muskiest muskiness muskingum muskmelon muskmelons muskogean muskogeans muskogee muskogees muskox muskoxen muskrat muskrats muskroot muskroots musky muslim muslims muslin muslins musquash musquashes musquashs muss mussalman mussed mussel mussels musses mussier mussiest mussily mussiness mussing mussolini mussorgsky mussulman mussulmans mussulmen mussy must mustache mustached mustaches mustachio mustachioed mustachios mustang mustangs mustard mustards mustardy musteline muster mustered mustering musters musth musths mustier mustiest mustily mustiness mustn mustn't musts musty mutability mutable mutableness mutably mutagen mutageneses mutagenesis mutagenic mutagenically mutagenicity mutagenize mutagenized mutagenizes mutagenizing mutagens mutandis mutant mutants mutase mutases mutate mutated mutates mutating mutation mutational mutationally mutations mutatis mutative mutchkin mutchkins mute muted mutedly mutely muteness muter mutes mutest mutilate mutilated mutilates mutilating mutilation mutilations mutilative mutilator mutilators mutine mutined mutineer mutineers mutines muting mutinied mutinies mutining mutinous mutinously mutinousness mutiny mutinying mutism mutisms muton mutons mutt mutter muttered mutterer mutterers muttering mutterings mutters mutton muttonchops muttonfish muttonfishes muttonhead muttonheaded muttonheads muttons muttony mutts mutual mutualism mutualisms mutualist mutualistic mutualists mutuality mutualization mutualizations mutualize mutualized mutualizes mutualizing mutually mutuals mutuel mutuels muumuu muumuus muzak muzhik muzhiks muzjik muzjiks muztag muztagata muztagh muzzier muzziest muzzily muzziness muzzle muzzled muzzleloader muzzleloaders muzzleloading muzzler muzzlers muzzles muzzling muzzy mv my myalgia myalgic myanmar myasthenia myasthenic myc mycelia mycelial mycelium mycenae mycenaean mycenaeans mycenian mycenians mycetoma mycetomas mycetomata mycetomatous mycetophagous mycetozoan mycetozoans mycobacteria mycobacterial mycobacterium mycoflora mycologic mycological mycologically mycologies mycologist mycologists mycology mycophagist mycophagists mycophagous mycophagy mycophile mycophiles mycoplasma mycoplasmal mycoplasmas mycorhiza mycorrhiza mycorrhizae mycorrhizal mycorrhizas mycoses mycosis mycotic mycotoxicoses mycotoxicosis mycotoxin mycotoxins mycs mydriasis mydriatic mydriatics myelencephalic myelencephalon myelencephalons myelin myelinated myelination myelinations myeline myelines myelinic myelinization myelinizations myelinize myelinized myelinizes myelinizing myelins myelitis myeloblast myeloblastic myeloblasts myelocyte myelocytes myelocytic myelofibroses myelofibrosis myelofibrotic myelogenic myelogenous myelogram myelograms myelography myeloid myeloma myelomas myelomata myelomatoid myelomatous myelopathic myelopathy myeloproliferative myiases myiasis mykonos mylar mylonite mylonites myna mynah mynahs mynas mynheer mynheers myoblast myoblasts myocardia myocardial myocarditis myocarditises myocardium myoclonic myoclonus myoclonuses myoelectric myoelectrical myofibril myofibrillar myofibrils myofilament myofilaments myogenetic myogenic myoglobin myoglobins myograph myographs myoinositol myoinositols myologic myologist myologists myology myoma myomas myomata myomatous myoneural myopathic myopathies myopathy myope myopes myopia myopic myopically myosin myosis myositis myositises myosotis myosotises myotic myotome myotomes myotonia myotonias myotonic myriad myriads myriapod myriapodous myriapods myriopod myriopods myristic myrmecological myrmecologist myrmecologists myrmecology myrmecophile myrmecophiles myrmecophilous myrmecophily myrmidon myrmidons myrobalan myrobalans myrrh myrtle myself mysia mysian mysians mysid mysids mysophobia mysophobias mysore mystagogic mystagogue mystagogues mystagogy mysteries mysterious mysteriously mysteriousness mystery mystic mystical mystically mysticalness mysticete mysticetes mysticetous mysticism mystics mystification mystified mystifier mystifiers mystifies mystify mystifying mystifyingly mystique mystiques myth mythic mythical mythically mythicize mythicized mythicizer mythicizers mythicizes mythicizing mythmaker mythmakers mythmaking mythographer mythographers mythographies mythography mythoi mythologer mythologers mythologic mythological mythologically mythologies mythologist mythologists mythologize mythologized mythologizer mythologizers mythologizes mythologizing mythology mythomania mythomaniac mythomanias mythopeic mythopoeia mythopoeic mythopoesis mythopoetic mythopoetical mythos myths mythy myxameba myxamoeba myxamoebae myxamoebas myxedema myxedemas myxedematous myxedemic myxobacteria myxobacterium myxoedema myxoedemas myxoid myxoma myxomas myxomata myxomatoses myxomatosis myxomatous myxomycete myxomycetes myxoviral myxovirus myxoviruses málaga mâche mâches mâché mâcon mälaren märchen médaillon médaillons médoc mélange mélanges ménage ménages ménière mérida mérite mésalliance mésalliances métier métiers métis mêlée mêlées même míkonos mílos möbius mössbauer müller müllerian münster n n'djamena n'gana n'ganas naan nab nabataea nabataean nabataeans nabatean nabateans nabbed nabber nabbers nabbing nabe nabes nabob nabobs nabokov naboth nabs nacelle nacelles nacho nachos nacre nacred nacreous nacres nada nadir nadirs nadu naff naffed naffing naffs nag naga nagaland nagana naganas nagar nagas nagasaki nagged nagger naggers nagging naggingly nags nah nahuatl nahuatlan nahuatls nahum naiad naiades naiads naif naifs nail nailbrush nailbrushes nailed nailer nailers nailing nails nainsook naipaul naira nairas nairobi naive naively naiveness naiveties naivety naiveté naked nakedly nakedness naled naleds nalidixic nalorphine nalorphines naloxone naloxones naltrexone naltrexones nam nama namable namaland namaqualand namas namaycush namaycushes namby name nameable named nameless namelessly namelessness namely nameplate nameplates namer namers names namesake namesakes nametag nametags nametape nametapes namib namibia namibian namibians naming nan nana nanak nanas nance nances nancy nandina nanism nanisms nankeen nankeens nankin nanking nankins nannie nannies nannofossil nannofossils nannoplankton nannoplanktons nanny nannyberries nannyberry nannyish nanoampere nanoamperes nanobecquerel nanobecquerels nanocandela nanocandelas nanocoulomb nanocoulombs nanoengineering nanofarad nanofarads nanofossil nanofossils nanogram nanograms nanohenries nanohenry nanohenrys nanohertz nanojoule nanojoules nanokelvin nanokelvins nanolumen nanolumens nanolux nanometer nanometers nanomole nanomoles nanonewton nanonewtons nanoohm nanoohms nanopascal nanopascals nanoplankton nanoplanktons nanoradian nanoradians nanosecond nanoseconds nanosiemens nanosievert nanosieverts nanosteradian nanosteradians nanotechnology nanotesla nanoteslas nanovolt nanovolts nanowatt nanowatts nanoweber nanowebers nansen nanterre nantes nanticoke nanticokes nantua nantucket nantucketer nantucketers naoise naomi nap napa napalm napalmed napalming napalms napas nape naperies naperville napery napes naphtali naphtha naphthalene naphthalenes naphthalenic naphthalin naphthaline naphthalines naphthalins naphthas naphthene naphthenes naphthenic naphthol naphthols naphthous naphthylamine naphthylamines naphtol naphtols napier napierian napiform napkin napkins naples napless napoleon napoleonic napoleons napoli napoléon nappa nappas nappe napped nappes nappier nappies nappiest napping nappy naprapath naprapathies naprapaths naprapathy naproxen naproxens naps naptime naptimes narbonne narc narceine narceines narcism narcisms narcissi narcissism narcissisms narcissist narcissistic narcissistically narcissists narcissus narcissuses narco narcoanalyses narcoanalysis narcoanalytic narcodollar narcodollars narcokleptocracies narcokleptocracy narcolepsies narcolepsy narcoleptic narcoma narcomas narcomata narcos narcoses narcosis narcosyntheses narcosynthesis narcotic narcotically narcotics narcotism narcotisms narcotization narcotizations narcotize narcotized narcotizes narcotizing narcs nard nards nares narghile narghiles nargileh nargilehs narial naris nark narked narking narks narraganset narragansets narragansett narragansetts narratability narratable narrate narrated narrater narraters narrates narrating narration narrational narrationally narrations narrative narratively narratives narratological narratologist narratologists narratology narrator narrators narrow narrowback narrowbacks narrowband narrowcast narrowcaster narrowcasters narrowcasting narrowcasts narrowed narrower narrowest narrowing narrowish narrowly narrowness narrows narthex narthexes narváez narwal narwals narwhal narwhale narwhales narwhals nary nasal nasality nasalization nasalizations nasalize nasalized nasalizes nasalizing nasally nasals nascence nascency nascent naseberries naseberry naseby nashville nasion nasions naskapi naskapis nasofrontal nasogastric nasopharyngeal nasopharynges nasopharynx nasopharynxes nassau nastic nastier nasties nastiest nastily nastiness nasturtium nasturtiums nasty natal natalities natality natant natation natations natatorial natatorium natatory natch natchez nates nathan nathanael natheless nathless natick naticks nation national nationalism nationalist nationalistic nationalistically nationalists nationalities nationality nationalization nationalizations nationalize nationalized nationalizer nationalizers nationalizes nationalizing nationally nationals nationhood nationless nations nationwide native natively nativeness natives nativism nativisms nativist nativistic nativists nativities nativity nato natriureses natriuresis natriuretic natrolite natrolites natron natrons natter nattered nattering natters nattier nattiest nattily nattiness natty naturae natural naturalism naturalist naturalistic naturalistically naturalists naturalizable naturalization naturalizations naturalize naturalized naturalizes naturalizing naturally naturalness naturals nature natured naturedly naturedness naturel natures naturism naturist naturists naturopath naturopathic naturopathies naturopaths naturopathy naugahyde naught naughtier naughties naughtiest naughtily naughtiness naughts naughty naumachia naumachiae naumachias nauplial nauplii nauplius nauru nauruan nauruans nausea nauseam nauseant nauseants nauseate nauseated nauseates nauseating nauseatingly nauseation nauseations nauseous nauseously nauseousness nausicaa nautch nautical nautically nautili nautiloid nautiloids nautilus nautiluses navaho navahos navaid navaids navajo navajos naval navarre nave navel navels navelwort navelworts naves navicular naviculars navies navigability navigable navigableness navigably navigate navigated navigates navigating navigation navigational navigationally navigations navigator navigators navvies navvy navy nawab nawabs naxos nay nays naysaid naysay naysayer naysayers naysaying naysays nazarene nazarenes nazareth nazarite nazarites naze nazi nazification nazifications nazify naziism nazirite nazirites naziritism nazis nazism naïf naïfs naïve naïvely naïver naïvest naïvety naïveté naïvetés nco ncos ncr ndebele ndebeles ndjamena ndongo ndongos ne ne'er neandertal neanderthal neanderthaloid neanderthals neanthropic neap neapolitan neapolitans neaps near nearby nearctic neared nearer nearest nearing nearly nearness nears nearshore nearside nearsighted nearsightedly nearsightedness neat neaten neatened neatening neatens neater neatest neath neatherd neatly neatness neats neb nebbish nebbishes nebbishy nebenkern nebenkerns nebraska nebraskan nebraskans nebs nebuchadnezzar nebuchadnezzars nebula nebulae nebular nebulas nebulization nebulizations nebulize nebulized nebulizer nebulizers nebulizes nebulizing nebulosities nebulosity nebulous nebulously nebulousness necessaries necessarily necessary necessitarian necessitarianism necessitarians necessitate necessitated necessitates necessitating necessitation necessitations necessitative necessities necessitous necessitously necessitousness necessity neck neckband neckbands necked neckerchief neckerchiefs neckerchieves necking neckings necklace necklaces neckless neckline necklines neckpiece neckpieces necks necktie neckties neckwear necrobiosis necrobiotic necrologic necrological necrologies necrologist necrologists necrology necromancer necromancers necromancy necromantic necromantically necrophagia necrophagias necrophagous necrophile necrophiles necrophilia necrophiliac necrophiliacs necrophilic necrophilism necrophobia necrophobias necrophobic necropoleis necropolis necropolises necropsied necropsies necropsing necropsy necrose necrosed necroses necrosing necrosis necrotic necrotize necrotized necrotizes necrotizing necrotomies necrotomy nectar nectarial nectaries nectarine nectarines nectarous nectars nectary nee need needed needful needfully needfulness needier neediest neediness needing needle needlecraft needlecrafts needled needlefish needlefishes needlelike needlepoint needlepointed needlepointing needlepoints needler needlers needles needless needlessly needlessness needlewoman needlewomen needlework needleworker needleworkers needling needn needn't needs needy neem neems nefarious nefariously nefariousness nefertiti nefyn negate negated negater negaters negates negating negation negational negations negative negatived negatively negativeness negatives negativing negativism negativist negativistic negativists negativity negator negators negatory negatron negatrons negev neglect neglected neglecter neglecters neglectful neglectfully neglectfulness neglecting neglects negligee negligees negligence negligent negligently negligibility negligible negligibleness negligibly negligé negligée negligées negligés negotiability negotiable negotiably negotiant negotiants negotiate negotiated negotiates negotiating negotiation negotiations negotiator negotiators negotiatory negress negresses negrillo negrilloes negrillos negrito negritoes negritos negritude negro negroes negroid negroids negroness negrophile negrophiles negrophilism negrophobe negrophobes negrophobia negros negus neguses nehemiah nehemias nehru neigh neighbor neighbored neighborhood neighborhoods neighboring neighborliness neighborly neighbors neighed neighing neighs neither nekton nektonic nektons nellie nellies nelly nellyism nelson nelsons nem nematic nematicidal nematicide nematicides nematocidal nematocide nematocides nematocyst nematocystic nematocysts nematode nematodes nematological nematologist nematologists nematology nembutal nemean nemeans nemertean nemerteans nemertine nemertines nemeses nemesis nemophila nemophilas nene nenes nenets nennius neo neoarsphenamine neoarsphenamines neoclassic neoclassical neoclassicism neoclassicist neoclassicists neocolonial neocolonialism neocolonialist neocolonialists neocon neocons neoconservatism neoconservative neoconservatives neocortex neocortexes neocortical neocortices neodymium neofascism neofascist neofascists neogaea neogaean neogaeas neogea neogeas neogenesis neogenetic neoimpressionism neoimpressionist neoimpressionists neoliberal neoliberalism neoliberals neolith neolithic neoliths neological neologically neologies neologism neologisms neologist neologistic neologistical neologists neologize neologized neologizes neologizing neology neomycin neon neonatal neonatally neonate neonates neonatologist neonatologists neonatology neoned neoorthodox neoorthodoxy neopallia neopallium neopalliums neophilia neophiliac neophiliacs neophyte neophytes neoplasia neoplasias neoplasm neoplasms neoplastic neoplasticism neoplasticist neoplasticists neoplatonic neoplatonism neoplatonist neoplatonists neoprene neoptolemus neorealism neorealist neorealistic neorealists neorican neoricans neostigmine neostigmines neotenic neotenies neotenous neoteny neoteric neoterics neotropic neotropical neotropics neotype neotypes nepal nepalese nepali nepalis nepenthe nepenthean nepenthes nepheline nephelines nephelinic nephelinite nephelinites nephelinitic nephelite nephelites nephelometer nephelometers nephelometric nephelometrically nephelometry nephew nephews nephological nephology nephoscope nephoscopes nephrectomies nephrectomize nephrectomized nephrectomizes nephrectomizing nephrectomy nephric nephridia nephridial nephridium nephrite nephrites nephritic nephritides nephritis nephritises nephrogenic nephrogenous nephrologist nephrologists nephrology nephron nephrons nephropathic nephropathies nephropathy nephroses nephrosis nephrostome nephrostomes nephrotic nephrotomies nephrotomy nephrotoxic nephrotoxicity nepotism nepotist nepotistic nepotistical nepotists neptune neptunian neptunium neral nerals nerd nerdish nerds nerdy nereid nereides nereids nereis nereus neritic nero nerol neroli nerols neronian nerts nervate nervation nervations nerve nerved nerveless nervelessly nervelessness nerves nervier nerviest nervily nerviness nerving nervosa nervosity nervous nervously nervousness nervure nervures nervy nescience nesciences nescient nescients ness nesselrode nesselrodes nesses nessus nest nested nester nesters nesting nestle nestled nestler nestlers nestles nestling nestlings nestor nestorian nestorianism nestorians nestorius nestors nests net netback netbacks nether netherlander netherlanders netherlandish netherlands nethermost netherworld netherworldly netherworlds netkeeper netkeepers netless netlike netminder netminders nets netsuke netsukes netted netter netters netting nettle nettled nettles nettlesome nettling netty network networked networker networkers networking networkings networks netzahualcóyotl neuchâtel neufchâtel neum neumatic neume neumes neums neural neuralgia neuralgic neurally neuraminidase neuraminidases neurasthenia neurasthenic neurasthenically neurasthenics neurectomies neurectomy neurilemma neurilemmal neurilemmas neuristor neuristors neuritic neuritis neuroanatomical neuroanatomies neuroanatomist neuroanatomists neuroanatomy neurobiological neurobiologist neurobiologists neurobiology neuroblast neuroblastoma neuroblastomas neuroblastomata neuroblasts neurochemical neurochemist neurochemistry neurochemists neuroendocrine neuroendocrinological neuroendocrinologist neuroendocrinologists neuroendocrinology neurofibril neurofibrillary neurofibrils neurofibroma neurofibromas neurofibromata neurofibromatoses neurofibromatosis neurofilament neurofilamentous neurofilaments neurogeneses neurogenesis neurogenetics neurogenic neurogenically neuroglia neuroglial neurohormonal neurohormone neurohormones neurohypophyseal neurohypophyses neurohypophysial neurohypophysis neuroimaging neuroleptic neuroleptics neurologic neurological neurologically neurologist neurologists neurology neuroma neuromas neuromata neuromuscular neuron neuronal neurone neurones neuronic neuronically neurons neuropath neuropathic neuropathically neuropathies neuropathologic neuropathological neuropathologist neuropathologists neuropathology neuropaths neuropathy neuropharmacological neuropharmacologist neuropharmacologists neuropharmacology neurophysiologic neurophysiological neurophysiologist neurophysiologists neurophysiology neuropsychiatric neuropsychiatrist neuropsychiatrists neuropsychiatry neuropsychological neuropsychologist neuropsychologists neuropsychology neuropteran neuropterans neuropterous neuroradiological neuroradiologist neuroradiologists neuroradiology neuroscience neuroscientific neuroscientist neuroscientists neurosecretion neurosecretions neurosecretory neurosensory neuroses neurosis neurospora neurosurgeon neurosurgeons neurosurgeries neurosurgery neurosurgical neurotic neurotically neuroticism neurotics neurotomies neurotomy neurotoxic neurotoxicity neurotoxin neurotoxins neurotransmission neurotransmissions neurotransmitter neurotransmitters neurotropic neurotropism neurula neurulae neurulas neurulation neurulations neustadt neuston neustons neustria neustrian neustrians neuter neutered neutering neuters neutral neutralism neutralist neutralistic neutralists neutrality neutralization neutralizations neutralize neutralized neutralizer neutralizers neutralizes neutralizing neutrally neutralness neutrals neutrino neutrinoless neutrinos neutron neutronic neutrons neutrophil neutrophile neutrophilic neutrophils nevada nevadan nevadans nevadian nevadians never neverland nevermore nevertheless nevi neville nevilles nevis nevoid nevus new newark newborn newborns newburg newburgh newcastle newcomen newcomer newcomers newel newels newer newest newfangled newfangledness newfound newfoundland newfoundlander newfoundlanders newie newies newish newly newlywed newlyweds newmarket newmarkets newness newport news newsagent newsagents newsboy newsboys newsbreak newsbreaks newscast newscaster newscasters newscasts newsdealer newsdealers newsgathering newsgatherings newsgirl newsgirls newsgroup newsgroups newshound newshounds newsier newsiest newsiness newsless newsletter newsletters newsmagazine newsmagazines newsmaker newsmakers newsman newsmen newsmonger newsmongers newspaper newspapering newspaperings newspaperman newspapermen newspapers newspaperwoman newspaperwomen newspeak newspeople newsperson newspersons newsprint newsreader newsreaders newsreel newsreels newsroom newsrooms newsstand newsstands newsweeklies newsweekly newswire newswires newswoman newswomen newsworthier newsworthiest newsworthiness newsworthy newswriting newsy newt newton newtonian newtons newts next nexus nexuses nez ngorongoro ngultrum ngultrums nguni ngunis ngwee niacin niacinamide niagara nialamide niamey nib nibble nibbled nibbler nibblers nibbles nibbling nibelung nibelungen nibelungenlied nibelungs niblick niblicks nibs nicad nicads nicaea nicaragua nicaraguan nicaraguans niccolite niccolites nice nicely nicene niceness nicer nicest niceties nicety niche niched niches niching nicholas nichrome nick nicked nickel nickeled nickelic nickeliferous nickeling nickelled nickelling nickelodeon nickelodeons nickelous nickels nicker nickered nickering nickers nicking nickle nickles nicknack nicknacks nickname nicknamed nicknamer nicknamers nicknames nicknaming nicks nicobar nicodemus nicomedia nicosia nicotiana nicotianas nicotinamide nicotine nicotinic nicotinism nictate nictated nictates nictating nictitate nictitated nictitates nictitating nictitation nictitations nidate nidated nidates nidating nidation nidations niddering nidderings nide nides nidi nidicolous nidificate nidificated nidificates nidificating nidification nidifications nidified nidifies nidifugous nidify nidifying nidus niduses niece nieces nielli niellist niellists niello nielloed nielloing niellos nielsbohrium niente nietzsche nietzschean nietzscheans nifedipine nifedipines niflheim niftier nifties niftiest niftily niftiness nifty nigella nigellas niger nigeria nigerian nigerians niggard niggardliness niggardly niggards nigger niggers niggle niggled niggler nigglers niggles niggling nigglingly nigglings nigh nighed nigher nighest nighing nighs night nightcap nightcaps nightclothes nightclub nightclubber nightclubbers nightclubby nightclubs nightdress nightdresses nighter nighters nightfall nightglow nightglows nightgown nightgowns nighthawk nighthawks nightie nighties nightingale nightingales nightjar nightjars nightless nightlife nightlong nightly nightmare nightmares nightmarish nightmarishly nightmarishness nightrider nightriders nights nightscape nightscapes nightscope nightscopes nightshade nightshades nightshirt nightshirts nightside nightsides nightspot nightspots nightstand nightstands nightstick nightsticks nighttime nightwalker nightwalkers nightwear nighty nigra nigrae nigrescence nigrescences nigrescent nigrosine nigrosines nihil nihilism nihilist nihilistic nihilistically nihilists nihilities nihility niihau nijinsky nike nikkei nil nile niles nilgai nilgais nill nilled nilling nills nilly nilotic nilpotency nilpotent nilpotents nim nimbi nimble nimbleness nimbler nimblest nimbly nimbostrati nimbostratus nimbus nimbuses nimes nimieties nimiety niminy nimmed nimming nimrod nimrods nims nincompoop nincompoopery nincompoops nine ninebark ninebarks ninefold ninepin ninepins niner niners nines nineteen nineteenfold nineteens nineteenth nineteenths nineties ninetieth ninetieths ninety ninetyfold nineveh ninhydrin ninhydrins ninja ninjas ninnies ninny ninnyhammer ninnyhammers ninon ninons ninth ninthly ninths niobate niobates niobe niobite niobites niobium nip nipa nipas niping nipped nipper nippers nippier nippiest nippily nippiness nipping nippingly nipple nippled nipples nipplewort nippleworts nippon nipponese nippy nips nirvana nirvanas nirvanic nisan nisei niseis nisi nissan nissans nissen nisus nit niter niterie niteries niters nitery nitid nitinol nitpick nitpicked nitpicker nitpickers nitpicking nitpickings nitpicks nitpicky nitrate nitrated nitrates nitrating nitration nitrations nitrator nitrators nitric nitride nitrided nitrides nitriding nitrifiable nitrification nitrifications nitrified nitrifier nitrifiers nitrifies nitrify nitrifying nitril nitrile nitriles nitrils nitrite nitrites nitro nitrobacteria nitrobacterium nitrobenzene nitrocellulose nitrocellulosic nitrochloroform nitrochloroforms nitrofuran nitrofurans nitrofurantoin nitrofurantoins nitrogen nitrogenase nitrogenases nitrogenize nitrogenized nitrogenizes nitrogenizing nitrogenous nitroglycerin nitroglycerine nitrohydrochloric nitromethane nitromethanes nitroparaffin nitroparaffins nitroreductase nitros nitrosamine nitrosamines nitrostarch nitrostarches nitrous nits nitty nitwit nitwits nitwitted niue nival niveous nivernais nix nixed nixes nixie nixies nixing nixy nizam nizamate nizams niño niños no noachian noachic noachical noah noah's nob nobbier nobbiest nobble nobbled nobbler nobblers nobbles nobbling nobby nobel nobelist nobelists nobelium nobiliary nobilities nobility noble nobleman noblemen nobleness nobler nobles noblesse noblest noblewoman noblewomen nobly nobodies nobody nobs nocent nociceptive nociceptor nociceptors nock nocked nocking nocks noctambulation noctambulations noctambulism noctambulisms noctambulist noctambulists noctiluca noctilucas noctilucent noctuid noctuids noctule noctules nocturn nocturnal nocturnally nocturne nocturnes nocturns nocuous nocuously nod nodal nodality nodally nodded nodder nodders noddies nodding noddle noddles noddy node nodes nodi nodose nodosity nods nodular nodulation nodulations nodule nodules nodulose nodulous nodus noel noels noes noesis noetic nog noggin nogging noggins nogs noh nohow noil noils noir noire noires noirish noise noised noiseless noiselessly noiselessness noisemaker noisemakers noisemaking noises noisette noisettes noisier noisiest noisily noisiness noising noisome noisomely noisomeness noisy nolens nolle nolo nolos nom noma nomad nomadic nomadically nomadism nomads nomarchies nomarchy nomas nombril nombrils nome nomen nomenclator nomenclatorial nomenclators nomenclatural nomenclature nomenclatures nomenklatura nomenklaturas nomes nomina nominal nominalism nominalist nominalistic nominalists nominalization nominalize nominalized nominalizes nominalizing nominally nominals nominate nominated nominates nominating nomination nominations nominative nominatives nominator nominators nominee nominees nomogram nomograms nomograph nomographic nomographs nomography nomologic nomological nomologically nomologist nomologists nomology nomothetic nomothetical nomothetically noms non nonabrasive nonabsorbable nonabsorbent nonabsorptive nonabstract nonacademic nonacceptance nonaccountable nonaccredited nonaccrual nonachievement nonacid nonacidic nonacquisitive nonacting nonaction nonactivated nonactor nonadaptive nonaddict nonaddictive nonadditive nonadditivity nonadhesive nonadiabatic nonadjacent nonadjustable nonadmirer nonadmission nonaesthetic nonaffiliated nonaffluent nonage nonagenarian nonagenarians nonages nonaggression nonaggressive nonagon nonagons nonagricultural nonalcoholic nonalcoholics nonaligned nonalignment nonallelic nonallergenic nonallergic nonalphabetic nonaluminum nonambiguous nonanalytic nonanatomic nonanimal nonanoic nonanswer nonantagonistic nonanthropological nonanthropologist nonantibiotic nonantigenic nonappearance nonappearances nonaquatic nonaqueous nonarable nonarbitrariness nonarbitrary nonarchitect nonarchitecture nonargument nonaristocratic nonaromatic nonart nonartist nonartistic nonary nonascetic nonaspirin nonassertive nonassessable nonassociated nonastronomical nonathlete nonathletic nonatomic nonattached nonattachment nonattendance nonattender nonauditory nonauthor nonauthoritarian nonautomated nonautomatic nonautomotive nonautonomous nonavailability nonbacterial nonbank nonbanking nonbarbiturate nonbaryonic nonbasic nonbearing nonbehavioral nonbeing nonbeings nonbelief nonbeliever nonbelievers nonbelligerency nonbelligerent nonbelligerents nonbetting nonbibliographic nonbinary nonbinding nonbiodegradable nonbiographical nonbiological nonbiologically nonbiologist nonbiting nonblack nonblacks nonblank nonbody nonbonded nonbonding nonbook nonbooks nonbotanist nonbrand nonbreakable nonbreathing nonbreeder nonbreeding nonbroadcast nonbuilding nonburnable nonbusiness nonbuying noncabinet noncaking noncallable noncaloric noncampus noncancelable noncancerous noncandidacy noncandidate noncandidates noncannibalistic noncapital noncapitalist noncarcinogen noncarcinogenic noncardiac noncareer noncarrier noncash noncasual noncausal nonce noncelebration noncelebrity noncellular noncellulosic noncentral noncertificated noncertified nonchalance nonchalant nonchalantly noncharacter noncharismatic nonchauvinist nonchemical nonchromosomal nonchronological nonchurch nonchurchgoer noncircular noncirculating noncitizen noncitizens nonclandestine nonclass nonclassical nonclassified nonclassroom nonclearing nonclerical noncling nonclinical nonclogging noncoercive noncognitive noncoherent noncoincidence noncoital noncoking noncola noncollector noncollege noncollegiate noncollinear noncolor noncolored noncolorfast noncom noncombat noncombatant noncombatants noncombative noncombustible noncommercial noncommissioned noncommitment noncommittal noncommittally noncommitted noncommunicating noncommunication noncommunicative noncommunist noncommunists noncommunity noncommutative noncommutativity noncomparability noncomparable noncompatible noncompetition noncompetitive noncompetitor noncomplementary noncomplex noncompliance noncompliances noncompliant noncompliants noncomplicated noncomplying noncomposer noncompound noncomprehension noncompressible noncompulsory noncomputer noncomputerized noncoms nonconceptual nonconcern nonconclusion nonconcur nonconcured nonconcuring nonconcurrence nonconcurrent nonconcurring nonconcurs noncondensable nonconditioned nonconducting nonconduction nonconductive nonconductor nonconductors nonconference nonconfidence nonconfidential nonconflicting nonconform nonconformance nonconformances nonconformed nonconformer nonconformers nonconforming nonconformism nonconformist nonconformists nonconformity nonconforms nonconfrontation nonconfrontational noncongruent nonconjugated nonconnection nonconscious nonconsecutive nonconsensual nonconservation nonconservative nonconsolidated nonconstant nonconstitutional nonconstruction nonconstructive nonconsumer nonconsuming nonconsumption nonconsumptive noncontact noncontagious noncontemporary noncontiguous noncontingent noncontinuous noncontract noncontractual noncontradiction noncontradictory noncontributing noncontributory noncontrollable noncontrolled noncontrolling noncontroversial nonconventional nonconvertible noncooperation noncooperationist noncooperationists noncooperations noncooperative noncooperator noncooperators noncoplanar noncorporate noncorrelation noncorrodible noncorroding noncorrosive noncountry noncounty noncoverage noncreative noncreativity noncredentialed noncredit noncrime noncriminal noncrisis noncritical noncrossover noncrushable noncrystalline nonculinary noncultivated noncultivation noncultural noncumulative noncurrent noncustodial noncustomer noncyclic noncyclical nondairy nondance nondancer nondeceptive nondecision nondecreasing nondeductibility nondeductible nondeductive nondefense nondeferrable nondeforming nondegenerate nondegradable nondegree nondelegate nondeliberate nondelinquent nondelivery nondemanding nondemocratic nondenominational nondenominationalism nondepartmental nondependent nondepletable nondepleting nondeposition nondepressed nonderivative nondescript nondescriptive nondescriptly nondescripts nondesert nondestructive nondestructively nondestructiveness nondetachable nondeterministic nondevelopment nondeviant nondiabetic nondialyzable nondiapausing nondidactic nondiffusible nondimensional nondiplomatic nondirected nondirectional nondirective nondisabled nondisclosure nondisclosures nondiscount nondiscretionary nondiscrimination nondiscriminatory nondiscursive nondisjunction nondisjunctional nondisjunctions nondispersive nondisruptive nondistinctive nondiversified nondividing nondoctor nondoctrinaire nondocumentary nondogmatic nondollar nondomestic nondominant nondormant nondramatic nondrinker nondrinkers nondrinking nondriver nondrug nondrying nondurable nondurables none nonearning nonecclesiastical noneconomic noneconomist nonedible noneditorial noneducation noneducational noneffective nonego nonelastic nonelected nonelection nonelective nonelectric nonelectrical nonelectrolyte nonelectrolytes nonelectronic nonelementary nonelite nonemergency nonemotional nonemphatic nonempirical nonemployee nonemployment nonempty nonencapsulated nonending nonenergy nonenforceability nonenforcement nonengagement nonengineering nonentertainment nonentities nonentity nonenzymatic nonenzymic nonequilibrium nonequivalence nonequivalent nonerotic nones nonessential nonessentials nonestablished nonestablishment nonesterified nonesuch nonesuches nonet nonetheless nonethical nonethnic nonets nonevaluative nonevent nonevents nonevidence nonexclusive nonexecutive nonexempt nonexistence nonexistent nonexistential nonexotic nonexpendable nonexperimental nonexpert nonexplanatory nonexploitation nonexploitative nonexploitive nonexplosive nonexplosives nonexposed nonextant nonfact nonfactor nonfactual nonfaculty nonfading nonfamilial nonfamily nonfan nonfarm nonfarmer nonfat nonfatal nonfattening nonfatty nonfeasance nonfederal nonfederated nonfeminist nonferrous nonfiction nonfictional nonfigurative nonfilamentous nonfilterable nonfinal nonfinancial nonfinite nonfissionable nonflammability nonflammable nonflowering nonfluency nonfluorescent nonflying nonfood nonforfeitable nonforfeiture nonformal nonfossil nonfraternization nonfreezing nonfrivolous nonfrozen nonfuel nonfulfillment nonfunctional nonfunctioning nongame nongaseous nongay nongenetic nongenital nongeometrical nonghetto nonglamorous nonglare nongolfer nongonococcal nongovernment nongovernmental nongraded nongraduate nongrammatical nongranular nongravitational nongreasy nongreen nongregarious nongrowing nongrowth nonguest nonhalogenated nonhandicapped nonhappening nonhardy nonharmonic nonhazardous nonheme nonhemolytic nonhereditary nonhero nonheroes nonhierarchical nonhistone nonhistorical nonhome nonhomogeneous nonhomologous nonhomosexual nonhormonal nonhospital nonhospitalized nonhostile nonhousing nonhuman nonhumans nonhunter nonhunting nonhygroscopic nonhysterical nonideal nonidentical nonidentity nonideological nonillion nonillions nonillionth nonillionths nonimage nonimitative nonimmigrant nonimmigrants nonimmune nonimpact nonimplication nonimportation noninclusion nonincreasing nonincumbent nonindependence nonindigenous nonindividual noninductive nonindustrial nonindustrialized nonindustry noninfected noninfectious noninfective noninfested noninflammable noninflammatory noninflationary noninflectional noninfluence noninformation noninitial noninitiate noninjury noninsect noninsecticidal noninstallment noninstitutional noninstitutionalized noninstructional noninstrumental noninsurance noninsured nonintegral nonintegrated nonintellectual noninteracting noninteractive noninterchangeable nonintercourse noninterest noninterference nonintersecting nonintervention noninterventionist noninterventionists nonintimidating nonintoxicant nonintoxicating nonintrospective nonintrusive nonintuitive noninvasive noninvolved noninvolvement nonionic nonionizing nonirradiated nonirrigated nonirritant nonirritating nonissue nonissues nonjoinder nonjoinders nonjoiner nonjudgmental nonjudicial nonjuring nonjuror nonjurors nonjury nonjusticiable nonkosher nonlabor nonlandowner nonlanguage nonlawyer nonleaded nonleague nonlegal nonlegume nonleguminous nonlethal nonlexical nonlibrarian nonlibrary nonlife nonlineal nonlinear nonlinearities nonlinearity nonlinearly nonlinguistic nonliquid nonliteral nonliterary nonliterate nonliterates nonliving nonlocal nonlogical nonluminous nonmagnetic nonmainstream nonmajor nonmalignant nonmalleable nonmammalian nonmanagement nonmanagerial nonmandatory nonmanual nonmanufacturing nonmarital nonmarket nonmarketable nonmaterial nonmaterialistic nonmathematical nonmatriculated nonmeaningful nonmeasurable nonmeat nonmechanical nonmechanistic nonmedical nonmeeting nonmember nonmembers nonmembership nonmental nonmercurial nonmetal nonmetallic nonmetals nonmetameric nonmetaphorical nonmetric nonmetrical nonmetro nonmetropolitan nonmicrobial nonmigrant nonmigratory nonmilitant nonmilitary nonmimetic nonminority nonmobile nonmolecular nonmonetarist nonmonetary nonmoney nonmonogamous nonmoral nonmotile nonmotility nonmotorized nonmoving nonmunicipal nonmusic nonmusical nonmusician nonmutant nonmyelinated nonmystical nonnarrative nonnational nonnative nonnatural nonnecessity nonnegative nonnegligent nonnegotiable nonnetwork nonneural nonnews nonnitrogenous nonnormative nonnovel nonnuclear nonnucleated nonnumeric nonnumerical nonnumerically nonnutritious nonnutritive nonobjective nonobjectivism nonobjectivist nonobjectivists nonobjectivity nonobligatory nonobscene nonobservance nonobservances nonobservant nonobservantly nonobvious nonoccupational nonoccurrence nonofficial nonohmic nonoily nonoperatic nonoperating nonoperational nonoperative nonoptimal nonorganic nonorgasmic nonorthodox nonoverlapping nonowner nonoxidizing nonoxynol nonpaid nonpainful nonparallel nonparametric nonparasitic nonpareil nonpareils nonparticipant nonparticipating nonparticipation nonparticipatory nonpartisan nonpartisans nonpartisanship nonpartisanships nonparty nonpasserine nonpassive nonpast nonpathogenic nonpaying nonpayment nonpeak nonperformance nonperformer nonperforming nonperishable nonpermanent nonpermissive nonpersistent nonperson nonpersonal nonpersons nonpetroleum nonphilosopher nonphilosophical nonphonemic nonphonetic nonphosphate nonphotographic nonphysical nonphysician nonplanar nonplastic nonplay nonplaying nonplus nonplused nonpluses nonplusing nonplussed nonplusses nonplussing nonpoetic nonpoint nonpoisonous nonpolar nonpolarizable nonpolice nonpolitical nonpolitically nonpolitician nonpolluting nonpoor nonporous nonpossession nonpractical nonpracticing nonpregnant nonprescription nonprime nonprint nonprinting nonproblem nonprocedural nonproducing nonproductive nonproductively nonproductiveness nonproductives nonprofessional nonprofessionally nonprofessionals nonprofessorial nonprofit nonprogram nonprogrammer nonprogressive nonproliferation nonproprietary nonpros nonprossed nonprosses nonprossing nonprotein nonpsychiatric nonpsychiatrist nonpsychological nonpsychotic nonpublic nonpunitive nonpurposive nonquantifiable nonquantitative nonracial nonracially nonradioactive nonrailroad nonrandom nonrandomness nonrated nonrational nonreactive nonreactor nonreader nonreaders nonreading nonrealistic nonreappointment nonreceipt nonreciprocal nonrecognition nonrecombinant nonrecourse nonrecoverable nonrectangular nonrecurrent nonrecurring nonrecursive nonrecyclable nonreducing nonredundant nonrefillable nonreflecting nonrefundable nonregulated nonregulation nonrelative nonrelativistic nonrelativistically nonrelevant nonreligious nonrenewable nonrenewal nonrepayable nonrepresentational nonrepresentationalism nonrepresentative nonreproductive nonresidence nonresidency nonresident nonresidential nonresidents nonresistance nonresistances nonresistant nonresistants nonresonant nonrespondent nonresponder nonresponse nonresponsive nonrestricted nonrestrictive nonretractile nonretroactive nonreturnable nonreusable nonreversible nonrevolutionary nonrigid nonrioter nonrioting nonromantic nonrotating nonroutine nonroyal nonrubber nonruling nonruminant nonsalable nonsaline nonsaponifiable nonscheduled nonschizophrenic nonschool nonscience nonscientific nonscientist nonscientists nonseasonal nonsecretor nonsecretors nonsecretory nonsectarian nonsectarianism nonsecure nonsedimentable nonsegregated nonsegregation nonselected nonselective nonself nonsensational nonsense nonsensical nonsensicality nonsensically nonsensicalness nonsensitive nonsensuous nonsentence nonseptate nonsequential nonserious nonsexist nonsexual nonshrink nonshrinkable nonsigner nonsignificance nonsignificant nonsignificantly nonsimultaneous nonsingular nonsinkable nonskater nonsked nonskeds nonskeletal nonskid nonskier nonslip nonsmoker nonsmokers nonsmoking nonsocial nonsocialist nonsolar nonsolid nonsolution nonspatial nonspeaker nonspeaking nonspecialist nonspecialists nonspecific nonspecifically nonspectacular nonspeculative nonspeech nonspherical nonsporting nonstandard nonstarter nonstarters nonstationary nonstatistical nonsteady nonsteroid nonsteroidal nonstick nonstop nonstory nonstrategic nonstructural nonstructured nonstudent nonstyle nonsubject nonsubjective nonsubsidized nonsuccess nonsuch nonsuches nonsugar nonsuit nonsuited nonsuiting nonsuits nonsuperimposable nonsupervisory nonsupport nonsurgical nonswimmer nonswimmers nonsyllabic nonsymbolic nonsymmetric nonsymmetrical nonsynchronous nonsystem nonsystematic nonsystemic nonsystems nontarget nontariff nontaxable nonteaching nontechnical nontemporal nontenured nonterminal nonterminating nontheatrical nontheist nontheistic nontheological nontheoretical nontherapeutic nonthermal nonthinking nonthreatening nontidal nontitle nontobacco nontonal nontotalitarian nontoxic nontraditional nontraditionally nontransferable nontransparent nontreatment nontrivial nontropical nonturbulent nontypical nonunanimous nonuniform nonuniformity nonunion nonunionized nonunique nonuniqueness nonuniversal nonuniversity nonuple nonuples nonurban nonurgent nonuse nonuser nonusers nonutilitarian nonutility nonutopian nonvalid nonvalidity nonvanishing nonvascular nonvector nonvectors nonvegetarian nonvenomous nonverbal nonverbally nonveteran nonviable nonviewer nonvintage nonviolence nonviolent nonviolently nonviral nonvirgin nonviscous nonvisual nonvocal nonvocational nonvolatile nonvolcanic nonvoluntary nonvoter nonvoters nonvoting nonwar nonwestern nonwhite nonwhites nonwinning nonwoody nonword nonwords nonwork nonworker nonworking nonwoven nonwovens nonwriter nonyellowing nonylphenylhydroxynonaoxyethylene nonzero noodle noodled noodles noodling nook nooks nooky noon noonday nooning noons noontide noontime noose noosed nooses noosing noosphere nootka nootkas nopal nopals nope nor nor'easter nor'easters nor'wester nor'westers noradrenalin noradrenaline noradrenalins noradrenergic noradrenergically nordic nordics nordkyn nordmann norepinephrine norepinephrines norethindrone norethindrones norfolk nori noria norias noricum noris norite norites noritic norland norm norma normal normalcy normality normalizable normalization normalizations normalize normalized normalizer normalizers normalizes normalizing normally normals norman normande normandy normans normative normatively normativeness normed normocyte normocytes normotensive normotensives normothermia normothermic norms norn nornicotine nornicotines norns norrköping norse norseman norsemen north northamptonshire northanger northbound northeast northeaster northeasterly northeastern northeasterner northeasterners northeasternmost northeasters northeastward northeastwardly northeastwards norther northerlies northerly northern northerner northerners northernmost northernness northers northing northings northland northlander northlanders northlands northman northmen northrop northumberland northumbria northumbrian northumbrians northward northwardly northwards northwest northwester northwesterly northwestern northwesterner northwesterners northwesternmost northwesters northwestward northwestwardly northwestwards nortriptyline nortriptylines norway norwegian norwegians norwich nose nosebag nosebags noseband nosebands nosebleed nosebleeds nosed nosedive nosedives nosegay nosegays noseguard noseguards nosepiece nosepieces noser noses nosewheel nosewheels nosey nosh noshed nosher noshers noshes noshing nosier nosiest nosily nosiness nosing nosings nosocomial nosographer nosographers nosographic nosographical nosography nosologic nosological nosologically nosologies nosologist nosologists nosology nostalgia nostalgic nostalgically nostalgist nostalgists nostoc nostocs nostra nostradamus nostril nostrils nostrum nostrums nosy not nota notabilities notability notable notableness notables notably notarial notarially notaries notarization notarizations notarize notarized notarizes notarizing notary notate notated notates notating notation notational notations notch notchback notchbacks notched notches notching note notebook notebooks notecase notecases noted notedly notedness noteless notepad notepads notepaper noter noters notes noteworthier noteworthiest noteworthily noteworthiness noteworthy nothing nothingism nothingness nothings notice noticeability noticeable noticeably noticed noticer noticers notices noticing notifiable notification notifications notified notifier notifiers notifies notify notifying noting notion notional notionality notionally notions notochord notochordal notochords notogaea notogea notoriety notorious notoriously notoriousness notornis nottinghamshire notum notwithstanding nouakchott nougat nougats nought noughts noumena noumenal noumenon nouméa noun nouns nourish nourished nourisher nourishers nourishes nourishing nourishment nourishments nous nouveau nouveaux nouvelle nova novaculite novaculites novae novalike novas novation novations novaya novel novelette novelettes novelettish novelist novelistic novelistically novelists novelization novelizations novelize novelized novelizer novelizers novelizes novelizing novella novellas novelle novelly novels novelties novelty november novembers novemdecillion novena novenae novenas novercal novgorod novice novices noviciate noviciates novitiate novitiates novo novobiocin novobiocins novocain novocaine novocaines now nowadays noway noways nowhere nowhither nowise nowness noxious noxiously noxiousness nozzle nozzles noël noëls ns nt nth nu nuance nuanced nuances nub nuba nubbier nubbiest nubbin nubbins nubble nubbles nubbly nubby nubia nubian nubians nubile nubility nubs nucellar nucelli nucellus nucha nuchal nuchas nuclear nuclearization nuclearizations nuclearize nuclearized nuclearizes nuclearizing nuclease nucleases nucleate nucleated nucleates nucleating nucleation nucleations nucleator nucleators nuclei nucleic nuclein nucleinic nucleins nucleocapsid nucleocapsids nucleohistone nucleohistones nucleoid nucleoids nucleolar nucleolate nucleolated nucleoli nucleolus nucleon nucleonic nucleonics nucleons nucleophile nucleophiles nucleophilic nucleophilically nucleophilicity nucleoplasm nucleoplasmatic nucleoplasmic nucleoplasms nucleoprotein nucleoproteins nucleoside nucleosides nucleosomal nucleosome nucleosomes nucleosynthesis nucleosynthetic nucleotidase nucleotidases nucleotide nucleotides nucleus nucleuses nuclide nuclides nuclidic nude nudely nudeness nuder nudes nudest nudge nudged nudger nudgers nudges nudging nudibranch nudibranches nudibranchian nudibranchians nudibranchiate nudibranchiates nudism nudist nudists nudity nudnick nudnicks nudnik nudniks nudzh nudzhed nudzhes nudzhing nudzhs nugatory nugget nuggets nuisance nuisances nuke nuked nukes nuking null nullah nullahs nullarbor nulled nullification nullificationist nullificationists nullifications nullified nullifier nullifiers nullifies nullify nullifying nulling nullipara nulliparas nulliparous nullities nullity nulls numb numbed number numberable numbered numberer numberers numbering numberings numberless numbers numbest numbfish numbfishes numbing numbingly numbly numbness numbs numbskull numbskulls numen numerable numeracy numeral numerally numerals numerary numerate numerated numerates numerating numeration numerations numerator numerators numeric numerical numerically numerics numero numerological numerologist numerologists numerology numerous numerously numerousness numidia numidian numidians numina numinous numinousness numismatic numismatically numismatics numismatist numismatists nummular nummulite nummulites nummulitic numskull numskulls nun nunatak nunataks nunc nunchaku nunchakus nunciature nunciatures nuncio nuncios nuncle nuncles nuncupative nunivak nunlike nunneries nunnery nuns nuptial nuptiality nuptially nuptials nurd nurds nuremberg nureyev nuristan nuristani nuristanis nurse nursed nursemaid nursemaids nurser nurseries nursers nursery nurseryman nurserymen nurses nursing nursling nurslings nurturance nurturances nurturant nurture nurtured nurturer nurturers nurtures nurturing nut nutate nutated nutates nutating nutation nutational nutations nutcase nutcases nutcracker nutcrackers nutgall nutgalls nuthatch nuthatches nuthouse nuthouses nutlet nutlets nutlike nutmeat nutmeats nutmeg nutmegs nutpick nutpicks nutria nutrias nutrient nutrients nutriment nutrimental nutriments nutrition nutritional nutritionally nutritionist nutritionists nutritious nutritiously nutritiousness nutritive nutritively nuts nutsedge nutshell nutshells nutted nutter nutters nuttier nuttiest nuttily nuttiness nutting nutty nux nuzzle nuzzled nuzzler nuzzlers nuzzles nuzzling nw nyala nyalas nyanja nyasa nyasaland nyctalopia nyctalopias nyctalopic nyctitropic nyctitropism nyctitropisms nyctophobia nyctophobias nyet nylon nylons nymph nympha nymphae nymphal nymphalid nymphalids nymphet nymphets nymphette nymphettes nympho nympholepsies nympholepsy nympholept nympholeptic nympholepts nymphomania nymphomaniac nymphomaniacal nymphomaniacs nymphos nymphs nynorsk nystagmic nystagmus nystagmuses nystatin nystatins náxos née névé nîmes nürnberg o o'clock o'er o'neill o'odham o'odhams oaf oafish oafishly oafishness oafs oahu oak oaken oakland oakley oakleys oakmoss oakmosses oaks oakum oar oared oarfish oarfishes oaring oarless oarlock oarlocks oars oarsman oarsmanship oarsmen oarswoman oarswomen oases oasis oast oasts oat oatcake oatcakes oaten oater oaters oath oaths oatmeal oats obadiah obbligati obbligato obbligatos obcompressed obcordate obduracy obdurate obdurately obdurateness obeah obeahs obedience obedient obediently obeisance obeisances obeisant obeisantly obeli obelia obelias obeliscal obelisk obeliskoid obelisks obelize obelized obelizes obelizing obelus obento obentos oberammergau oberon obese obesely obeseness obesity obey obeyed obeyer obeyers obeying obeys obfuscate obfuscated obfuscates obfuscating obfuscation obfuscations obfuscatory obi obie obies obis obit obiter obits obituaries obituarist obituarists obituary object objected objectification objectifications objectified objectifier objectifiers objectifies objectify objectifying objecting objection objectionability objectionable objectionableness objectionably objections objective objectively objectiveness objectives objectivism objectivist objectivistic objectivists objectivity objectivization objectivizations objectivize objectivized objectivizes objectivizing objectless objectlessness objector objectors objects objet objets objurgate objurgated objurgates objurgating objurgation objurgations objurgatorily objurgatory oblanceolate oblast oblasti oblasts oblate oblately oblateness oblates oblation oblational oblations oblatory obligable obligate obligated obligately obligates obligati obligating obligation obligational obligations obligato obligator obligatorily obligators obligatory obligatos oblige obliged obligee obligees obliger obligers obliges obliging obligingly obligingness obligor obligors oblique obliqued obliquely obliqueness obliques obliquing obliquities obliquitous obliquity obliterate obliterated obliterates obliterating obliteration obliterations obliterative obliterator obliterators oblivion oblivious obliviously obliviousness oblong oblongata oblongatae oblongatas oblongs obloquies obloquy obnoxious obnoxiously obnoxiousness obnubilate obnubilated obnubilates obnubilating obnubilation obnubilations oboe oboes oboist oboists obol oboli obols obolus obovate obovoid obscene obscenely obsceneness obscener obscenest obscenities obscenity obscura obscurant obscurantic obscurantism obscurantist obscurantists obscurants obscuras obscuration obscurations obscure obscured obscurely obscureness obscurer obscurers obscures obscurest obscuring obscurities obscurity obsequies obsequious obsequiously obsequiousness obsequy observability observable observables observably observance observances observant observantly observants observation observational observationally observations observatories observatory observe observed observer observers observes observing observingly obsess obsessed obsesses obsessing obsession obsessional obsessionally obsessions obsessive obsessively obsessiveness obsessives obsessor obsessors obsidian obsidians obsolesce obsolesced obsolescence obsolescent obsolescently obsolesces obsolescing obsolete obsoleted obsoletely obsoleteness obsoletes obsoleting obsoletism obstacle obstacles obstante obstetric obstetrical obstetrically obstetrician obstetricians obstetrics obstinacies obstinacy obstinate obstinately obstinateness obstreperous obstreperously obstreperousness obstruct obstructed obstructer obstructers obstructing obstruction obstructionism obstructionist obstructionistic obstructionists obstructions obstructive obstructively obstructiveness obstructor obstructors obstructs obstruent obstruents obtain obtainability obtainable obtained obtainer obtainers obtaining obtainment obtainments obtains obtect obtected obtest obtestation obtestations obtested obtesting obtests obtrude obtruded obtruder obtruders obtrudes obtruding obtrusion obtrusions obtrusive obtrusively obtrusiveness obtund obtunded obtundent obtunding obtundity obtunds obturate obturated obturates obturating obturation obturations obturator obturators obtuse obtusely obtuseness obtuser obtusest obverse obversely obverses obversion obversions obvert obverted obverting obverts obviate obviated obviates obviating obviation obviations obviator obviators obvious obviously obviousness oca ocarina ocarinas ocas occam occasion occasional occasionally occasioned occasioning occasions occident occidental occidentalism occidentalization occidentalizations occidentalize occidentalized occidentalizes occidentalizing occidentally occidentals occipita occipital occipitally occipitals occiput occiputs occitan occitanian occitans occlude occluded occludent occludes occluding occlusal occlusion occlusions occlusive occlusives occult occultation occultations occulted occulter occulters occulting occultism occultist occultists occultly occultness occults occupancies occupancy occupant occupants occupation occupational occupationally occupations occupied occupier occupiers occupies occupy occupying occur occurred occurrence occurrences occurrent occurring occurs ocean oceanaria oceanarium oceanariums oceanaut oceanauts oceanfront oceangoing oceania oceanian oceanians oceanic oceanid oceanides oceanids oceanographer oceanographers oceanographic oceanographical oceanographically oceanography oceanologic oceanological oceanologically oceanologist oceanologists oceanology oceans oceanus ocellar ocellate ocellated ocellation ocellations ocelli ocellus ocelot ocelots ocher ocherous ochers ochery ochlocracies ochlocracy ochlocrat ochlocratic ochlocratical ochlocratically ochlocrats ochlophobia ochlophobic ochlophobics ochre ochreous ochres ockham ocotillo ocotillos ocrea ocreae octad octadic octads octagon octagonal octagonally octagons octahedra octahedral octahedrally octahedron octahedrons octal octamerous octameter octameters octandrious octane octans octant octantal octants octapeptide octapeptides octastyle octaval octavalent octave octaves octavian octavius octavo octavos octennial octet octets octillion octillions octillionth octillionths october octobers octobrist octobrists octocentenary octodecillion octodecimo octodecimos octogenarian octogenarians octometer octometers octonaries octonary octopi octoploid octoploids octopod octopodous octopods octopus octopuses octoroon octoroons octosyllabic octosyllabics octosyllable octosyllables octothorp octothorps octuple octupled octuples octupling octylcyanoacrylate ocular ocularist ocularists oculars oculi oculist oculists oculogyric oculomotor oculus odalisk odalisks odalisque odalisques odd oddball oddballs odder oddest oddish oddities oddity oddjobber oddjobbers oddly oddment oddments oddness odds oddsmaker oddsmakers ode odea odense odeon oder odes odessa odeum odic odin odious odiously odiousness odist odists odium odograph odographs odometer odometers odometry odonate odonates odontalgia odontalgias odontalgic odontoblast odontoblastic odontoblasts odontoglossum odontoid odontological odontologically odontologist odontologists odontology odontophoral odontophore odontophores odontophorine odontophorous odor odorant odorants odored odoriferous odoriferously odoriferousness odorize odorized odorizes odorizing odorless odorlessly odorlessness odorous odorously odorousness odors odyssean odysseus odyssey odysseys oecumenical oedema oedipal oedipally oedipus oeil oeillade oeillades oeils oenological oenologist oenologists oenology oenomel oenomels oenone oenophile oenophiles oersted oersteds oesophagi oesophagus oestrogen oestrogens oestrus oeuvre oeuvres of ofay off offa offal offbeat offcast offcasts offcut offcuts offed offenbach offence offences offend offended offender offenders offending offends offense offenseless offenses offensive offensively offensiveness offensives offer offered offerer offerers offering offerings offeror offerors offers offertories offertory offhand offhanded offhandedly offhandedness office officeholder officeholders officemate officemates officer officered officering officers offices official officialdom officialdoms officialese officialeses officialism officially officials officiant officiants officiaries officiary officiate officiated officiates officiating officiation officiations officiator officiators officinal officinally officinals officio officious officiously officiousness offing offish offishly offishness offline offload offloaded offloading offloads offprint offprinted offprinting offprints offs offscouring offscourings offscreen offset offsets offsetting offshoot offshoots offshore offside offsides offspring offsprings offstage offtrack offy oft often oftener oftenest oftentimes ofttimes ogam ogams ogee ogees ogham oghamic oghamist oghamists oghams ogival ogive ogives oglala oglalas ogle ogled ogler oglers ogles ogling ogre ogreish ogres ogress ogresses oh ohia ohio ohioan ohioans ohm ohmic ohmically ohmmeter ohmmeters ohms oho oidia oidium oil oilbird oilbirds oilcan oilcans oilcloth oilcloths oiled oiler oilers oilfield oilfields oilier oiliest oilily oiliness oiling oilman oilmen oilpaper oilpapers oils oilseed oilseeds oilskin oilskins oilstone oilstones oily oink oinked oinking oinks ointment ointments oireachtas oiticica oiticicas ojibwa ojibwas ojibway ojibways ok ok'd ok'ing ok's oka okapi okapis okas okay okayed okaying okays okeechobee okeydoke okeydokey okhotsk okie okies okinawa oklahoma oklahoman oklahomans okra okras oks oktoberfest olaf old olden oldenburg older oldest oldfangled oldie oldies oldish oldness olds oldsquaw oldsquaws oldster oldsters oldwife oldwives olea oleaginous oleaginously oleaginousness oleander oleanders oleandomycin oleaster oleasters oleate oleates olecranal olecranial olecranian olecranon olecranons olefin olefinic olefins oleic olein oleine oleines oleins oleo oleograph oleographer oleographers oleographic oleographs oleography oleomargarine oleomargarines oleoresin oleoresinous oleoresins oleos oleum oleums olfaction olfactometer olfactometers olfactometric olfactometry olfactory olicook olicooks oligarch oligarchic oligarchical oligarchies oligarchs oligarchy oligocene oligochaete oligochaetes oligochaetous oligochete oligochetes oligoclase oligoclases oligodendrocyte oligodendrocytes oligodendroglia oligodendroglial oligodendroglias oligomer oligomeric oligomerization oligomerizations oligomers oligonucleotide oligonucleotides oligophagous oligophagy oligopolies oligopolistic oligopoly oligopsonies oligopsonistic oligopsony oligosaccharide oligosaccharides oligotrophic oligotrophy olingo olingos olio olios olivaceous olive olivenite olivenites oliver olives olivewood olivewoods olivia olivier olivine olivinic olivinitic olla ollas olmec olmecs ologies ology ololiuqui oloroso olorosos olympia olympiad olympiads olympian olympians olympic olympics olympus olé om omaha omahas oman omani omanis omar omasa omasum omayyad omber ombre ombudsman ombudsmanship ombudsmen ombudsperson ombudspersons ombudspersonship ombudswoman ombudswomanship ombudswomen omdurman omega omegas omelet omelets omelette omelettes omen omened omening omens omenta omental omentum omentums omer omers omertà omicron omicrons ominous ominously ominousness omissible omission omissions omissive omit omits omitted omitting ommatidia ommatidial ommatidium ommatophore ommatophores ommatophorous ommiad omnibus omnibuses omnicompetence omnicompetent omnidirectional omnifarious omnifariously omnifariousness omnificent omnipotence omnipotency omnipotent omnipotently omnipotents omnipresence omnipresent omnirange omniranges omniscience omnisciency omniscient omnisciently omniscients omnium omnivore omnivores omnivorous omnivorously omnivorousness omphali omphalos omphaloskepsis omsk on onager onagers onanism onanist onanistic onanists onboard once onchocerciasis oncidium oncidiums oncogene oncogenes oncogenesis oncogenic oncogenicity oncologic oncological oncologist oncologists oncology oncoming oncornavirus oncornaviruses one one's onefold oneida oneidas oneiric oneirically oneiromancer oneiromancers oneiromancy oneness onerous onerously onerousness ones oneself onetime ongoing ongoingness onion onions onionskin onionskins oniony onium onlay onlays online onload onloaded onloading onloads onlooker onlookers onlooking only onomastic onomastically onomastician onomasticians onomastics onomatologist onomatologists onomatology onomatopoeia onomatopoeias onomatopoeic onomatopoeically onomatopoetic onomatopoetically onondaga onondagan onondagas onrush onrushes onrushing onset onsets onshore onside onsite onslaught onslaughts onstage onstream ontario ontic ontically onto ontogeneses ontogenesis ontogenetic ontogenetically ontogenies ontogeny ontological ontologically ontologist ontologists ontology onus onuses onward onwards onycholyses onycholysis onychophoran onychophorans onyx onyxes oocyst oocysts oocyte oocytes oodles oogamete oogametes oogamous oogamy oogenesis oogenetic oogonia oogonial oogonium oogoniums ooh oohed oohing oohs oolemma oolemmas oolite oolites oolith ooliths oolitic oologic oological oologically oologist oologists oology oolong oolongs oomiak oomiaks oompah oompahs oomph oop oophorectomies oophorectomy oophoritis oophoritises oops oort oosphere oospheres oospore oospores oosporic oosporous ootheca oothecae oothecal ootid ootids ooze oozed oozes oozier ooziest oozily ooziness oozing oozy op opacifier opacifiers opacities opacity opah opahs opal opalesce opalesced opalescence opalescent opalescently opalesces opalescing opaline opallesces opals opaque opaquely opaqueness opaques ope oped open openability openable opencast opened opener openers openest openhanded openhandedly openhandedness openhearted openheartedly openheartedness opening openings openly openmouthed openmouthedly openmouthedness openness opens openwork opera operability operable operably operagoer operagoers operagoing operand operandi operands operant operantly operants operas operate operated operates operatic operatically operatics operating operation operational operationalism operationalist operationalistic operationalists operationalize operationalized operationalizes operationalizing operationally operationism operationist operationists operations operative operatively operativeness operatives operator operatorless operators opercula opercular opercularly operculate operculated operculum operculums operetta operettas operettist operettists operon operons operose operosely operoseness opes ophelia ophidian ophidians ophiolite ophiolites ophiological ophiologist ophiologists ophiology ophiophagous ophir ophite ophites ophitic ophiuchus ophiuroid ophiuroids ophthalmia ophthalmias ophthalmic ophthalmitis ophthalmitises ophthalmologic ophthalmological ophthalmologically ophthalmologist ophthalmologists ophthalmology ophthalmoscope ophthalmoscopes ophthalmoscopic ophthalmoscopical ophthalmoscopy opiate opiated opiates opiating opine opined opines oping opining opinion opinionated opinionatedly opinionatedness opinionative opinionatively opinionativeness opinioned opinions opioid opioids opisthobranch opisthobranchs opisthognathism opisthognathous opium oporto opossum opossums opponency opponent opponents opportune opportunely opportuneness opportunism opportunist opportunistic opportunistically opportunists opportunities opportunity opposability opposable oppose opposed opposeless opposer opposers opposes opposing opposite oppositely oppositeness opposites opposition oppositional oppositionist oppositionists oppositions oppress oppressed oppresses oppressing oppression oppressions oppressive oppressively oppressiveness oppressor oppressors opprobrious opprobriously opprobriousness opprobrium oppugn oppugned oppugner oppugners oppugning oppugns opsin opsins opsonic opsonin opsonins opsonization opsonizations opsonize opsonized opsonizes opsonizing opt optative optatively optatives opted optic optical optically optician opticians optics optima optimal optimality optimally optimism optimist optimistic optimistically optimists optimization optimizations optimize optimized optimizer optimizers optimizes optimizing optimum optimums opting option optional optionality optionally optioned optioning options optoelectronic optoelectronics optokinetic optometric optometrical optometrist optometrists optometry opts opulence opulency opulent opulently opuntia opuntias opus opuscula opuscule opuscules opusculum opuses opéra oquassa oquassas or ora orach orache oraches oracle oracles oracular oracularity oracularly oral oralism oralist oralists orality orally orals oran orang orange orangeade orangeades orangeism orangeman orangemen orangerie orangeries orangeroot orangeroots orangery oranges orangewood orangewoods orangey orangish orangoutang orangoutangs orangs orangutan orangutans orangy orate orated orates orating oration orations orator oratorial oratorian oratorians oratorical oratorically oratories oratorio oratorios orators oratorship oratory orb orbed orbicular orbicularity orbicularly orbiculate orbiculated orbiculately orbing orbit orbital orbitals orbited orbiteer orbiteered orbiteering orbiteers orbiter orbiters orbiting orbits orbs orca orcadian orcadians orcas orchard orchardist orchardists orchards orchestra orchestral orchestrally orchestras orchestrate orchestrated orchestrater orchestraters orchestrates orchestrating orchestration orchestrational orchestrations orchestrator orchestrators orchestrina orchestrion orchid orchidaceous orchidectomies orchidectomy orchidlike orchids orchiectomies orchiectomy orchil orchils orchis orchises orcus ordain ordained ordainer ordainers ordaining ordainment ordainments ordains ordeal ordeals order orderable ordered orderer orderers ordering orderings orderless orderlies orderliness orderly orders ordinal ordinals ordinance ordinances ordinand ordinands ordinaries ordinarily ordinariness ordinary ordinate ordinates ordination ordinations ordines ordnance ordo ordonnance ordonnances ordos ordovician ordure ore oread oreads oregano oregon oregonian oregonians oreide oreides oreo oreos ores orestes oresund orfray orfrays organ organa organdie organdies organdy organelle organelles organic organically organicism organicist organicists organicity organics organism organismal organismic organismically organisms organist organists organizable organization organizational organizationally organizations organize organized organizer organizers organizes organizing organochlorine organochlorines organogeneses organogenesis organogenetic organogenetically organographic organographically organographies organography organoleptic organoleptically organologic organological organology organomercurial organomercurials organometallic organon organons organophosphate organophosphates organophosphorous organophosphorus organophosphoruses organotherapeutic organotherapies organotherapy organotropic organotropically organotropism organotropy organs organum organums organza organzine organzines orgasm orgasmic orgasmically orgasms orgastic orgastically orgeat orgeats orgiast orgiastic orgiastically orgiasts orgies orgone orgones orgulous orgy oribatid oribatids oribi oribis oriel oriels orient oriental orientalia orientalism orientalist orientalists orientalize orientalized orientalizes orientalizing orientally orientals orientate orientated orientates orientating orientation orientational orientationally orientations oriented orienteer orienteering orienteers orienting orients orifice orifices orificial oriflamme oriflammes origami origamis origanum origanums origin original originalism originalist originalists originalities originality originally originals originate originated originates originating origination originations originative originatively originator originators origins orinasal orinasals orinoco oriole orioles orion orion's orismological orismology orison orisons orissa oriya orizaba orkney orlando orleanian orleanians orleanist orleanists orleans orlon orlop orlops orléanais orléans ormazd ormer ormers ormolu ormolus ormuz ormuzd ornament ornamental ornamentally ornamentals ornamentation ornamented ornamenter ornamenters ornamenting ornaments ornate ornately ornateness ornerier orneriest orneriness ornery ornithic ornithine ornithines ornithischian ornithischians ornithologic ornithological ornithologically ornithologist ornithologists ornithology ornithopod ornithopods ornithopter ornithopters ornithosis orogenesis orogenetic orogenic orogenically orogeny orographic orographical orographically orography oroide oroides orological orologically orologist orologists orology oromo oromos oropharyngeal oropharynges oropharynx oropharynxes orotund orotundity orphan orphanage orphanages orphaned orphanhood orphaning orphans orphean orpheus orphic orphically orphism orphist orphists orphrey orphreys orpiment orpine orpines orpington orpingtons orreries orrery orris orrises orrisroot orrisroots ors ort orthicon orthicons ortho orthocenter orthocenters orthochromatic orthochromatism orthoclase orthoclastic orthodontia orthodontic orthodontically orthodontics orthodontist orthodontists orthodonture orthodox orthodoxes orthodoxies orthodoxly orthodoxy orthoepic orthoepical orthoepically orthoepist orthoepists orthoepy orthogenesis orthogenetic orthogenetically orthogonal orthogonality orthogonalization orthogonalizations orthogonalize orthogonalized orthogonalizes orthogonalizing orthogonally orthograde orthographer orthographers orthographic orthographical orthographically orthographies orthographist orthographists orthography orthomolecular orthonormal orthopaedic orthopaedics orthopedic orthopedically orthopedics orthopedist orthopedists orthophosphate orthophosphates orthophosphoric orthopsychiatric orthopsychiatrical orthopsychiatrist orthopsychiatrists orthopsychiatry orthoptera orthopteral orthopteran orthopterans orthopterist orthopterists orthopteroid orthopteron orthopterons orthopterous orthorhombic orthoscopic orthoses orthosis orthostatic orthotic orthotics orthotist orthotists orthotropic orthotropically orthotropism orthotropous ortler ortles ortolan ortolans orts orvieto orwellian oryx oryxes orzo orzos os osage osages osaka osar osborne oscan oscans oscar oscars osceola oscillate oscillated oscillates oscillating oscillation oscillational oscillations oscillator oscillators oscillatory oscillogram oscillograms oscillograph oscillographic oscillographically oscillographs oscillography oscilloscope oscilloscopes oscilloscopic oscine oscines oscitance oscitances oscitancies oscitancy oscitant oscula osculant oscular osculate osculated osculates osculating osculation osculations osculatory oscule oscules osculum osee osier osiers osiris oslo osmanli osmanlis osmatic osmeteria osmeterium osmic osmically osmics osmious osmiridium osmiridiums osmium osmol osmolal osmolalities osmolality osmolar osmolarities osmolarity osmole osmoles osmols osmometer osmometers osmometric osmometry osmoregulation osmoregulations osmoregulatory osmose osmosed osmoses osmosing osmosis osmotic osmotically osmous osmund osmunda osmundas osmunds osnabrück osnaburg osnaburgs osprey ospreys osric ossa ossature ossatures ossein osseins osseous osseously osset ossete ossetes ossetia ossetian ossetians ossetic ossets ossia ossian ossianic ossicle ossicles ossicular ossiculate ossific ossification ossified ossifies ossifrage ossifrages ossify ossifying osso ossuaries ossuary osteal osteitis ostend ostende ostensible ostensibly ostensive ostensively ostensoria ostensories ostensorium ostensory ostentation ostentatious ostentatiously ostentatiousness osteoarthritic osteoarthritis osteoblast osteoblastic osteoblasts osteoclases osteoclasis osteoclast osteoclastic osteoclasts osteocyte osteocytes osteogeneses osteogenesis osteogenetic osteogenic osteogenous osteoid osteoids osteological osteologically osteologies osteologist osteologists osteology osteolyses osteolysis osteolytic osteoma osteomalacia osteomalacias osteomas osteomata osteomyelitis osteomyelitises osteopath osteopathic osteopathically osteopathist osteopathists osteopaths osteopathy osteophyte osteophytes osteophytic osteoplastic osteoplasties osteoplasty osteoporoses osteoporosis osteoporotic osteosarcoma osteosarcomas osteosarcomata osteoses osteosis osteotomies osteotomist osteotomists osteotomy ostia ostiak ostiaks ostiaries ostiary ostinato ostinatos ostiolar ostiole ostioles ostium ostler ostlers ostmark ostmarks ostomate ostomates ostomies ostomy ostoses ostosis ostraca ostracism ostracize ostracized ostracizes ostracizing ostracod ostracode ostracoderm ostracoderms ostracodes ostracods ostracon ostrich ostriches ostrichlike ostrogoth ostrogothic ostrogoths ostyak ostyaks oswego otaheite otalgia otalgias otalgic othello other otherguess otherness others otherwhere otherwhile otherwhiles otherwise otherworld otherworldliness otherworldly otherworlds othman othmans otic otiose otiosely otioseness otiosity otitic otitis oto otocyst otocystic otocysts otolaryngological otolaryngologist otolaryngologists otolaryngology otolith otolithic otoliths otological otologist otologists otology otophone otorhinolaryngological otorhinolaryngologist otorhinolaryngologists otorhinolaryngology otos otoscleroses otosclerosis otosclerotic otoscope otoscopes ototoxic ototoxicity otranto ottar ottars ottava ottawa ottawas otter otters otto ottoman ottomans ottos otway ouabain ouabains ouachita ouagadougou oubliette oubliettes ouch ouches oud oudenarde oudh ouds ought oughtn oughtn't oughts ouguiya ouguiyas ouija ounce ounces our ours ourself ourselves ousel ousels oushak oust ousted ouster ousters ousting ousts out outachieve outachieved outachieves outachieving outact outacted outacting outacts outage outages outate outback outbacker outbackers outbalance outbalanced outbalances outbalancing outbargain outbargained outbargaining outbargains outbid outbidden outbidding outbids outbitch outbitched outbitches outbitching outbluff outbluffed outbluffing outbluffs outboard outboards outbought outbound outbox outboxed outboxes outboxing outbrag outbraged outbraging outbrags outbrave outbraved outbraves outbraving outbrawl outbrawled outbrawling outbrawls outbreak outbreaks outbred outbreed outbreeding outbreedings outbreeds outbuilding outbuildings outbulk outbulked outbulking outbulks outburst outbursts outbuy outbuying outbuys outcall outcalls outcast outcaste outcastes outcasts outcatch outcatches outcatching outcaught outcharge outcharged outcharges outcharging outclass outclassed outclasses outclassing outclimb outclimbed outclimbing outclimbs outcoach outcoached outcoaches outcoaching outcome outcomes outcompete outcompeted outcompetes outcompeting outcries outcrop outcropped outcropping outcroppings outcrops outcross outcrossed outcrosses outcrossing outcry outcurve outcurves outdance outdanced outdances outdancing outdate outdated outdatedly outdatedness outdates outdating outdazzle outdazzled outdazzles outdazzling outdebate outdebated outdebates outdebating outdeliver outdelivered outdelivering outdelivers outdesign outdesigned outdesigning outdesigns outdid outdistance outdistanced outdistances outdistancing outdo outdoes outdoing outdone outdoor outdoors outdoorsman outdoorsmanship outdoorsmen outdoorswoman outdoorswomen outdoorsy outdrag outdragged outdragging outdrags outdrank outdraw outdrawing outdrawn outdraws outdress outdressed outdresses outdressing outdrew outdrink outdrinking outdrinks outdrive outdriven outdrives outdriving outdrove outdrunk outduel outdueled outdueling outduelled outduelling outduels outearn outearned outearning outearns outeat outeaten outeating outeats outed outer outercoat outercoats outermost outers outerwear outface outfaced outfaces outfacing outfall outfalls outfield outfielder outfielders outfields outfight outfighting outfights outfigure outfigured outfigures outfiguring outfish outfished outfishes outfishing outfit outfits outfitted outfitter outfitters outfitting outflank outflanked outflanking outflanks outflew outflies outflow outflowed outflowing outflown outflows outfly outflying outfoot outfooted outfooting outfoots outfought outfox outfoxed outfoxes outfoxing outfumble outfumbled outfumbles outfumbling outgain outgained outgaining outgains outgas outgassed outgasses outgassing outgeneral outgeneraled outgeneraling outgenerals outgiving outglitter outglittered outglittering outglitters outgo outgoes outgoing outgoingness outgoings outgone outgrew outgrip outgripped outgripping outgrips outgross outgrossed outgrosses outgrossing outgrow outgrowing outgrown outgrows outgrowth outgrowths outguess outguessed outguesses outguessing outgun outgunned outgunning outguns outhaul outhauls outhit outhits outhitting outhomer outhomered outhomering outhomers outhouse outhouses outhunt outhunted outhunting outhunts outhustle outhustled outhustles outhustling outing outings outintrigue outintrigued outintrigues outintriguing outjump outjumped outjumping outjumps outkick outkicked outkicking outkicks outkill outkilled outkilling outkills outlaid outland outlander outlanders outlandish outlandishly outlandishness outlands outlast outlasted outlasting outlasts outlaw outlawed outlawing outlawries outlawry outlaws outlay outlaying outlays outleap outleaped outleaping outleaps outleapt outlearn outlearned outlearning outlearns outlearnt outlet outlets outlier outliers outline outlined outliner outliners outlines outlining outlive outlived outlives outliving outlook outlooks outlying outman outmaneuver outmaneuvered outmaneuvering outmaneuvers outmanipulate outmanipulated outmanipulates outmanipulating outmanned outmanning outmans outmarch outmarched outmarches outmarching outmatch outmatched outmatches outmatching outmode outmoded outmodes outmoding outmost outmuscle outmuscled outmuscles outmuscling outness outnumber outnumbered outnumbering outnumbers outorganize outorganized outorganizes outorganizing outpace outpaced outpaces outpacing outpass outpassed outpasses outpassing outpatient outpatients outperform outperformed outperforming outperforms outpitch outpitched outpitches outpitching outplace outplaced outplacement outplacements outplacer outplacers outplaces outplacing outplay outplayed outplaying outplays outplot outplots outplotted outplotting outpoint outpointed outpointing outpoints outpolitick outpoliticked outpoliticking outpoliticks outpoll outpolled outpolling outpolls outpopulate outpopulated outpopulates outpopulating outport outports outpost outposts outpour outpoured outpourer outpourers outpouring outpourings outpours outpower outpowered outpowering outpowers outpray outprayed outpraying outprays outpreach outpreached outpreaches outpreaching outprice outpriced outprices outpricing outproduce outproduced outproduces outproducing outpromise outpromised outpromises outpromising outpull outpulled outpulling outpulls outpunch outpunched outpunches outpunching output outputs outputted outputting outrace outraced outraces outracing outrage outraged outrageous outrageously outrageousness outrages outraging outran outrange outranged outranges outranging outrank outranked outranking outranks outrate outrated outrates outrating outreach outreached outreaches outreaching outrebound outrebounded outrebounding outrebounds outreproduce outreproduced outreproduces outreproducing outridden outride outrider outriders outrides outriding outrigger outriggers outright outrightly outrightness outrival outrivaled outrivaling outrivalled outrivalling outrivals outroar outroared outroaring outroars outrode outrow outrowed outrowing outrows outrun outrunning outruns outrush outrushed outrushes outrushing outré outs outsail outsailed outsailing outsails outsang outsat outscheme outschemed outschemes outscheming outscoop outscooped outscooping outscoops outscore outscored outscores outscoring outsell outselling outsells outset outsets outshine outshines outshining outshone outshoot outshooting outshoots outshot outshout outshouted outshouting outshouts outside outsider outsiderness outsiders outsides outsight outsights outsing outsinging outsings outsit outsits outsitting outsize outsized outsizes outskate outskated outskates outskating outskirt outskirts outslick outslicked outslicking outslicks outsmart outsmarted outsmarting outsmarts outsoar outsoared outsoaring outsoars outsold outsole outsoles outsource outsourced outsources outsourcing outsourcings outsparkle outsparkled outsparkles outsparkling outspeak outspeaking outspeaks outsped outspeed outspeeded outspeeding outspeeds outspend outspending outspends outspent outspoke outspoken outspokenly outspokenness outspread outspreading outspreads outsprint outsprinted outsprinting outsprints outstand outstanding outstandingly outstands outstare outstared outstares outstaring outstation outstations outstay outstayed outstaying outstays outstood outstretch outstretched outstretches outstretching outstridden outstride outstrides outstriding outstrip outstripped outstripping outstrips outstrode outstroke outstrokes outsung outswam outswear outswearing outswears outswim outswimming outswims outswore outsworn outswum outtake outtakes outtalk outtalked outtalking outtalks outthink outthinking outthinks outthought outthrew outthrow outthrowing outthrown outthrows outthrust outthrusted outthrusting outthrusts outtrade outtraded outtrades outtrading outturn outturning outturns outvie outvied outvies outvote outvoted outvotes outvoting outvying outwait outwaited outwaiting outwaits outwalk outwalked outwalking outwalks outward outwardly outwardness outwards outwash outwashes outwatch outwatched outwatches outwatching outwear outwearing outwears outweigh outweighed outweighing outweighs outwent outwit outwits outwitted outwitting outwore outwork outworked outworker outworkers outworking outworks outworn outwrestle outwrestled outwrestles outwrestling outwrite outwrites outwriting outwritten outwrote outwrought outyell outyelled outyelling outyells outyield outyielded outyielding outyields ouzel ouzels ouzo ouzos ova oval ovalbumin ovalbumins ovality ovally ovalness ovals ovambo ovambos ovarial ovarian ovariectomies ovariectomized ovariectomy ovaries ovariole ovarioles ovariotomies ovariotomy ovaritis ovaritises ovary ovate ovately ovation ovational ovations oven ovenable ovenbird ovenbirds ovenproof ovens ovenware over overabounding overabstract overabundance overabundances overabundant overabundantly overaccentuate overaccentuated overaccentuates overaccentuating overachieve overachieved overachievement overachievements overachiever overachievers overachieves overachieving overact overacted overacting overaction overactions overactive overactivity overacts overadjustment overadjustments overadvertise overadvertised overadvertises overadvertising overage overaged overages overaggressive overaggressively overaggressiveness overalert overall overalled overalls overambition overambitious overambitiously overambitiousness overamplified overanalyses overanalysis overanalytical overanalyze overanalyzed overanalyzes overanalyzing overanxieties overanxiety overanxious overanxiously overanxiousness overapplication overapplications overarch overarched overarches overarching overarchingly overarm overarmed overarming overarms overarousal overarousals overarrange overarranged overarranges overarranging overarticulate overassert overasserted overasserting overassertion overassertions overassertive overasserts overassess overassessed overassesses overassessing overassessment overassessments overate overattention overattentions overawe overawed overawes overawing overbake overbaked overbakes overbaking overbalance overbalanced overbalances overbalancing overbear overbearing overbearingly overbearingness overbears overbeat overbeaten overbeating overbeats overbejeweled overbid overbidden overbidder overbidders overbidding overbids overbill overbilled overbilling overbills overbite overbites overbleach overbleached overbleaches overbleaching overblew overblouse overblouses overblow overblowing overblown overblows overboard overboil overboiled overboiling overboils overbold overbook overbooked overbooking overbooks overbore overborne overborrow overborrowed overborrowing overborrows overbought overbreathing overbrief overbright overbroad overbrowse overbrowsed overbrowses overbrowsing overbrutal overbuild overbuilding overbuilds overbuilt overburden overburdened overburdening overburdens overburn overbusy overbuy overbuying overbuys overcall overcalled overcalling overcalls overcame overcapacities overcapacity overcapitalization overcapitalizations overcapitalize overcapitalized overcapitalizes overcapitalizing overcareful overcast overcasting overcastings overcasts overcaution overcautious overcautiously overcautiousness overcentralization overcentralize overcentralized overcentralizes overcentralizing overcharge overcharged overcharges overcharging overchill overchilled overchilling overchills overcivilized overclaim overclaimed overclaiming overclaims overclassification overclassifications overclassified overclassifies overclassify overclassifying overclean overcleaned overcleaning overcleans overclear overcloud overclouded overclouding overclouds overcoach overcoached overcoaches overcoaching overcoat overcoating overcoatings overcoats overcome overcomer overcomers overcomes overcoming overcommercialization overcommercialize overcommercialized overcommercializes overcommercializing overcommit overcommitment overcommitments overcommits overcommitted overcommitting overcommunicate overcommunicated overcommunicates overcommunicating overcommunication overcompensate overcompensated overcompensates overcompensating overcompensation overcompensatory overcomplex overcompliance overcomplicate overcomplicated overcomplicates overcomplicating overcompress overcompressed overcompresses overcompressing overconcentration overconcentrations overconcern overconcerned overconcerning overconcerns overconfidence overconfident overconfidently overconscientious overconscious overconservative overconstruct overconstructed overconstructing overconstructs overconsume overconsumed overconsumes overconsuming overconsumption overcontrol overcontrolled overcontrolling overcontrols overcook overcooked overcooking overcooks overcool overcooled overcooling overcools overcorrect overcorrected overcorrecting overcorrection overcorrections overcorrects overcount overcounted overcounting overcountings overcounts overcredulous overcritical overcritically overcriticalness overcrop overcropped overcropping overcrops overcrowd overcrowded overcrowding overcrowds overcultivation overcure overcurious overcut overcuts overcutting overdecorate overdecorated overdecorates overdecorating overdecoration overdelicate overdemanding overdependence overdependent overdesign overdesigned overdesigning overdesigns overdetermine overdetermined overdetermines overdetermining overdevelop overdeveloped overdeveloping overdevelopment overdevelops overdid overdifferentiation overdirect overdiscount overdiscounted overdiscounting overdiscounts overdiversity overdo overdocument overdocumented overdocumenting overdocuments overdoer overdoers overdoes overdog overdogs overdoing overdominance overdominances overdominant overdone overdosage overdosages overdose overdosed overdoses overdosing overdraft overdrafts overdramatic overdramatize overdramatized overdramatizes overdramatizing overdrank overdraught overdraughts overdraw overdrawing overdrawn overdraws overdress overdressed overdresses overdressing overdrew overdried overdries overdrink overdrinking overdrinks overdrive overdriven overdrives overdriving overdrove overdry overdrying overdub overdubbed overdubbing overdubs overdue overeager overeagerly overeagerness overearnest overeat overeaten overeater overeaters overeating overeats overed overedit overedited overediting overedits overeducate overeducated overeducates overeducating overeducation overelaborate overelaborated overelaborates overelaborating overelaboration overembellish overembellished overembellishes overembellishing overemote overemotional overemphases overemphasis overemphasize overemphasized overemphasizes overemphasizing overemphatic overenamored overencourage overencouraged overencourages overencouraging overenergetic overengineer overengineered overengineering overengineers overenrolled overentertained overenthusiasm overenthusiasms overenthusiastic overequip overequipped overequipping overequips overestimate overestimated overestimates overestimating overestimation overestimations overevaluation overevaluations overexaggerate overexaggerated overexaggerates overexaggerating overexaggeration overexaggerations overexcite overexcited overexcites overexciting overexercise overexercised overexercises overexercising overexert overexerted overexerting overexertion overexertions overexerts overexpand overexpanded overexpanding overexpands overexpansion overexpectation overexpectations overexplain overexplained overexplaining overexplains overexplicit overexploit overexploitation overexploitations overexploited overexploiting overexploits overexpose overexposed overexposes overexposing overexposure overexposures overextend overextended overextending overextends overextension overextensions overextraction overextractions overextrapolation overextrapolations overextravagant overexuberant overfacile overfamiliar overfamiliarities overfamiliarity overfastidious overfat overfatigue overfatigued overfavor overfavored overfavoring overfavors overfed overfeed overfeeding overfeeds overfertilization overfertilize overfertilized overfertilizes overfertilizing overfill overfilled overfilling overfills overfish overfished overfishes overfishing overflew overflies overflight overflights overflow overflowed overflowing overflown overflows overfly overflying overfocus overfocused overfocuses overfocusing overfocussed overfocusses overfocussing overfond overfulfill overfulfilled overfulfilling overfulfills overfull overfund overfunded overfunding overfunds overfussy overgarment overgarments overgeneralization overgeneralizations overgeneralize overgeneralized overgeneralizes overgeneralizing overgenerosity overgenerous overgenerously overglamorize overglamorized overglamorizes overglamorizing overglaze overglazed overglazes overglazing overgovern overgoverned overgoverning overgoverns overgraze overgrazed overgrazes overgrazing overgrew overgrow overgrowing overgrown overgrows overgrowth overgrowths overhand overhanded overhanding overhandle overhandled overhandles overhandling overhands overhang overhanging overhangs overharvest overharvested overharvesting overharvests overhasty overhaul overhauled overhauler overhaulers overhauling overhauls overhead overheads overhear overheard overhearer overhearers overhearing overhears overheat overheated overheating overheats overhit overhits overhitting overhomogenize overhomogenized overhomogenizes overhomogenizing overhung overhunt overhunted overhunting overhunts overhydrate overhydrated overhydrates overhydrating overhydration overhype overhyped overhypes overhyping overidealize overidealized overidealizes overidealizing overidentification overidentified overidentifies overidentify overidentifying overimaginative overimpress overimpressed overimpresses overimpressing overindebtedness overindulge overindulged overindulgence overindulgences overindulgent overindulgently overindulges overindulging overindustrialize overindustrialized overindustrializes overindustrializing overinflate overinflated overinflates overinflating overinflation overinform overinformed overinforming overinforms overing overingenious overingenuity overinsistent overintellectualization overintellectualize overintellectualized overintellectualizes overintellectualizing overintense overintensity overinterpret overinterpretation overinterpretations overinterpreted overinterpreting overinterprets overinvestment overissuance overissue overissued overissues overissuing overjoy overjoyed overjoying overjoys overkill overkilled overkilling overkills overlabor overlabored overlaboring overlabors overladen overlaid overlain overland overlap overlapped overlapping overlaps overlarge overlavish overlay overlaying overlays overleaf overleap overleaped overleaping overleaps overleapt overlearn overlearned overlearning overlearns overlearnt overlend overlending overlends overlength overlengthen overlengthened overlengthening overlengthens overlent overlie overlies overlight overliteral overliterary overload overloaded overloading overloads overlong overlook overlooked overlooking overlooks overlord overlords overlordship overloud overlush overly overlying overman overmanage overmanaged overmanages overmanaging overmanned overmannered overmanning overmans overmantel overmantels overmaster overmastered overmastering overmasters overmatch overmatched overmatches overmatching overmature overmaturity overmedicate overmedicated overmedicates overmedicating overmedication overmen overmighty overmilk overmilked overmilking overmilks overmine overmined overmines overmining overmix overmixed overmixes overmixing overmodest overmodestly overmuch overmuscled overnice overnight overnighted overnighter overnighters overnighting overnights overnourish overnourished overnourishes overnourishing overnutrition overobvious overoperate overoperated overoperates overoperating overopinionated overoptimism overoptimist overoptimistic overoptimistically overoptimists overorchestrate overorchestrated overorchestrates overorchestrating overorganize overorganized overorganizes overorganizing overornament overornamented overornamenting overornaments overpackage overpackaged overpackages overpackaging overpaid overparticular overpass overpassed overpasses overpassing overpast overpay overpaying overpayment overpayments overpays overpedal overpedaled overpedaling overpedals overpeople overpeopled overpeoples overpeopling overpersuade overpersuaded overpersuades overpersuading overpersuasion overplaid overplaided overplan overplanned overplanning overplans overplant overplanted overplanting overplants overplay overplayed overplaying overplays overplenty overplot overplots overplotted overplotting overplus overpluses overpopulate overpopulated overpopulates overpopulating overpopulation overpotent overpower overpowered overpowering overpoweringly overpowers overpraise overpraised overpraises overpraising overprecise overprescribe overprescribed overprescribes overprescribing overprescription overprescriptions overpressure overpressured overpressures overpressuring overpressurization overpressurizations overprice overpriced overprices overpricing overprint overprinted overprinting overprints overprivileged overprize overprized overprizes overprizing overprocess overprocessed overprocesses overprocessing overproduce overproduced overproducer overproducers overproduces overproducing overproduction overproductions overprogram overprogrammed overprogramming overprograms overpromise overpromised overpromises overpromising overpromote overpromoted overpromotes overpromoting overproof overproportion overproportionate overproportionately overproportioned overproportioning overproportions overprotect overprotected overprotecting overprotection overprotections overprotective overprotectiveness overprotects overpump overpumped overpumping overpumps overqualified overran overrate overrated overrates overrating overreach overreached overreacher overreachers overreaches overreaching overreact overreacted overreacting overreaction overreactions overreactive overreacts overrefine overrefined overrefinement overrefinements overrefines overrefining overregulate overregulated overregulates overregulating overregulation overregulations overreliance overreport overreported overreporting overreports overrepresentation overrepresentations overrepresented overrespond overresponded overresponding overresponds overrich overridden override overrides overriding overridingly overrigid overripe overripely overripeness overrode overruff overruffed overruffing overruffs overrule overruled overrules overruling overrun overrunning overruns overs oversalt oversalted oversalting oversalts oversanguine oversaturate oversaturated oversaturates oversaturating oversaturation oversauce oversauced oversauces oversaucing oversaw overscale overscaled overscore overscored overscores overscoring overscrupulous oversea overseas oversecretion oversee overseeing overseen overseer overseers oversees oversell overselling oversells oversensitive oversensitiveness oversensitivities oversensitivity overserious overseriously overservice overserviced overservices overservicing overset oversets oversetting oversew oversewed oversewing oversewn oversews oversexed overshadow overshadowed overshadowing overshadows overshirt overshirts overshoe overshoes overshoot overshooting overshoots overshot oversight oversights oversimple oversimplification oversimplifications oversimplified oversimplifier oversimplifiers oversimplifies oversimplify oversimplifying oversimplistic oversimply oversize oversized oversizes overskirt overskirts overslaugh overslaughed overslaughing overslaughs oversleep oversleeping oversleeps overslept overslip overslipped overslipping overslips oversmoke oversmoked oversmokes oversmoking oversold oversolicitous oversophisticated oversoul oversouls overspecialization overspecializations overspecialize overspecialized overspecializes overspecializing overspeculate overspeculated overspeculates overspeculating overspeculation overspeculations overspend overspender overspenders overspending overspends overspent overspill overspilled overspilling overspills overspilt overspread overspreading overspreads overstability overstaff overstaffed overstaffing overstaffs overstate overstated overstatement overstatements overstates overstating overstay overstayed overstaying overstays oversteer oversteers overstep overstepped overstepping oversteps overstimulate overstimulated overstimulates overstimulating overstimulation overstimulations overstitch overstitched overstitches overstitching overstock overstocked overstocking overstocks overstories overstory overstrain overstrained overstraining overstrains overstress overstressed overstresses overstressing overstretch overstretched overstretches overstretching overstrew overstrewed overstrewing overstrews overstridden overstride overstrides overstriding overstrike overstrikes overstrode overstructured overstrung overstuff overstuffed overstuffing overstuffs oversubscribe oversubscribed oversubscribes oversubscribing oversubscription oversubscriptions oversubtle oversuds oversupplied oversupplies oversupply oversupplying oversuspicious oversweet oversweeten oversweetened oversweetening oversweetens oversweetness overswing overt overtake overtaken overtakes overtaking overtalk overtalkative overtalked overtalking overtalks overtax overtaxation overtaxations overtaxed overtaxes overtaxing overthin overthink overthinking overthinks overthinned overthinning overthins overthought overthrew overthrow overthrowing overthrown overthrows overthrust overtighten overtightened overtightening overtightens overtime overtimed overtimes overtiming overtip overtipped overtipping overtips overtire overtired overtires overtiring overtly overtness overtone overtones overtook overtop overtopped overtopping overtops overtrade overtraded overtrades overtrading overtrain overtrained overtraining overtrains overtreat overtreated overtreating overtreatment overtreats overtrick overtricks overtrump overtrumped overtrumping overtrumps overture overtured overtures overturing overturn overturned overturning overturns overtype overtyped overtyping overuse overused overuses overusing overutilization overutilize overutilized overutilizes overutilizing overvaluation overvaluations overvalue overvalued overvalues overvaluing overview overviews overviolent overvivid overvoltage overvoltages overwater overwatered overwatering overwaters overwear overwearied overwearies overwearing overwears overweary overwearying overweening overweeningly overweigh overweighed overweighing overweighs overweight overweighted overweighting overweights overwhelm overwhelmed overwhelming overwhelmingly overwhelms overwind overwinding overwinds overwinter overwintered overwintering overwinters overwithheld overwithhold overwithholding overwithholds overwore overwork overworked overworking overworks overworn overwound overwrite overwrites overwriting overwritten overwrote overwrought overzealous overzealously overzealousness ovicidal ovicide ovicides ovid ovidian oviduct oviductal oviducts oviferous oviform ovimbundu ovimbundus ovine ovines ovipara oviparity oviparous oviparously oviposit oviposited ovipositing oviposition ovipositional ovipositions ovipositor ovipositors oviposits ovisac ovisacs ovoid ovoidal ovoidals ovoids ovolactovegetarian ovolactovegetarians ovoli ovolo ovonic ovonics ovotestes ovotestis ovoviviparity ovoviviparous ovoviviparously ovoviviparousness ovular ovulary ovulate ovulated ovulates ovulating ovulation ovulations ovulatory ovule ovules ovum ow owe owed owes owing owl owlet owlets owlish owlishly owlishness owls own owned owner ownerless owners ownership owning owns owyheei ox oxacillin oxacillins oxalacetate oxalacetates oxalacetic oxalate oxalated oxalates oxalating oxalic oxalis oxalises oxaloacetate oxaloacetates oxaloacetic oxalosuccinic oxazepam oxazepams oxblood oxbow oxbows oxbridge oxcart oxcarts oxen oxeye oxeyes oxford oxfords oxfordshire oxheart oxhearts oxidant oxidants oxidase oxidases oxidasic oxidation oxidations oxidative oxidatively oxide oxides oxidic oxidizable oxidization oxidizations oxidize oxidized oxidizer oxidizers oxidizes oxidizing oxidoreductase oxidoreductases oxime oximes oximeter oximeters oximetric oximetrically oximetry oxlip oxlips oxo oxon oxonian oxonians oxpecker oxpeckers oxtail oxtails oxter oxters oxtongue oxtongues oxus oxyacetylene oxyacid oxyacids oxycephalic oxycephalies oxycephalous oxycephaly oxycodone oxycodones oxygen oxygenase oxygenases oxygenate oxygenated oxygenates oxygenating oxygenation oxygenations oxygenator oxygenators oxygenic oxygenically oxygenize oxygenized oxygenizes oxygenizing oxygenless oxygenous oxyhemoglobin oxyhemoglobins oxyhydrogen oxymetazoline oxymetazolines oxymora oxymoron oxymoronic oxymoronically oxymorons oxyphenbutazone oxyphenbutazones oxyphilic oxysulfide oxysulfides oxytetracycline oxytetracyclines oxytocia oxytocias oxytocic oxytocics oxytocin oxytocins oxytone oxytones oxyuriasis oyer oyes oyesses oyez oyster oystercatcher oystercatchers oystered oystering oysterman oystermen oysters oz ozark ozarkian ozarkians ozarks ozocerite ozocerites ozokerite ozokerites ozonate ozonated ozonates ozonating ozonation ozonations ozone ozonic ozonide ozonides ozonization ozonizations ozonize ozonized ozonizer ozonizers ozonizes ozonizing ozonosphere ozonospheric ozonospherical ozonous ozostomia ozostomias p pa pa'anga pablum pablums pabulum pac paca pacas pace paced pacemaker pacemakers pacemaking pacer pacers paces pacesetter pacesetters pacesetting pacha pachas pachinko pachinkos pachisi pachisis pachouli pachoulis pachuco pachucos pachyderm pachydermal pachydermatous pachydermic pachydermous pachyderms pachysandra pachysandras pachytene pachytenes pacifarin pacifarins pacifiable pacific pacifical pacifically pacification pacifications pacificator pacificators pacificatory pacificism pacificisms pacificist pacificists pacified pacifier pacifiers pacifies pacifism pacifist pacifistic pacifistically pacifists pacify pacifying pacing pacinian pack packability packable package packaged packager packagers packages packaging packagings packboard packboards packed packer packers packet packets packhorse packhorses packing packinghouse packinghouses packings packman packmen packs packsack packsacks packsaddle packsaddles packthread packthreads pacs pact pacts pad padauk padauks padded padder padders paddies padding paddings paddle paddleball paddleballs paddleboard paddleboards paddleboat paddleboats paddled paddlefish paddlefishes paddler paddlers paddles paddling paddlings paddock paddocked paddocking paddocks paddy paderborn padi padis padishah padishahs padless padlock padlocked padlocking padlocks padouk padouks padova padre padres padrone padrones padroni padronism pads padua paduan paduans paduasoy paduasoys paean paeanistic paeans paedogeneses paedogenesis paedogenetic paedogenetically paedogenic paedomorph paedomorphic paedomorphism paedomorphisms paedomorphoses paedomorphosis paedomorphs paella paellas paeon paeons pagan pagandom pagandoms paganini paganish paganism paganization paganizations paganize paganized paganizer paganizers paganizes paganizing pagans page pageant pageantries pageantry pageants pageboy pageboys paged pageful pagefuls pager pagers pages paginal paginate paginated paginates paginating pagination paginations paging pagoda pagodas pah pahlavi pahlavis paid pail pailful pailfuls paillard paillards paillasse paillasses paillette pailletted paillettes pails pain pained painful painfuller painfullest painfully painfulness paining painkiller painkillers painkilling painless painlessly painlessness pains painstaking painstakingly paint paintability paintable paintbrush paintbrushes painted painter painterliness painterly painters painting paintings paints paintwork pair paired pairing pairings pairs paisa paisan paisano paisanos paisans paisas paise paisley paisleys paiute paiutes pajama pajamaed pajamas pakeha pakehas pakistan pakistani pakistanis pal palace palaces paladin paladins palaestra palankeen palankeens palanquin palanquins palapa palapas palatability palatable palatableness palatably palatal palatalization palatalizations palatalize palatalized palatalizes palatalizing palatally palatals palate palates palatial palatially palatialness palatinate palatinates palatine palatines palatino palau palaver palavered palavering palavers palawan palazzi palazzo palazzos pale palea paleae paleal palearctic paled paleethnologic paleethnological paleethnologies paleethnology paleface palefaces palely paleness paleoanthropic paleoanthropologic paleoanthropological paleoanthropologist paleoanthropologists paleoanthropology paleobiochemical paleobiochemistries paleobiochemistry paleobiogeographic paleobiogeographical paleobiogeography paleobiologic paleobiological paleobiologist paleobiologists paleobiology paleobotanic paleobotanical paleobotanically paleobotanist paleobotanists paleobotany paleocene paleoclimatologist paleoclimatologists paleoclimatology paleoecologic paleoecological paleoecologist paleoecologists paleoecology paleogene paleogeographic paleogeographical paleogeographically paleogeography paleographer paleographers paleographic paleographical paleographically paleography paleolith paleolithic paleoliths paleomagnetic paleomagnetically paleomagnetism paleomagnetist paleomagnetists paleontologic paleontological paleontologist paleontologists paleontology paleopathological paleopathologist paleopathologists paleopathology paleozoic paleozoological paleozoologist paleozoologists paleozoology paler palermo pales palest palestine palestinian palestinians palestra palestrae palestral palestras palestrian palestrina palette palettes paley palfrey palfreys pali palier paliest palimony palimpsest palimpsests palindrome palindromes palindromic palindromist palindromists paling palingeneses palingenesis palingenetic palingenetically palings palinode palinodes palisade palisaded palisades palisading palish pall palladia palladian palladianism palladic palladio palladium palladiums palladous pallas pallbearer pallbearers palled pallet palletization palletizations palletize palletized palletizer palletizers palletizes palletizing pallets pallette pallettes pallia pallial palliasse palliasses palliate palliated palliates palliating palliation palliations palliative palliatively palliatives palliator palliators pallid pallidly pallidness pallier palliest palling pallium palliums pallor pallors palls pally palm palma palmar palmary palmas palmate palmated palmately palmatifid palmation palmations palmatisect palmed palmer palmers palmerston palmerworm palmerworms palmette palmettes palmetto palmettoes palmettos palmful palmfuls palmier palmiest palming palmist palmister palmisters palmistry palmists palmitate palmitates palmitic palmitin palmitins palmlike palms palmy palmyra palmyras palomar palomino palominos palooka palookas palouse palouses paloverde paloverdes palp palpability palpable palpably palpal palpate palpated palpates palpating palpation palpations palpator palpators palpatory palpebra palpebrae palpebral palpebras palpi palpitant palpitate palpitated palpitates palpitating palpitatingly palpitation palpitations palps palpus pals palsgrave palsgraves palship palships palsied palsies palsy palsying palter paltered palterer palterers paltering palters paltrier paltriest paltrily paltriness paltry paludal paludism paludisms paly palynologic palynological palynologically palynologist palynologists palynology pam pamby pamir pamlico pampa pampas pampean pamper pampered pamperer pamperers pampering pampero pamperos pampers pamphlet pamphletary pamphleteer pamphleteered pamphleteering pamphleteers pamphlets pamplona pamprodactylous pan panacea panacean panaceas panache panaches panada panadas panama panamanian panamanians panamint panatela panatelas panay pancake pancaked pancakes pancaking pancetta pancettas panchax panchaxes panchen panchromatic panchromatism pancratium pancratiums pancreas pancreases pancreatectomies pancreatectomized pancreatectomy pancreatic pancreatin pancreatins pancreatitis pancreozymin pancreozymins pancytopenia pancytopenias panda pandaemonium pandanaceous pandanus pandanuses pandar pandarus pandas pandean pandect pandects pandemic pandemics pandemoniac pandemonium pander pandered panderer panderers pandering panders pandied pandies pandit pandits pandora pandore pandores pandowdies pandowdy pandurate panduriform pandy pandying pane paned panegyric panegyrical panegyrically panegyrics panegyrist panegyrists panegyrize panegyrized panegyrizes panegyrizing panel paneled paneling panelings panelist panelists panelization panelizations panelize panelized panelizes panelizing panelled panelling panellings panels panencephalitis panes panetela panetelas panetella panetellas panettone panettones panettoni panfish panfishes panfried panfries panfry panfrying panful panfuls pang panga pangaea pangas pangea panged pangenesis pangenetic pangenetically panging pangloss panglossian pangola pangolin pangolins pangram pangrammatic pangrams pangs panhandle panhandled panhandler panhandlers panhandles panhandling panhellenic panhuman panic panicked panicking panicky panicle panicled panicles panics paniculate paniculated paniculately panicum panicums panier paniers panini panjabi panjandrum panjandrums panky panleucopenia panleukopenia panmictic panmixia panmixias panmixis panne panned pannes pannier panniered panniers pannikin pannikins panning pannonia pannonian pannonians panocha panochas panoche panoches panoplied panoplies panoply panoptic panoptical panorama panoramas panoramic panoramically panpipe panpipes pans pansexual pansexuality pansies panspermia panspermias pansy pant pantagruel pantagruelian pantagruelism pantagruelist pantagruelists pantalet pantalets pantalette pantalettes pantalone pantalones pantaloon pantaloons pantdress pantdresses pantechnicon pantechnicons panted pantheism pantheist pantheistic pantheistical pantheistically pantheists pantheon pantheons panther panthers pantie panties pantile pantiled pantiles panting pantingly pantisocracies pantisocracy pantisocratic pantisocratical pantisocratist pantisocratists panto pantoffle pantoffles pantofle pantofles pantograph pantographic pantographs pantomime pantomimed pantomimes pantomimic pantomiming pantomimist pantomimists pantos pantothenate pantothenates pantothenic pantoum pantoums pantries pantropic pantropical pantry pantryman pantrymen pants pantsuit pantsuited pantsuits panty pantyhose pantywaist pantywaists panzer panzers pap papa papacies papacy papago papagos papain papains papal papally papanicolaou paparazzi paparazzo papas papaverine papaverines papaw papaws papaya papayas papeete paper paperback paperbacked paperbacks paperboard paperboards paperbound paperboy paperboys paperclip paperclips papercraft papered paperer paperers papergirl papergirls paperhanger paperhangers paperhanging paperiness papering paperings paperknife paperknives paperless papermaker papermakers papermaking papers paperweight paperweights paperwork papery papeterie papeteries paphian paphians paphos papiamento papiamentu papier papilionaceous papilla papillae papillary papillate papilloma papillomas papillomata papillomatous papillomavirus papillomaviruses papillon papillons papillose papillote papillotes papist papistic papistry papists papoose papooses papovavirus papovaviruses pappataci pappi pappier pappies pappiest pappose pappous pappus pappy paprika paprikas paps papua papuan papuans papula papulae papular papule papules papyri papyrologic papyrological papyrologist papyrologists papyrology papyrus papyruses par para parabioses parabiosis parabiotic parabiotically parablast parablastic parablasts parable parables parabola parabolas parabolic parabolical parabolically paraboloid paraboloidal paraboloids paracelsus parachute parachuted parachuter parachuters parachutes parachutic parachuting parachutist parachutists paraclete parade paraded parader paraders parades paradichlorobenzene paradichlorobenzenes paradiddle paradiddles paradigm paradigmatic paradigmatically paradigms parading paradisaic paradisaical paradisaically paradisal paradisally paradise paradises paradisiac paradisiacal paradisiacally paradisial paradisical parador paradores paradors paradox paradoxes paradoxical paradoxicality paradoxically paradoxicalness paradrop paradropped paradropping paradrops paraesthesia paraffin paraffined paraffinic paraffining paraffins parafoil parafoils paraformaldehyde paraformaldehydes paragenesia paragenesis paragenetic paragenetically paragon paragoned paragoning paragons paragraph paragraphed paragrapher paragraphers paragraphic paragraphical paragraphing paragraphs paraguay paraguayan paraguayans parainfluenza parajournalism parajournalist parajournalistic parajournalists parakeet parakeets paralanguage paraldehyde paralegal paralegals paralinguistic paralinguistics paralipomenon parallactic parallax parallaxes parallel paralleled parallelepiped parallelepipeds paralleling parallelism parallelisms parallelled parallelling parallelogram parallelograms parallels paralogism paralogisms paralogist paralogistic paralogists paralympian paralympians paralympic paralyses paralysis paralytic paralytically paralytics paralyzation paralyzations paralyze paralyzed paralyzer paralyzers paralyzes paralyzing paralyzingly paramagnet paramagnetic paramagnetically paramagnetism paramagnets paramaribo paramatta paramattas paramecia paramecium parameciums paramedic paramedical paramedics parament paramenta paraments parameter parameterization parameterizations parameterize parameterized parameterizes parameterizing parameters parametric parametrical parametrically parametrization parametrizations parametrize parametrized parametrizes parametrizing paramilitaries paramilitary paramnesia paramo paramorph paramorphic paramorphine paramorphines paramorphism paramorphisms paramorphous paramorphs paramos paramount paramountcy paramountly paramour paramours paramylon paramylons paramylum paramylums paramyxovirus paramyxoviruses parang parangs paranoia paranoiac paranoiacs paranoic paranoically paranoics paranoid paranoidal paranoids paranormal paranormality paranormally paranymph paranymphs parapareses paraparesis parapet parapeted parapets paraph paraphernalia paraphrasable paraphrase paraphrased paraphraser paraphrasers paraphrases paraphrasing paraphrastic paraphrastical paraphrastically paraphs paraphyses paraphysis paraplegia paraplegic paraplegics parapodia parapodial parapodium parapraxes parapraxis paraprofessional paraprofessionals parapsychological parapsychologist parapsychologists parapsychology paraquat paraquats pararosaniline pararosanilines paras parasail parasailed parasailer parasailers parasailing parasails parasang parasangs paraselenae paraselene paraselenic parasensorily parasensory parasexual parasexuality parashah parasite parasites parasitic parasitical parasitically parasiticidal parasiticide parasiticides parasitism parasitization parasitizations parasitize parasitized parasitizes parasitizing parasitoid parasitoids parasitologic parasitological parasitologically parasitologist parasitologists parasitology parasitoses parasitosis parasol parasoled parasols parasomnia parasomnias parastatal parastatals parasympathetic parasympathetically parasympathetics parasympathomimetic parasympathomimetics parasyntheses parasynthesis parasynthetic paratactic paratactical paratactically parataxis parathion parathions parathormone parathormones parathyroid parathyroidectomies parathyroidectomized parathyroidectomy parathyroids paratroop paratrooper paratroopers paratroops paratyphoid paravane paravanes paraxial parboil parboiled parboiling parboils parbuckle parbuckled parbuckles parbuckling parcae parcel parceled parceling parcelled parcelling parcels parcenaries parcenary parcener parceners parch parched parchedness parcheesi parches parching parchment parchments pard pardi pardie pardner pardners pardon pardonable pardonableness pardonably pardoned pardoner pardoners pardoning pardons pards pardy pare pared paregoric paregorics parenchyma parenchymal parenchymatous parenchymatously parent parentage parental parentally parented parenteral parenterally parentheses parenthesis parenthesize parenthesized parenthesizes parenthesizing parenthetic parenthetical parenthetically parenthood parenting parentis parentless parents parenty pareo pareos parer parers pares pareses paresis paresthesia paresthetic paretic paretically paretics pareu pareus pareve parfait parfaits parfleche parfleches parfocal parfocality parfocalize parfocalized parfocalizes parfocalizing parge parged parges parget pargeted pargeting pargets pargetted pargetting parging pargyline pargylines parhelia parhelic parhelion pari pariah pariahs parian parians paribus paricutin paries parietal parietals parietes paring parings paripinnate paris parish parishes parishioner parishioners parisian parisians parisienne parities parity park parka parkas parked parker parkers parking parkinson parkinson's parkinsonian parkinsonism parkinsonisms parkland parklands parklike parks parkway parkways parlance parlances parlando parlante parlay parlayed parlaying parlays parle parled parles parley parleyed parleying parleys parliament parliamentarian parliamentarians parliamentary parliaments parling parlor parlors parlous parlously parma parmenides parmesan parmesans parmigiana parmigiano parnassian parnassians parnassus parnassós parnell parochial parochialism parochialist parochialists parochially parodic parodical parodied parodies parodist parodistic parodists parody parodying parol parole paroled parolee parolees paroles paroling parols paronomasia paronomasial paronomasias paronomastic paronomastically paronychia paronychial paronychias paronym paronymic paronymous paronyms paros parosmia parosmias parotid parotidectomies parotidectomy parotiditis parotids parotitic parotitis parous parousia paroxysm paroxysmal paroxysmally paroxysms paroxytone paroxytones parquet parqueted parqueting parquetries parquetry parquets parr parrakeet parrakeets parral parrals parramatta parramattas parred parrel parrels parricidal parricidally parricide parricides parried parries parring parrot parroted parroter parroters parrotfish parrotfishes parroting parrots parrs parry parrying pars parse parsec parsecs parsed parsee parseeism parsees parser parsers parses parsi parsifal parsiism parsimonious parsimoniously parsimoniousness parsimony parsing parsis parsley parsleyed parsleys parslied parsnip parsnips parson parsonage parsonages parsons part partake partaken partaker partakers partakes partaking parte parted parterre parterres parthenocarpic parthenocarpically parthenocarpy parthenogenesis parthenogenetic parthenogenetically parthenogenone parthenogenones parthenon parthia parthian parthians parti partial partialities partiality partially partialness partials partibility partible participance participant participants participate participated participates participating participation participational participations participative participator participators participatory participial participially participials participle participles particle particleboard particles particular particularism particularist particularistic particularists particularities particularity particularization particularizations particularize particularized particularizer particularizers particularizes particularizing particularly particulars particulate particulates partied parties parting partings partis partisan partisanly partisans partisanship partisanships partita partitas partite partition partitioned partitioner partitioners partitioning partitionings partitionist partitionists partitionment partitionments partitions partitive partitively partitives partizan partizans partlet partlets partly partner partnered partnering partnerless partners partnership partnerships parton partons partook partout partridge partridgeberry partridges parts parturiency parturient parturifacient parturifacients parturition parturitions partway party partyer partyers partygoer partygoers partying parure parures parvati parve parvenu parvenue parvenues parvenus parvis parvise parvises parvo parvos parvovirus parvoviruses pará pas pasadena pascal pascals pasch pascha paschal pase paseo paseos pases pash pasha pashas pashes pashto pashtun pashtuns pasiphaë paso pasqueflower pasqueflowers pasquinade pasquinaded pasquinader pasquinaders pasquinades pasquinading pass passable passableness passably passacaglia passacaglias passade passades passado passadoes passados passage passaged passages passageway passageways passagework passageworks passaging passamaquoddies passamaquoddy passant passband passbands passbook passbooks passchendaele passe passed passel passels passementerie passementeries passenger passengers passepied passepieds passer passerby passerine passerines passers passersby passes passibility passible passim passing passingly passings passion passional passionals passionate passionately passionateness passionflower passionflowers passionist passionists passionless passionlessly passions passiontide passiontides passivate passivated passivates passivating passivation passivations passivator passivators passive passively passiveness passives passivism passivisms passivist passivists passivity passkey passkeys passover passovers passport passports passu password passwords passé past pasta pastas paste pasteboard pasteboards pasted pastedown pastedowns pastel pastelist pastelists pastellist pastellists pastels paster pastern pasternak pasterns pasters pastes pasteup pasteups pasteur pasteurization pasteurizations pasteurize pasteurized pasteurizer pasteurizers pasteurizes pasteurizing pasticci pasticcio pasticcios pastiche pastiches pasticheur pasticheurs pastier pasties pastiest pastil pastille pastilles pastils pastime pastimes pastina pastiness pasting pastis pastises pastless pastness pastor pastoral pastorale pastorales pastorali pastoralism pastoralisms pastoralist pastoralists pastoralization pastoralizations pastoralize pastoralized pastoralizes pastoralizing pastorally pastoralness pastorals pastorate pastorates pastored pastoring pastorium pastoriums pastors pastorship pastorships pastrami pastramis pastries pastromi pastromis pastry pasts pasturable pasturage pasture pastured pastureland pasturelands pasturer pasturers pastures pasturing pasty pat pataca patacas patagia patagial patagium patagonia patagonian patagonians pataphysics patas patch patchable patchboard patchboards patched patcher patchers patches patchier patchiest patchily patchiness patching patchouli patchoulies patchoulis patchouly patchwork patchworks patchy pate pated patella patellae patellar patellate patelliform paten patency patens patent patentability patentable patented patentee patentees patenting patently patentor patentors patents pater paterfamilias paterfamiliases paternal paternalism paternalist paternalistic paternalistically paternalists paternally paternities paternity paternoster paternosters paters pates path pathan pathans pathbreaking pathetic pathetical pathetically pathfinder pathfinders pathfinding pathless pathlessness pathname pathobiology pathogen pathogeneses pathogenesis pathogenetic pathogenic pathogenically pathogenicity pathogenies pathogens pathogeny pathognomonic pathography pathologic pathological pathologically pathologies pathologist pathologists pathology pathophysiologic pathophysiological pathophysiologist pathophysiologists pathophysiology pathos paths pathway pathways pathétique patience patient patiently patients patin patina patinae patinaed patinas patinate patinated patinates patinating patination patinations patine patined patines patining patins patio patios patisserie patisseries patissier patissiers patly patmos patna patness patois patresfamilias patriarch patriarchal patriarchalism patriarchally patriarchate patriarchates patriarchic patriarchies patriarchs patriarchy patricia patrician patricianly patricians patriciate patriciates patricidal patricide patricides patrick patriclinous patrilineage patrilineages patrilineal patrilocal patrilocally patrimonial patrimonially patrimonies patrimony patriot patriotic patriotically patriotism patriots patristic patristical patristically patristics patroclinous patroclus patrol patrolled patroller patrollers patrolling patrolman patrolmen patrols patrolwoman patrolwomen patron patronage patronal patroness patronesses patronization patronizations patronize patronized patronizer patronizers patronizes patronizing patronizingly patrons patronymic patronymically patronymics patroon patroons pats patsies patsy patted patten pattens patter pattered patterer patterers pattering pattern patterned patterning patternings patternless patternmaker patternmakers patternmaking patterns patters pattie patties patting patty pattypan pattypans patulent patulous patulously patulousness patzer patzers paucity paul pauline paulist paulists paulo paulownia paulownias paunch paunches paunchier paunchiest paunchiness paunchy pauper pauperism pauperization pauperizations pauperize pauperized pauperizes pauperizing paupers paupiette paupiettes pausanias pause paused pauses pausing pavan pavane pavanes pavans pavarotti pave paved paveed pavement pavements paver pavers paves pavia pavid pavilion pavilioned pavilioning pavilions paving pavings pavis pavises pavisse pavisses pavlov pavlova pavlovian pavo pavonine pavé paw pawed pawer pawers pawing pawkier pawkiest pawky pawl pawls pawn pawnable pawnage pawnages pawnbroker pawnbrokers pawnbroking pawned pawnee pawnees pawner pawners pawning pawnor pawnors pawns pawnshop pawnshops pawpaw pawpaws paws pax pay payable payables payback paybacks paycheck paychecks payday paydays payed payee payees payer payers paying payload payloader payloads paymaster paymasters payment payments paynim paynims payoff payoffs payola payolas payor payors payout payouts payphone payphones payroll payrolls pays pc pcs pe pea peabody peace peaceable peaceableness peaceably peaceful peacefully peacefulness peacekeeper peacekeepers peacekeeping peacemaker peacemakers peacemaking peacenik peaceniks peacetime peacetimes peach peached peaches peachick peachicks peachier peachiest peachiness peaching peachy peacock peacocked peacocking peacockish peacocks peacocky peafowl peafowls peag peage peages peags peahen peahens peak peaked peakedness peaking peaks peaky peal pealed pealike pealing peals pean peans peanut peanuts pear pearl pearled pearler pearlers pearlescence pearlescent pearlier pearliest pearliness pearling pearlite pearlites pearlitic pearlized pearls pearly pears peart peartly peas peasant peasantry peasants peascod peascods pease peasecod peasecods peashooter peashooters peat peats peaty peavey peaveys peavies peavy peavys pebble pebbled pebbles pebbling pebbly pec pecan pecans peccability peccable peccadillo peccadilloes peccadillos peccancies peccancy peccant peccantly peccaries peccary peccavi peccavis peck pecked pecker peckers peckerwood peckerwoods pecking peckish pecks pecksniffian pecky pecorino pecorinos pecs pectase pectases pectate pectates pecten pectens pectic pectin pectinaceous pectinate pectinated pectination pectinations pectines pectinesterase pectinesterases pectinous pectins pectoral pectorals pectoris peculate peculated peculates peculating peculation peculations peculator peculators peculiar peculiarities peculiarity peculiarly peculiars pecuniarily pecuniary ped pedagog pedagogic pedagogical pedagogically pedagogics pedagogs pedagogue pedagogues pedagoguish pedagogy pedal pedaled pedaler pedalers pedalfer pedalfers pedaling pedalled pedaller pedallers pedalling pedalo pedalos pedals pedant pedantic pedantically pedantries pedantry pedants pedate peddle peddled peddler peddlers peddles peddling pederast pederastic pederasties pederasts pederasty pedes pedestal pedestaled pedestaling pedestalled pedestalling pedestals pedestrian pedestrianism pedestrianization pedestrianizations pedestrianize pedestrianized pedestrianizes pedestrianizing pedestrians pediatric pediatrician pediatricians pediatrics pediatrist pediatrists pedicab pedicabs pedicel pedicellar pedicellate pedicels pedicle pedicled pedicles pedicular pediculate pediculates pediculosis pediculous pedicure pedicured pedicures pedicuring pedicurist pedicurists pediform pedigree pedigreed pedigrees pediment pedimental pedimented pediments pedipalp pedipalps pedlar pedlars pedocal pedocalic pedocals pedodontia pedodontias pedodontics pedodontists pedogeneses pedogenesis pedogenetic pedogenic pedologic pedological pedologically pedologist pedologists pedology pedometer pedometers pedomorph pedomorphism pedomorphisms pedomorphoses pedomorphosis pedomorphs pedophile pedophiles pedophilia pedophiliac pedophiliacs pedophilic peduncle peduncled peduncles peduncular pedunculate pedunculated pee peed peeing peek peekaboo peeked peeking peeks peel peelable peeled peeler peelers peeling peelings peels peen peened peening peens peep peeped peeper peepers peephole peepholes peeping peeps peepshow peepshows peepul peepuls peer peerage peerages peered peeress peeresses peering peerless peerlessly peerlessness peers pees peetweet peetweets peeve peeved peeves peeving peevish peevishly peevishness peewee peewees peewit peewits peg pegasus pegboard pegboards pegged pegging pegmatite pegmatitic pegs pehlevi peignoir peignoirs pein peined peining peins pejoration pejorations pejorative pejoratively pejoratives pekan pekans peke pekes pekin pekinese peking pekingese pekins pekoe pekoes pelage pelages pelagian pelagianism pelagians pelagic pelargonic pelargonium pelargoniums pelasgian pelasgians pelasgic pelecypod pelecypods pelerine pelerines pelew pelf pelican pelicans pelion pelisse pelisses pelite pelites pelitic pell pellagra pellagrin pellagrins pellagrous pellet pelletal pelleted pelleting pelletization pelletizations pelletize pelletized pelletizer pelletizers pelletizes pelletizing pellets pellicle pellicles pellicular pellitories pellitory pellucid pellucida pellucidae pellucidity pellucidly pellucidness pelmet pelmets peloponnese peloponnesian peloponnesians peloponnesos peloponnesus peloria pelorias peloric pelorus peloruses pelota pelotas pelt peltate peltately pelted pelter pelters pelting peltries peltry pelts pelves pelvic pelvimeter pelvimeters pelvimetry pelvis pelvises pelycosaur pelycosaurs pelée pemba pembroke pemican pemicans pemmican pemmicans pemoline pemolines pemphigous pemphigus pemphiguses pen penal penalization penalizations penalize penalized penalizes penalizing penally penalties penalty penance penanced penances penancing penang penates pence pencel pencels penchant penchants pencil penciled penciler pencilers penciling pencilled penciller pencillers pencilling pencils pendant pendants pendelikón pendency pendent pendentive pendently pendents pending pendular pendulous pendulously pendulousness pendulum pendulums penelope peneplain peneplains peneplane peneplanes penes penetrability penetrable penetrably penetralia penetrameter penetrameters penetrance penetrances penetrant penetrants penetrate penetrated penetrates penetrating penetratingly penetration penetrations penetrative penetrator penetrators penetrometer penetrometers penghu pengo pengos penguin penguins penh penholder penholders penicillamine penicillamines penicillate penicillately penicillation penicillations penicillia penicillin penicillinase penicillinases penicillium penicilliums penicuik penile peninsula peninsular peninsulas penis penises penitence penitences penitent penitente penitentes penitential penitentially penitentials penitentiaries penitentiary penitently penitents penknife penknives penlight penlights penlite penlites penman penmanship penmen penn penna pennaceous pennae penname pennames pennant pennants pennate pennated penne penned penner penners penni pennia pennies penniless pennilessly pennilessness pennine pennines penning pennis pennon pennoncel pennoncelle pennoncelles pennoncels pennoned pennons pennsylvania pennsylvanian pennsylvanians penny pennycress pennycresses pennyroyal pennyroyals pennyweight pennyweights pennywhistle pennywhistles pennywise pennywort pennyworth pennyworths pennyworts penobscot penobscots penoche penological penologically penologist penologists penology penoncel penoncels pens pensil pensile pensils pension pensionable pensionaries pensionary pensione pensioned pensioner pensioners pensiones pensioning pensionless pensions pensive pensively pensiveness penstemon penstemons penstock penstocks pensée pensées pent pentachlorophenol pentachlorophenols pentacle pentacles pentad pentadactyl pentadactylate pentadactylism pentads pentagon pentagonal pentagonally pentagonese pentagons pentagram pentagrams pentagynous pentahedra pentahedral pentahedron pentahedrons pentamerism pentamerous pentameter pentameters pentamidine pentandrous pentane pentanes pentangle pentangles pentangular pentapeptide pentapeptides pentaploid pentaploids pentaploidy pentaquin pentaquine pentaquines pentaquins pentarchical pentarchies pentarchy pentastich pentastiches pentastome pentastomes pentateuch pentateuchal pentathlete pentathletes pentathlon pentathlons pentatonic pentavalent pentazocine pentazocines pentecost pentecostal pentecostalism pentecostalist pentecostalists pentecostals penthouse penthouses pentimenti pentimento pentlandite pentlandites pentobarbital pentobarbitone pentobarbitones pentosan pentosans pentose pentoses pentothal pentoxide pentoxides pentstemon pentstemons pentyl pentylenetetrazol pentylenetetrazols pentyls penuche penuches penuchi penuchis penuchle penuckle penult penultima penultimas penultimate penultimately penultimates penults penumbra penumbrae penumbral penumbras penumbrous penurious penuriously penuriousness penury penutian peon peonage peones peonies peons peony people peopled peoplehood peopleless peopler peoplers peoples peopling peoria peorias pep peperomia peperomias pepier pepiest pepino pepinos peplos peploses peplum peplumed peplums peplus pepluses pepo pepos pepped pepper pepperbox pepperboxes pepperbush pepperbushes peppercorn peppercorns peppercress peppercresses peppered pepperer pepperers peppergrass peppergrasses pepperidge pepperidges pepperiness peppering peppermint peppermints pepperminty pepperoni pepperonis peppers peppershaker peppershakers peppertree peppertrees pepperwood pepperwoods pepperwort pepperworts peppery peppier peppiest peppily peppiness pepping peppy peps pepsi pepsin pepsine pepsines pepsinogen pepsinogens pepsins peptic peptics peptidase peptidases peptide peptides peptidic peptidically peptidoglycan peptidoglycans peptization peptizations peptize peptized peptizer peptizers peptizes peptizing peptone peptones peptonic peptonization peptonizations peptonize peptonized peptonizes peptonizing pepys pequot pequots per peracid peracids peradventure peradventures perambulate perambulated perambulates perambulating perambulation perambulations perambulator perambulators perambulatory perborate perborates percale percales percaline percalines perceivable perceivably perceive perceived perceiver perceivers perceives perceiving percent percentage percentages percenter percenters percentile percentiles percentism percents percept perceptibility perceptible perceptibly perception perceptional perceptions perceptive perceptively perceptiveness perceptivity percepts perceptual perceptually perch perchance perched percher percheron percherons perchers perches perching perchlorate perchlorates perchloric perchlorid perchloride perchlorides perchlorids perchloroethylene perchloroethylenes perciatelli percipience percipiency percipient percipiently percipients percodan percoid percoidean percoids percolate percolated percolates percolating percolation percolations percolator percolators percurrent percuss percussed percusses percussing percussion percussionist percussionists percussions percussive percussively percussiveness percutaneous percutaneously percy perdie perdita perdition perdu perdue perdues perdurability perdurable perdurably perdure perdured perdures perduring perdus peregrinate peregrinated peregrinates peregrinating peregrination peregrinations peregrinator peregrinators peregrine peregrines pereion pereiopod pereiopods peremptorily peremptoriness peremptory perennate perennated perennates perennating perennation perennations perennial perennially perennials perentie perenties pereon pereopod pereopods perestroika perfect perfecta perfectas perfected perfecter perfecters perfectibility perfectible perfecting perfection perfectionism perfectionist perfectionistic perfectionists perfections perfective perfectively perfectiveness perfectives perfectivity perfectly perfectness perfecto perfectos perfects perfervid perfervidly perfervidness perfidies perfidious perfidiously perfidiousness perfidy perfoliate perfoliation perforable perforate perforated perforates perforating perforation perforations perforative perforator perforators perforce perform performability performable performance performances performative performatory performed performer performers performing performs perfume perfumed perfumer perfumeries perfumers perfumery perfumes perfuming perfunctorily perfunctoriness perfunctory perfusate perfusates perfuse perfused perfuses perfusing perfusion perfusionist perfusionists perfusions perfusive pergamum pergola pergolas perhaps perianth perianths periapt periapts periaqueductal pericardia pericardiac pericardial pericarditis pericardium pericarp pericarpial pericarps perichondral perichondria perichondrial perichondrium periclase periclases periclean pericles pericline periclines pericope pericopes pericrania pericranial pericranium pericycle pericycles pericyclic periderm peridermal peridermic periderms peridia peridial peridium peridot peridotic peridotite peridotites peridotitic peridots perigeal perigean perigee perigees perigynous perigyny perihelia perihelial perihelion perikarya perikaryal perikaryon peril periled periling perilla perillas perilled perilling perilous perilously perilousness perils perilune perilunes perilymph perilymphatic perilymphs perimeter perimeters perimetric perimetrical perimetrically perimorph perimorphic perimorphism perimorphous perimorphs perimysia perimysium perinatal perinatally perinatology perinea perineal perinephral perinephria perinephrial perinephric perinephrium perineum perineuria perineurial perineurium period periodic periodical periodically periodicals periodicities periodicity periodization periodizations periodontal periodontally periodontia periodontias periodontic periodontical periodontics periodontist periodontists periodontology periods perionychia perionychium periostea periosteal periosteous periosteum periostitic periostitis periostitises periostraca periostracum periotic peripatetic peripatetically peripateticism peripatetics peripatus peripatuses peripeteia peripeteias peripetia peripetias peripeties peripety peripheral peripherally peripherals peripheries periphery periphrases periphrasis periphrastic periphrastically periphytic periphytics periphyton periphytons periplasm periplasmic periplasms periplast periplasts periproct periprocts peripteral perique periques perisarc perisarcal perisarcous perisarcs periscope periscopes periscopic periscopical perish perishability perishable perishableness perishables perishably perished perishes perishing perisperm perisperms perissodactyl perissodactyla perissodactylous perissodactyls peristalses peristalsis peristaltic peristaltically peristomal peristome peristomes peristomial peristylar peristyle peristyles perithecia perithecial perithecium peritonaea peritonaeum peritonea peritoneal peritoneally peritoneum peritoneums peritonitis peritrich peritricha peritrichous peritrichously peritrichs perivisceral periwig periwigged periwigs periwinkle periwinkles perjure perjured perjurer perjurers perjures perjuries perjuring perjurious perjuriously perjury perk perked perkier perkiest perkily perkiness perking perks perky perlite perlites perlitic perm permaculture permacultures permafrost permalloy permanence permanencies permanency permanent permanently permanentness permanents permanganate permanganates permanganic permeabilities permeability permeable permeably permeance permeances permeant permease permeases permeate permeated permeates permeating permeation permeations permeative permed permethrin permian permillage perming permissibility permissible permissibleness permissibly permission permissions permissive permissively permissiveness permit permits permitted permittee permittees permitter permitters permitting permittivities permittivity perms permutability permutable permutably permutation permutational permutations permute permuted permutes permuting pernambuco pernicious perniciously perniciousness pernickety pernod peroneal peroral perorally perorate perorated perorates perorating peroration perorational perorations perovskite perovskites peroxidase peroxidases peroxide peroxided peroxides peroxidic peroxiding peroxisomal peroxisome peroxisomes peroxyacetyl perp perpend perpended perpendicular perpendicularity perpendicularly perpendiculars perpending perpends perpetrate perpetrated perpetrates perpetrating perpetration perpetrations perpetrator perpetrators perpetual perpetually perpetuance perpetuances perpetuate perpetuated perpetuates perpetuating perpetuation perpetuations perpetuator perpetuators perpetuities perpetuity perphenazine perphenazines perpignan perplex perplexed perplexedly perplexes perplexing perplexingly perplexities perplexity perps perquisite perquisites perrault perries perron perrons perry perse persecute persecuted persecutee persecutees persecutes persecuting persecution persecutional persecutions persecutive persecutor persecutors persecutory perseid perseides perseids persephone persepolis perseus perseverance perseverant perseverate perseverated perseverates perseverating perseveration perseverations perseverative persevere persevered perseveres persevering perseveringly persia persian persians persiflage persimmon persimmons persist persisted persistence persistency persistent persistently persister persisters persisting persists persnicketiness persnickety person persona personable personableness personably personae personage personages personal personalia personalism personalisms personalist personalistic personalists personalities personality personalization personalizations personalize personalized personalizes personalizing personally personals personalties personalty personas personate personated personates personating personation personations personative personator personators personhood personification personifications personified personifier personifiers personifies personify personifying personnel persons perspectival perspective perspectively perspectives perspex perspicacious perspicaciously perspicaciousness perspicacity perspicuity perspicuous perspicuously perspicuousness perspiration perspiratory perspire perspired perspires perspiring persuadable persuadably persuade persuaded persuader persuaders persuades persuading persuasibility persuasible persuasibleness persuasion persuasions persuasive persuasively persuasiveness pert pertain pertained pertaining pertains perter pertest perth pertinacious pertinaciously pertinaciousness pertinacity pertinence pertinency pertinent pertinently pertly pertness perturb perturbable perturbation perturbational perturbations perturbed perturbing perturbs pertussal pertussis peru perugia peruke peruked perukes perusable perusal perusals peruse perused peruser perusers peruses perusing peruvian peruvians pervade pervaded pervader pervaders pervades pervading pervasion pervasions pervasive pervasively pervasiveness perverse perversely perverseness perversion perversions perversities perversity perversive pervert perverted pervertedly pervertedness perverter perverters pervertible perverting perverts pervious perviously perviousness pes pesach pesade pesades pescadores peseta pesetas pesewa pesewas peshawar peskier peskiest peskily peskiness pesky peso pesos pessaries pessary pessimism pessimist pessimistic pessimistically pessimists pest pester pestered pesterer pesterers pestering pesters pesthole pestholes pesthouse pesthouses pesticidal pesticide pesticides pestiferous pestiferously pestiferousness pestilence pestilences pestilent pestilential pestilentially pestilently pestle pestled pestles pestling pesto pestos pests pesty pet petaampere petaamperes petabecquerel petabecquerels petabit petabits petabyte petabytes petacandela petacandelas petacoulomb petacoulombs petafarad petafarads petagram petagrams petahenries petahenry petahenrys petahertz petajoule petajoules petakelvin petakelvins petal petaled petaliferous petaline petalled petallike petaloid petalous petals petalumen petalumens petalux petameter petameters petamole petamoles petanewton petanewtons petaohm petaohms petapascal petapascals petaradian petaradians petard petards petasecond petaseconds petasiemens petasievert petasieverts petasos petasoses petasteradian petasteradians petasus petasuses petatesla petateslas petavolt petavolts petawatt petawatts petaweber petawebers petcock petcocks petechia petechiae petechial petechiate peter peter's petered petering peters petersburg petiolar petiolate petiole petioled petioles petiolule petiolules petit petite petiteness petites petition petitionary petitioned petitioner petitioners petitioning petitions petits petnapper petnappers petnapping petnappings petrale petrarch petrarchan petrel petrels petri petrifaction petrifactions petrification petrifications petrified petrifies petrify petrifying petrine petrochemical petrochemicals petrochemistries petrochemistry petrodollar petrodollars petrogenesis petrogenetic petroglyph petroglyphic petroglyphs petrograd petrographer petrographers petrographic petrographical petrographically petrography petrol petrolatum petroleum petrolic petroliferous petrologic petrological petrologically petrologist petrologists petrology petronel petronels petronius petropolitics petrosal petrous pets petted petter petters petti petticoat petticoated petticoats pettier pettiest pettifog pettifogged pettifogger pettifoggers pettifoggery pettifogging pettifogs pettily pettiness pettinesses petting pettis pettish pettishly pettishness pettiskirt pettiskirts pettislip pettislips pettitoes petty petulance petulancy petulant petulantly petunia petunias petuntse petuntses petuntze petuntzes peugeot pew pewee pewees pewholder pewholders pewit pewits pews pewter pewterer pewterers peyote peyotl peyotls pfennig pfennige pfennigs pfft ph phacoemulsification phacoemulsifications phaedra phaedrus phaeton phaetons phage phages phagocyte phagocytes phagocytic phagocytize phagocytized phagocytizes phagocytizing phagocytose phagocytosed phagocytoses phagocytosing phagocytosis phagocytotic phagosome phagosomes phalangal phalange phalangeal phalangean phalanger phalangers phalanges phalangist phalangists phalansterian phalansterianism phalansterians phalansteries phalanstery phalanx phalanxes phalarope phalaropes phalli phallic phallically phallicism phallocentric phallus phalluses phanerogam phanerogamic phanerogamous phanerogams phanerophyte phanerophytes phanerozoic phantasies phantasm phantasma phantasmagoria phantasmagorias phantasmagoric phantasmagorical phantasmagorically phantasmagories phantasmagory phantasmal phantasmata phantasmic phantasms phantasy phantom phantomlike phantoms pharaoh pharaohs pharaonic pharisaic pharisaical pharisaically pharisaicalness pharisaism pharisaisms pharisee phariseeism phariseeisms pharisees pharmaceutic pharmaceutical pharmaceutically pharmaceuticals pharmaceutics pharmacies pharmacist pharmacists pharmacodynamic pharmacodynamically pharmacodynamics pharmacogenetic pharmacogenetics pharmacogenomic pharmacogenomics pharmacognosist pharmacognosists pharmacognostic pharmacognostical pharmacognosy pharmacokinetic pharmacokinetics pharmacologic pharmacological pharmacologically pharmacologist pharmacologists pharmacology pharmacopeia pharmacopeial pharmacopeias pharmacopoeia pharmacopoeial pharmacopoeias pharmacopoeist pharmacopoeists pharmacotherapies pharmacotherapy pharmacy pharos pharoses pharyngal pharyngals pharyngeal pharyngeals pharyngectomies pharyngectomy pharynges pharyngitis pharyngitises pharyngocele pharyngoceles pharyngology pharyngoscope pharyngoscopes pharyngoscopy pharynx pharynxes phase phased phasedown phasedowns phaseout phaseouts phases phasic phasing phasmid phasmids phatic phatically phaëthon pheasant pheasants phellem phellems phelloderm phellodermal phelloderms phellogen phellogenic phellogens phenacaine phenacaines phenacetin phenacetins phenacite phenacites phenakite phenakites phenanthrene phenanthrenes phenarsazine phenazin phenazine phenazines phenazins phencyclidine phencyclidines phenelzine phenelzines phenetic phenetically pheneticist pheneticists phenetics phenix phenixes phenmetrazine phenmetrazines phenobarbital phenobarbitone phenobarbitones phenocopies phenocopy phenocryst phenocrystic phenocrysts phenol phenolate phenolates phenolic phenolics phenological phenologically phenologist phenologists phenology phenolphthalein phenolphthaleins phenols phenom phenomena phenomenal phenomenalism phenomenalisms phenomenalist phenomenalistic phenomenalistically phenomenalists phenomenally phenomenological phenomenologically phenomenologist phenomenologists phenomenology phenomenon phenomenons phenoms phenothiazine phenothiazines phenotype phenotypes phenotypic phenotypical phenotypically phenoxide phenoxides phenoxybenzamine phenoxybenzamines phentolamine phentolamines phenyl phenylalanine phenylalanines phenylbutazone phenylbutazones phenylene phenylenes phenylenevinylene phenylephrine phenylephrines phenylethylamine phenylethylamines phenylic phenylketonuria phenylketonurias phenylketonuric phenylketonurics phenylpropanolamine phenylpropanolamines phenyls phenylthiocarbamide phenylthiocarbamides phenylthiourea phenylthioureas phenytoin phenytoins pheochromocytoma pheochromocytomas pheochromocytomata pheresis pheromonal pheromone pheromones phew phi phial phials phidias philadelphia philadelphian philadelphians philadelphus philander philandered philanderer philanderers philandering philanders philanthropic philanthropical philanthropically philanthropies philanthropist philanthropists philanthropoid philanthropoids philanthropy philatelic philatelical philatelically philatelist philatelists philately philemon philharmonic philharmonics philhellene philhellenes philhellenic philhellenism philhellenist philhellenists philip philippi philippians philippic philippics philippine philippines philistia philistine philistines philistinism philistinisms phillips phillumenist phillumenists philoctetes philodendra philodendron philodendrons philologer philologers philologic philological philologically philologist philologists philology philomel philomela philomels philoprogenitive philoprogenitively philoprogenitiveness philosophe philosopher philosophers philosophes philosophic philosophical philosophically philosophies philosophize philosophized philosophizer philosophizers philosophizes philosophizing philosophy philter philtered philtering philters philtre philtred philtres philtring phimoses phimosis phiz phizes phlebitic phlebitides phlebitis phlebogram phlebograms phlebographic phlebography phlebology phlebosclerosis phlebotomic phlebotomical phlebotomies phlebotomist phlebotomists phlebotomize phlebotomized phlebotomizes phlebotomizing phlebotomus phlebotomy phlegethon phlegm phlegmatic phlegmatical phlegmatically phlegmy phloem phlogistic phlogiston phlogistons phlogopite phlogopites phlox phloxes phlyctaena phlyctaenae phlyctena phlyctenae phlyctenar phnom phobia phobias phobic phobics phobos phocine phocomelia phocomelias phoebe phoebes phoebus phoenicia phoenician phoenicians phoenix phoenixes phoenixlike phon phonate phonated phonates phonating phonation phonations phone phoned phonematic phoneme phonemes phonemic phonemically phonemicist phonemicists phonemics phones phonetic phonetical phonetically phonetician phoneticians phoneticist phoneticists phonetics phoney phoneyed phoneying phoneys phonic phonically phonics phonied phonier phonies phoniest phonily phoniness phoning phono phonocardiogram phonocardiograms phonocardiograph phonocardiographic phonocardiographs phonocardiography phonogram phonogramic phonogramically phonogrammic phonogrammically phonograms phonograph phonographer phonographers phonographic phonographically phonographist phonographists phonographs phonography phonolite phonolites phonolitic phonologic phonological phonologically phonologies phonologist phonologists phonology phonometric phonon phonons phonoreception phonoreceptions phonoreceptor phonoreceptors phonos phonoscope phonoscopes phonotactic phonotactics phonotype phonotypes phonotypic phonotypical phonotypically phonotypist phonotypists phonotypy phons phony phonying phooey phorate phorates phoresies phoresy phoronid phoronids phosgene phosphamidon phosphamidons phosphatase phosphatases phosphate phosphates phosphatic phosphatide phosphatides phosphatidic phosphatization phosphatizations phosphatize phosphatized phosphatizes phosphatizing phosphaturia phosphaturias phosphaturic phosphene phosphenes phosphid phosphide phosphides phosphids phosphin phosphine phosphines phosphins phosphite phosphites phosphocreatin phosphocreatine phosphocreatines phosphocreatins phosphofructokinase phosphofructokinases phosphoinositide phospholipid phospholipids phosphonium phosphoniums phosphoprotein phosphoproteins phosphor phosphorate phosphorated phosphorates phosphorating phosphore phosphores phosphoresce phosphoresced phosphorescence phosphorescent phosphorescently phosphoresces phosphorescing phosphoric phosphorism phosphorisms phosphorite phosphorites phosphoritic phosphorolysis phosphorolytic phosphorous phosphors phosphorus phosphoryl phosphorylase phosphorylases phosphorylate phosphorylated phosphorylates phosphorylating phosphorylation phosphorylations phosphorylative phosphoryls phot photic photically photo photoactive photoactivity photoautotroph photoautotrophic photoautotrophically photoautotrophs photobiologic photobiological photobiologist photobiologists photobiology photobiotic photocathode photocathodes photocell photocells photochemical photochemically photochemist photochemistry photochemists photochromic photochromism photocoagulate photocoagulated photocoagulates photocoagulating photocoagulation photocoagulations photocompose photocomposed photocomposer photocomposers photocomposes photocomposing photocomposition photoconduction photoconductive photoconductivities photoconductivity photocopied photocopier photocopiers photocopies photocopy photocopying photocurrent photocurrents photodecomposition photodecompositions photodegradable photodetector photodetectors photodiode photodiodes photodisintegrate photodisintegrated photodisintegrates photodisintegrating photodisintegration photodisintegrations photodissociate photodissociated photodissociates photodissociating photodissociation photodissociations photodrama photodramas photoduplicate photoduplicated photoduplicates photoduplicating photoduplication photoduplications photodynamic photodynamically photodynamics photoed photoelectric photoelectrical photoelectrically photoelectron photoelectronic photoelectrons photoemission photoemissions photoemissive photoengrave photoengraved photoengraver photoengravers photoengraves photoengraving photoengravings photoexcitation photoexcitations photoexcited photofinisher photofinishers photofinishing photofinishings photoflash photoflashes photoflood photofloods photofluorogram photofluorograms photofluorographic photofluorography photog photogelatin photogene photogenes photogenic photogenically photogeologic photogeological photogeologist photogeologists photogeology photogram photogrammetric photogrammetrist photogrammetrists photogrammetry photograms photograph photographable photographed photographer photographers photographic photographical photographically photographing photographs photography photogravure photogravures photogs photoheliograph photoheliographs photoinduced photoinduction photoinductions photoinductive photoing photointerpretation photointerpreter photointerpreters photoionization photoionizations photoionize photoionized photoionizes photoionizing photojournalism photojournalist photojournalistic photojournalists photokinesis photokinetic photolithograph photolithographed photolithographer photolithographers photolithographic photolithographically photolithographing photolithographs photolithography photoluminescence photolysis photolytic photolytically photolyzable photolyze photolyzed photolyzes photolyzing photomap photomapped photomapping photomaps photomask photomasks photomechanical photomechanically photometer photometers photometric photometrical photometrically photometrist photometrists photometry photomicrograph photomicrographed photomicrographer photomicrographers photomicrographic photomicrographing photomicrographs photomicrography photomicroscope photomicroscopes photomicroscopic photomontage photomontages photomorphogenesis photomorphogenic photomosaic photomosaics photomultiplier photomural photomuralist photomuralists photomurals photon photonegative photonic photonics photons photonuclear photooxidation photooxidations photooxidative photooxidize photooxidized photooxidizes photooxidizing photoperiod photoperiodic photoperiodical photoperiodically photoperiodicities photoperiodicity photoperiodism photoperiodisms photoperiods photophase photophases photophilic photophilous photophobia photophobias photophobic photophore photophores photophosphorylation photophosphorylations photopia photopias photopic photoplay photoplays photopolarimeter photopolarimeters photopolymer photopolymers photopositive photoproduct photoproduction photoproductions photoproducts photoreaction photoreactions photoreactivating photoreactivation photoreactivations photoreception photoreceptive photoreceptor photoreceptors photoreconnaissance photoreduce photoreduced photoreduces photoreducing photoreduction photoreductions photoreproduction photoreproductions photoresist photoresists photorespiration photorespirations photos photosensitive photosensitivities photosensitivity photosensitization photosensitizations photosensitize photosensitized photosensitizer photosensitizers photosensitizes photosensitizing photoset photosets photosetter photosetters photosetting photosphere photospheres photospheric photostat photostatic photostats photostatted photostatting photosynthate photosynthates photosynthesis photosynthesize photosynthesized photosynthesizes photosynthesizing photosynthetic photosynthetically photosystem photosystems phototactic phototactically phototaxis phototaxises phototelegraphy phototherapeutic phototherapies phototherapy phototonic phototonus phototonuses phototoxic phototoxicity phototransistor phototransistors phototroph phototrophic phototrophically phototrophs phototropic phototropically phototropism phototube phototubes phototypeset phototypesets phototypesetter phototypesetters phototypesetting phototypographic phototypographical phototypographically phototypography photovoltaic photovoltaics phots phragmites phragmoplast phragmoplasts phrasal phrasally phrase phrased phrasemaker phrasemakers phrasemaking phrasemonger phrasemongering phrasemongers phraseogram phraseograms phraseograph phraseographic phraseographs phraseological phraseologies phraseologist phraseologists phraseology phrases phrasing phrasings phratric phratries phratry phreatic phreatophyte phreatophytes phreatophytic phrenetic phrenetical phrenic phrenitic phrenitis phrenologic phrenological phrenologist phrenologists phrenology phrensy phrenzied phrenzies phrenzy phrenzying phrygia phrygian phrygians phthalate phthalates phthalein phthaleine phthaleines phthaleins phthalic phthalin phthalins phthalocyanine phthalocyanines phthiriasis phthises phthisic phthisical phthisics phthisis phycobilin phycobilins phycocyanin phycocyanins phycoerythrin phycoerythrins phycological phycologist phycologists phycology phycomycete phycomycetes phycomycetous phyla phylacteries phylactery phylae phyle phyletic phyletically phylic phyllaries phyllary phyllite phyllites phyllitic phyllo phylloclad phylloclade phylloclades phylloclads phyllode phyllodes phyllodia phyllodial phyllodium phylloid phyllome phyllomes phyllomic phyllophagous phyllopod phyllopodan phyllopodans phyllopodous phyllopods phyllotactic phyllotactical phyllotaxes phyllotaxies phyllotaxis phyllotaxy phylloxera phylloxerae phylloxeran phylloxerans phylogenesis phylogenetic phylogenetically phylogenetics phylogenic phylogenies phylogeny phylum physiatrics physiatrist physiatrists physiatry physic physical physicalism physicalist physicalistic physicalists physicality physicalization physicalizations physicalize physicalized physicalizes physicalizing physically physicalness physicals physician physicians physicist physicists physicked physicking physicochemical physicochemically physics physiochemical physiocrat physiocratic physiocrats physiognomic physiognomical physiognomically physiognomies physiognomist physiognomists physiognomy physiographer physiographers physiographic physiographical physiographically physiography physiologic physiological physiologically physiologist physiologists physiology physiopathologic physiopathological physiopathologist physiopathologists physiopathology physiotherapeutic physiotherapist physiotherapists physiotherapy physique physiqued physiques physostigmin physostigmine physostigmines physostigmins physostomous phytane phytanes phytoalexin phytoalexins phytochemical phytochemically phytochemist phytochemistry phytochemists phytochrome phytochromes phytoflagellate phytoflagellates phytogenesis phytogenetic phytogenetical phytogenetically phytogenic phytogenous phytogeny phytogeographer phytogeographers phytogeographic phytogeographical phytogeographically phytogeography phytography phytohemagglutinin phytohemagglutinins phytohormone phytohormones phytol phytologic phytological phytology phytols phyton phytonic phytons phytopathogen phytopathogenic phytopathogens phytopathologic phytopathological phytopathologist phytopathologists phytopathology phytophagous phytoplankter phytoplankters phytoplankton phytoplanktonic phytoplanktons phytosociological phytosociologically phytosociologist phytosociologists phytosociology phytosterol phytosterols phytotoxic phytotoxicity pi pia piacenza piacular piaffe piaffed piaffer piaffers piaffes piaffing piaget pial pianism pianissimo pianissimos pianist pianistic pianistically pianistics pianists piano pianoforte pianofortes pianos pias piassaba piassabas piassava piassavas piaster piasters piastre piastres piazza piazzas piazze pibroch pibrochs pic pica picador picadores picadors picaninnies picaninny picante picara picaras picardy picaresque picaro picaroon picarooned picarooning picaroons picaros picas picasso picayune picayunes picayunish piccadilly piccalilli piccalillis piccata piccolo piccoloist piccoloists piccolos pice piceous pichiciego pichiciegos pick pickaninnies pickaninny pickax pickaxe pickaxed pickaxes pickaxing picked picker pickerel pickerels pickerelweed pickerelweeds pickers picket picketboat picketboats picketed picketer picketers picketing pickets pickier pickiest picking pickings pickle pickled pickles pickleworm pickleworms pickling picklock picklocks pickoff pickoffs pickpocket pickpockets pickproof picks pickthank pickthanks pickup pickups pickwick pickwickian picky picloram piclorams picnic picnicked picnicker picnickers picnicking picnicky picnics picoampere picoamperes picobecquerel picobecquerels picocandela picocandelas picocoulomb picocoulombs picofarad picofarads picogram picograms picohenries picohenry picohenrys picohertz picojoule picojoules picokelvin picokelvins picoline picolines picolumen picolumens picolux picometer picometers picomole picomoles piconewton piconewtons picoohm picoohms picopascal picopascals picoradian picoradians picornavirus picornaviruses picosecond picoseconds picosiemens picosievert picosieverts picosteradian picosteradians picot picoted picotee picotees picotesla picoteslas picoting picots picovolt picovolts picowatt picowatts picowave picowaved picowaves picowaving picoweber picowebers picquet picquets picrate picrates picric picrotoxic picrotoxin picrotoxins pics pict pictish pictogram pictograms pictograph pictographic pictographically pictographs pictography pictor pictorial pictorialism pictorialist pictorialists pictoriality pictorialization pictorializations pictorialize pictorialized pictorializes pictorializing pictorially pictorialness pictorials picts picture pictured picturephone picturephones pictures picturesque picturesquely picturesqueness picturing picturization picturizations picturize picturized picturizes picturizing picul piculs piddle piddled piddles piddling piddock piddocks pidgin pidginization pidginizations pidginize pidginized pidginizes pidginizing pidgins pie piebald piebalds piece pieced piecemeal piecer piecers pieces piecewise piecework pieceworker pieceworkers piecing piecrust piecrusts pied piedmont piedmontese piedmonts piegan piegans pieing pieplant pieplants pier pierce pierced piercer piercers pierces piercing piercingly pierian pierogi pierogies pierre pierrot piers pies pieta pietas pietermaritzburg pieties pietism pietist pietistic pietistical pietistically pietists piety pietà piezoelectric piezoelectrical piezoelectrically piezoelectricity piezometer piezometers piezometric piezometrical piezometry piffle piffled piffles piffling pig pigboat pigboats pigeon pigeonhole pigeonholed pigeonholer pigeonholers pigeonholes pigeonholing pigeonite pigeonites pigeons pigeonwing pigeonwings pigfish pigfishes pigged piggeries piggery piggier piggies piggiest piggin pigging piggins piggish piggishly piggishness piggledy piggy piggyback piggybacked piggybacking piggybacks pigheaded pigheadedly pigheadedness piglet piglets piglike pigment pigmentary pigmentation pigmentations pigmented pigmenting pigmentosa pigments pigmies pigmy pignoli pignolia pignut pignuts pigpen pigpens pigs pigskin pigskins pigsney pigsneys pigstick pigsticked pigsticker pigstickers pigsticking pigsticks pigsties pigsty pigtail pigtailed pigtails pigweed pigweeds piing pika pikake pikakes pikas pike piked pikeman pikemen pikeperch pikeperches piker pikers pikes pikestaff pikestaffs piki piking pilaf pilaff pilaffs pilafs pilar pilaster pilasters pilate pilatus pilau pilaw pilchard pilchards pile pilea pileate pileated piled pilei pileless piles pileum pileup pileups pileus pilewort pileworts pilfer pilferable pilferage pilfered pilferer pilferers pilfering pilferproof pilfers pilgarlic pilgarlics pilgrim pilgrimage pilgrimaged pilgrimages pilgrimaging pilgrims pili piliferous piliform piling pilings pilipino pill pillage pillaged pillager pillagers pillages pillaging pillar pillared pillaring pillarless pillars pillbox pillboxes pilled pilling pillion pillions pilloried pillories pillory pillorying pillow pillowcase pillowcases pillowed pillowing pillows pillowslip pillowslips pillowy pills pilocarpine pilocarpines pilose pilosity pilot pilotage piloted pilothouse pilothouses piloting pilotings pilotless pilots pilous pilsener pilseners pilsner pilsners piltdown pilular pilule pilules pilus pima piman pimas pimento pimentos pimiento pimientos piminy pimp pimped pimpernel pimpernels pimping pimple pimpled pimples pimply pimpmobile pimpmobiles pimps pin pinafore pinafored pinafores pinaster pinasters pinball pinballs pinbone pinbones pince pincer pincerlike pincers pinch pinchbeck pinchbecks pinchcock pinchcocks pinched pincher pinchers pinches pinching pinchpennies pinchpenny pincushion pincushions pindar pindaric pindling pine pineal pinealectomize pinealectomized pinealectomizes pinealectomizing pinealectomy pineapple pineapples pinecone pinecones pined pinedrops pineland pinelands pinene pinenes pineries pinery pines pinesap pinesaps pineta pinetum pinewood pinewoods piney pinfeather pinfeathers pinfish pinfishes pinfold pinfolded pinfolding pinfolds ping pinged pinger pingers pinging pingo pingoes pingos pings pinguid pinhead pinheaded pinheadedness pinheads pinhole pinholes pinier piniest pining pinion pinioned pinioning pinions pinite pinites pink pinked pinker pinkest pinkeye pinkie pinkies pinking pinkish pinkishness pinkly pinkness pinko pinkoes pinkos pinkroot pinkroots pinks pinkster pinksters pinky pinna pinnace pinnaces pinnacle pinnacled pinnacles pinnacling pinnae pinnal pinnas pinnate pinnated pinnately pinnatifid pinnatifidly pinnatiped pinnatisect pinned pinner pinners pinnigrade pinning pinniped pinnipeds pinnula pinnulae pinnular pinnule pinnules pinocchio pinochle pinocle pinocytic pinocytosis pinocytotic pinocytotically pinole pinoles pinot pinots pinpoint pinpointed pinpointing pinpoints pinprick pinpricked pinpricking pinpricks pins pinscher pinschers pinsetter pinsetters pinspotter pinspotters pinstripe pinstriped pinstripes pint pinta pintail pintails pintano pintanos pintas pintle pintles pinto pintoes pintos pints pintsize pintsized pinup pinups pinwale pinweed pinweeds pinwheel pinwheels pinwork pinworm pinworms pinwrench pinwrenches pinxter pinxters piny pinyin pinyon pinyons piolet piolets pion pioneer pioneered pioneering pioneers pionic pions piosities piosity pious piously piousness pip pipal pipals pipe piped pipefish pipefishes pipefitting pipefittings pipeful pipefuls pipeless pipelike pipeline pipelined pipelines pipelining piper piperazine piperazines piperidine piperidines piperine piperines piperonal piperonals piperonyl pipers pipes pipestone pipestones pipet pipets pipette pipetted pipettes pipetting piping pipings pipistrel pipistrelle pipistrelles pipistrels pipit pipits pipkin pipkins pipped pippin pipping pippins pips pipsissewa pipsissewas pipsqueak pipsqueaks piquance piquancy piquant piquantly piquantness pique piqued piques piquet piquets piquing piqué piracies piracy piraeus piragua piraguas piranesi piranha piranhas pirarucu pirarucus pirate pirated pirates piratic piratical piratically pirating piraña pirañas pirog piroghi pirogi pirogue pirogues piroplasm piroplasma piroplasmata piroplasmoses piroplasmosis piroplasms piroshki pirouette pirouetted pirouettes pirouetting pirozhki pis pisa pisan pisans piscaries piscary piscatorial piscatorially piscatory piscean pisceans pisces piscicultural pisciculture pisciculturist pisciculturists pisciform piscina piscinae piscinal piscine piscis piscivorous pish pishoge pishoges pishogue pishogues pisiform pisiforms pismire pismires pismo piso pisolite pisolites pisolith pisoliths pisolitic pisos piss pissant pissants pissarro pissed pisser pissers pisses pissing pissoir pissoirs pistachio pistachios pistareen pistareens piste pistes pistil pistillate pistils pistol pistole pistoled pistoleer pistoleers pistoles pistoling pistols piston pistons pistou pistous pit pita pitapat pitapats pitapatted pitapatting pitas pitcairn pitch pitchblende pitched pitcher pitcherful pitcherfuls pitchers pitches pitchfork pitchforked pitchforking pitchforks pitchier pitchiest pitchiness pitching pitchman pitchmen pitchout pitchouts pitchpole pitchpoled pitchpoles pitchpoling pitchstone pitchstones pitchwoman pitchwomen pitchy piteous piteously piteousness pitfall pitfalls pith pithead pitheads pithecanthropi pithecanthropic pithecanthropine pithecanthropus pithecoid pithed pithier pithiest pithily pithiness pithing piths pithy pitiable pitiableness pitiably pitied pitier pitiers pities pitiful pitifully pitifulness pitiless pitilessly pitilessness pitman pitmans pitmen piton pitons pitot pits pitsaw pitsaws pitta pittance pittances pittas pitted pitter pitting pittosporum pittosporums pittsburgh pituicyte pituicytes pituitaries pituitary pity pitying pityingly pityriases pityriasis piute piutes pivot pivotable pivotal pivotally pivoted pivoting pivotman pivotmen pivots pix pixel pixelate pixelated pixelates pixelating pixelation pixels pixes pixie pixieish pixies pixilated pixilation pixilations pixillated pixiness pixy pixyish pizarro pizazz pizazzy pizza pizzalike pizzas pizzaz pizzazes pizzazz pizzazzes pizzazzy pizzeria pizzerias pizzicati pizzicato pizzicatos pizzle pizzles pièce pièces piña piñata piñon piñones piñons più pkwy placability placable placably placard placarded placarder placarders placarding placards placate placated placater placaters placates placating placatingly placation placations placative placatory place placeable placebo placeboes placebos placed placeholder placeholders placekick placekicked placekicker placekickers placekicking placekicks placeless placelessly placeman placemen placement placements placenta placentae placental placentas placentation placentations placer placers places placid placidity placidly placidness placing placket plackets placoid plafond plafonds plagal plage plages plagiaries plagiarism plagiarisms plagiarist plagiaristic plagiarists plagiarize plagiarized plagiarizer plagiarizers plagiarizes plagiarizing plagiary plagioclase plagioclases plagiotropic plagiotropically plagiotropism plagiotropisms plague plagued plaguer plaguers plagues plaguey plaguily plaguing plaguy plaice plaices plaid plaided plaids plain plainchant plainchants plainclothes plainclothesman plainclothesmen plainer plainest plainly plainness plains plainsman plainsmen plainsong plainsongs plainspoken plainspokenness plainswoman plainswomen plaint plaintext plaintexts plaintful plaintiff plaintiffs plaintive plaintively plaintiveness plaints plait plaited plaiter plaiters plaiting plaits plan planar planaria planarian planarians planarity planate planation planations planchet planchets planchette planchettes planck plane planed planeload planeloads planeness planer planers planes planeside planesides planet planetaria planetarium planetariums planetary planetesimal planetesimals planetlike planetoid planetoidal planetoids planetological planetologist planetologists planetology planets planetwide planform planforms plangency plangent plangently planimeter planimeters planimetric planimetrical planimetrically planimetry planing planish planished planisher planishers planishes planishing planisphere planispheres planispheric planispherical plank planked planking plankings planks plankter plankters plankton planktonic planless planlessly planlessness planned planner planners planning plano planoblast planoblasts planoconcave planoconvex planogamete planogametes planographic planographically planography planometer planometers planometry planosol planosols plans plant plantable plantagenet plantagenets plantain plantains plantar plantation plantations planted planter planters plantigrade plantigrades planting plantings plantlet plantlets plantlike plantocracy plants plantsman plantsmen planula planulae planular planulate plaque plaques plash plashed plashes plashing plasm plasma plasmablast plasmablasts plasmacyte plasmacytes plasmagel plasmagels plasmagene plasmagenes plasmagenic plasmalemma plasmalemmas plasmapheresis plasmas plasmasol plasmasols plasmatic plasmic plasmid plasmids plasmin plasminogen plasminogens plasmins plasmodesm plasmodesma plasmodesmas plasmodesmata plasmodesms plasmodia plasmodial plasmodium plasmogamies plasmogamy plasmolyses plasmolysis plasmolytic plasmolytically plasmolyze plasmolyzed plasmolyzes plasmolyzing plasmon plasmons plasms plassey plaster plasterboard plasterboards plastered plasterer plasterers plastering plasterings plasters plasterwork plasterworks plastery plastic plastically plasticene plasticenes plasticine plasticines plasticity plasticization plasticizations plasticize plasticized plasticizer plasticizers plasticizes plasticizing plasticky plastics plastid plastidial plastids plastique plastisol plastisols plastocyanin plastocyanins plastoquinone plastoquinones plastral plastron plastrons plat platan platans plate plateau plateaued plateauing plateaus plateaux plated plateful platefuls plateglass platelet platelets platelike platemaker platemakers platemaking platen platens plater plateresque platers plates platform platforms platier platies platiest platina platinas plating platings platinic platinize platinized platinizes platinizing platinocyanide platinocyanides platinoid platinoids platinotype platinotypes platinous platinum platitude platitudes platitudinal platitudinarian platitudinarians platitudinize platitudinized platitudinizes platitudinizing platitudinous platitudinously plato platonic platonical platonically platonism platonist platonistic platonists platonize platonized platonizes platonizing platoon platooned platooning platoons plats plattdeutsch platted platter platterful platterfuls platters platting platy platyfish platyfishes platyhelminth platyhelminthic platyhelminths platypi platypus platypuses platyrrhine platyrrhinian platyrrhiny platys plaudit plaudits plausibility plausible plausibleness plausibly plausive plautus play playa playability playable playact playacted playacting playacts playas playback playbacks playbill playbills playbook playbooks playboy playboys played player players playfellow playfellows playfield playfields playful playfully playfulness playgirl playgirls playgoer playgoers playgoing playground playgrounds playhouse playhouses playing playland playlands playlet playlets playlist playlists playmaker playmakers playmaking playmate playmates playoff playoffs playpen playpens playroom playrooms plays playsuit playsuits plaything playthings playtime playtimes playwear playwright playwrighting playwrights playwriting plaza plazas plaît plea pleach pleached pleaches pleaching plead pleadable pleaded pleader pleaders pleading pleadingly pleadings pleads pleas pleasance pleasances pleasant pleasanter pleasantest pleasantly pleasantness pleasantries pleasantry please pleased pleaser pleasers pleases pleasing pleasingly pleasingness pleasurability pleasurable pleasurableness pleasurably pleasure pleasured pleasureless pleasures pleasuring pleat pleated pleater pleaters pleating pleatless pleats pleb plebe plebeian plebeianism plebeianly plebeians plebes plebianly plebiscitary plebiscite plebiscites plebs plecopteran plecopterans plectognath plectognaths plectra plectrum plectrums pled pledge pledged pledgee pledgees pledgeor pledgeors pledger pledgers pledges pledget pledgets pledging pledgor pledgors pleiad pleiades plein pleinairism pleinairist pleinairists pleiotaxies pleiotaxy pleiotropic pleiotropically pleiotropies pleiotropism pleiotropisms pleiotropy pleistocene plena plenarily plenariness plenary plenipotent plenipotentiaries plenipotentiary plenish plenished plenishes plenishing plenitude plenitudinous plenteous plenteously plenteousness plentiful plentifully plentifulness plentitude plenty plenum plenums pleochroic pleochroism pleochroisms pleomorphic pleomorphism pleomorphisms pleonasm pleonasms pleonastic pleonastically pleopod pleopods plerocercoid plerocercoids plesiosaur plesiosauri plesiosaurs plesiosaurus plessimeter plessimeters plessor plessors plethora plethoric plethorically plethysmogram plethysmograms plethysmograph plethysmographic plethysmographically plethysmographs plethysmography pleura pleurae pleural pleuras pleurisy pleuritic pleurodont pleurodonts pleurodynia pleurodynias pleuron pleuropneumonia pleurotomies pleurotomy pleuston pleustonic pleustons plexiform plexiglas pleximeter pleximeters pleximetric pleximetry plexor plexors plexus plexuses pliability pliable pliableness pliably pliancy pliant pliantly pliantness plica plicae plical plicate plicated plicately plicateness plication plications plicature plicatures plied plier pliers plies plight plighted plighter plighters plighting plights plimsol plimsole plimsoles plimsoll plimsolls plimsols plink plinked plinker plinkers plinking plinks plinth plinths pliny pliocene pliofilm pliskie pliskies plisky plisse plisses plissé plissés plié plod plodded plodder plodders plodding ploddingly plods ploidies ploidy plonk plonked plonking plonks plop plopped plopping plops plosion plosions plosive plosives plot plotinism plotinist plotinists plotinus plotless plotlessness plotline plotlines plots plottage plottages plotted plotter plotters plottier plottiest plotting plotty plough ploughed ploughing ploughman ploughs plover plovers plow plowable plowback plowbacks plowboy plowboys plowed plower plowers plowing plowman plowmen plows plowshare plowshares ploy ploys pluck plucked plucker pluckers pluckier pluckiest pluckily pluckiness plucking plucks plucky plug plugged plugger pluggers plugging plugola plugs plum plumage plumaged plumate plumb plumbable plumbago plumbagos plumbean plumbed plumber plumberies plumbers plumbery plumbic plumbiferous plumbing plumbism plumbisms plumbs plume plumed plumelet plumelets plumeria plumes plumier plumiest pluming plumlike plummet plummeted plummeting plummets plummier plummiest plummy plumose plumosely plumosity plump plumped plumpen plumpened plumpening plumpens plumper plumpest plumping plumpish plumply plumpness plumps plums plumule plumules plumulose plumy plunder plunderable plundered plunderer plunderers plundering plunderous plunders plunge plunged plunger plungers plunges plunging plunk plunked plunker plunkers plunking plunks plunky pluperfect pluperfects plural pluralism pluralist pluralistic pluralistically pluralists pluralities plurality pluralization pluralizations pluralize pluralized pluralizes pluralizing plurally plurals pluribus pluripotent plus pluses plush plusher plushest plushier plushiest plushily plushiness plushly plushness plushy plussage plusses plutarch plutarchan plutarchian pluto plutocracies plutocracy plutocrat plutocratic plutocratical plutocratically plutocrats plutographic plutography pluton plutonian plutonic plutonium plutons pluvial pluviograph pluviographs pluviometer pluviometers pluviometric pluviometrical pluviometrically pluviometry pluviose pluviosity pluvious ply plyer plyers plying plymouth plymouths plywood pneuma pneumas pneumatic pneumatical pneumatically pneumaticity pneumatics pneumatograph pneumatographs pneumatologic pneumatological pneumatologist pneumatologists pneumatology pneumatolysis pneumatolytic pneumatometer pneumatometers pneumatometry pneumatophore pneumatophores pneumatophoric pneumectomy pneumobacilli pneumobacillus pneumococcal pneumococci pneumococcus pneumoconiosis pneumoconiotic pneumoconiotics pneumocystis pneumocystises pneumogastric pneumograph pneumographic pneumographs pneumonectomies pneumonectomy pneumonia pneumonic pneumonitis pneumostome pneumostomes pneumotachogram pneumotachograms pneumotachograph pneumotachographic pneumotachographs pneumotachography pneumothorax pneumothoraxes po poach poachable poached poacher poachers poaches poaching poblano pocahontas pochard pochards pock pocked pocket pocketable pocketbook pocketbooks pocketed pocketful pocketfuls pocketing pocketknife pocketknives pocketless pockets pocketsful pocketsize pocking pockmark pockmarked pockmarking pockmarks pocks pocky poco pococurante pococurantes pococurantism pocono poconos pocosin pocosins pocus pocused pocuses pocusing pocussed pocusses pocussing pod podagra podagral podagras podagric podded podding podesta podestas podetia podetium podgier podgiest podgy podia podiatric podiatrist podiatrists podiatry podite podites poditic podium podiums podophylli podophyllin podophyllins podophyllum podophyllums podrida podridas pods podsol podsolization podsolizations podsols podunk podzol podzolic podzolization podzolizations podzolize podzolized podzolizes podzolizing podzols poem poems poenology poesies poesy poet poetaster poetasters poetess poetesses poetic poetical poeticality poetically poeticalness poeticism poeticisms poeticize poeticized poeticizes poeticizing poetics poetize poetized poetizer poetizers poetizes poetizing poetry poets pogies pogo pogonia pogonias pogonip pogonips pogonomyrmex pogonophoran pogonophorans pogonophore pogonophores pogonophorous pogrom pogromed pogroming pogromist pogromists pogroms pogy poi poignance poignancy poignant poignantly poikilotherm poikilothermal poikilothermia poikilothermic poikilothermism poikilothermous poikilotherms poilu poilus poincaré poinciana poinsettia poinsettias point pointblank pointe pointed pointedly pointedness pointelle pointer pointers pointes pointier pointiest pointillism pointillist pointillistic pointillists pointing pointless pointlessly pointlessness points pointtillist pointy pois poise poised poises poisha poising poison poisoned poisoner poisoners poisoning poisonings poisonous poisonously poisonousness poisons poisonwood poisonwoods poisson poitiers poitou poivre poke pokeberries pokeberry poked poker pokerfaced pokeroot pokeroots pokers pokery pokes pokeweed pokeweeds pokey pokeys pokier pokies pokiest pokily pokiness poking poky pol polab polabian polabians polabs polack polacks poland polar polarimeter polarimeters polarimetric polarimetry polaris polariscope polariscopes polariscopic polarities polarity polarizability polarizable polarization polarizations polarize polarized polarizer polarizers polarizes polarizing polarographic polarographically polarography polaroid polaron polarons polder polders pole poleax poleaxe poleaxed poleaxes poleaxing polecat polecats poled poleis poleless polemic polemical polemically polemicist polemicists polemicize polemicized polemicizes polemicizing polemics polemist polemists polemize polemized polemizes polemizing polemonium polenta polentas poler polers poles polestar polestars poleward police policeable policed policeman policemen policer policers polices policewoman policewomen policies policing policlinic policlinics policy policyholder policyholders policymaker policymakers policymaking poling polio poliomyelitic poliomyelitis poliovirus polioviruses polis polish polished polisher polishers polishes polishing polishings politburo politburos polite politely politeness politenesses politer politesse politest politic political politicalization politicalizations politicalize politicalized politicalizes politicalizing politically politician politicians politicization politicizations politicize politicized politicizes politicizing politick politicked politicker politickers politicking politicks politicly politico politicos politics polities polity polka polkaed polkaing polkas poll pollack pollacks pollard pollarded pollarding pollards polled pollen pollenate pollenated pollenates pollenating polleniferous pollenosis pollens poller pollers pollex pollices pollinate pollinated pollinates pollinating pollination pollinations pollinator pollinators polling pollinia polliniferous pollinium pollinization pollinizations pollinize pollinized pollinizer pollinizers pollinizes pollinizing pollinosis polliwog polliwogs pollo pollock pollocks polloi polls pollster pollsters polltaker polltakers pollutant pollutants pollute polluted polluter polluters pollutes polluting pollution pollutive pollux pollyanna pollyannaish pollyannaism pollyannas pollyannish pollywog pollywogs polo poloist poloists polonaise polonaises polonia polonium polonius pols poltergeist poltergeists poltroon poltrooneries poltroonery poltroons poly polyacetylene polyacrylamide polyacrylamides polyacrylonitrile polyadenylic polyalcohol polyalcohols polyamide polyamides polyamine polyamines polyandric polyandrous polyandry polyantha polyanthas polyanthus polyanthuses polyatomic polybasic polybasite polybasites polybius polybrominated polybutadiene polybutadienes polycarbonate polycarbonates polycarpellary polycarpic polycarpous polycarpy polycentric polycentrics polycentrism polychaete polychaetes polychete polychetes polychetous polychlorinated polychotomous polychotomy polychromatic polychromatophile polychromatophilia polychromatophilic polychrome polychromes polychromic polychromies polychromophilia polychromous polychromy polycistronic polyclinic polyclinics polyclonal polyclonally polyclone polyclones polycondensation polycondensations polyconic polycot polycots polycotyledon polycotyledonous polycotyledons polycrystal polycrystalline polycrystals polycyclic polycystic polycythemia polycythemias polycythemic polycytidylic polydactyl polydactylism polydactylous polydactyly polydemic polydiacetylene polydipsia polydipsic polydisperse polydispersity polydorus polyelectrolyte polyelectrolytes polyembryonic polyembryonies polyembryony polyene polyenes polyenic polyester polyesterification polyesterifications polyesters polyestrous polyether polyethers polyethylene polygala polygalas polygamic polygamist polygamists polygamize polygamized polygamizes polygamizing polygamous polygamously polygamy polygene polygenes polygenesis polygenesist polygenesists polygenetic polygenic polygenically polyglot polyglotism polyglots polyglottism polygon polygonal polygonally polygons polygonum polygonums polygraph polygraphed polygrapher polygraphers polygraphic polygraphing polygraphist polygraphists polygraphs polygynous polygyny polyhedra polyhedral polyhedron polyhedrons polyhedroses polyhedrosis polyhistor polyhistoric polyhistors polyhydric polyhydroxy polyhydroxybutyrate polyhymnia polyimide polyimides polyinosinic polylysine polylysines polymath polymathic polymaths polymathy polymer polymerase polymerases polymeric polymerically polymerism polymerization polymerizations polymerize polymerized polymerizes polymerizing polymerous polymers polymethyl polymnia polymorph polymorphic polymorphically polymorphism polymorphisms polymorphonuclear polymorphonuclears polymorphous polymorphously polymorphs polymyxin polymyxins polynesia polynesian polynesians polyneuritic polyneuritis polyneuritises polynices polynomial polynomials polynuclear polynucleotide polynucleotides polynya polynyas polynyi polyolefin polyolefins polyoma polyomas polyonymous polyp polyparia polyparies polyparium polypary polypeptide polypeptides polypeptidic polypetalous polyphagia polyphagian polyphagous polyphagy polyphase polyphasic polyphemus polyphenol polyphenolic polyphenols polyphiloprogenitive polyphone polyphones polyphonic polyphonically polyphonies polyphonous polyphonously polyphony polyphosphate polyphosphates polyphyletic polyphyletically polypide polypides polyploid polyploids polyploidy polypnea polypneas polypneic polypod polypodies polypodous polypody polypoid polypore polypores polyposes polyposis polypropylene polypropylenes polyprotic polyps polyptych polyptyches polyrhythm polyrhythmic polyrhythmically polyrhythms polyribonucleotide polyribonucleotides polyribosomal polyribosome polyribosomes polys polysaccharid polysaccharide polysaccharides polysaccharids polysaccharose polysaccharoses polysemous polysemy polysepalous polysome polysomes polysomic polysomics polysorbate polysorbates polyspermic polyspermies polyspermy polystichous polystyrene polystyrenes polysulfide polysulfides polysyllabic polysyllabically polysyllable polysyllables polysynaptic polysynaptically polysyndeton polysyndetons polysynthetic polytechnic polytechnics polytene polytenic polyteny polytetrafluoroethylene polytetrafluoroethylenes polytheism polytheist polytheistic polytheistical polytheists polythene polythenes polytocous polytonal polytonality polytonally polytrophic polytypic polytypical polyunsaturate polyunsaturated polyunsaturates polyurethane polyurethanes polyuria polyurias polyuric polyvalence polyvalency polyvalent polyvinyl polywater polyzoan polyzoans polyzoaria polyzoaries polyzoarium polyzoary polyzoic pom pomace pomaceous pomaces pomade pomaded pomades pomading pomander pomanders pomatum pomatums pome pomegranate pomegranates pomelo pomelos pomerania pomeranian pomeranians pomes pomiculture pomicultures pomiferous pommee pommel pommeled pommeling pommelled pommelling pommels pommie pommies pommy pomo pomological pomologically pomologist pomologists pomology pomona pomos pomp pompadour pompadoured pompadours pompano pompanos pompei pompeian pompeians pompeii pompeiian pompeiians pompelmous pompelmouses pompey pompidou pompom pompoms pompon pompons pomposity pompous pompously pompousness poms ponca poncas ponce ponces poncho ponchos pond ponder ponderability ponderable pondered ponderer ponderers pondering ponderosa ponderosas ponderosity ponderous ponderously ponderousness ponders pondicherry ponds pondweed pondweeds pone pones pong pongee pongees pongid pongids poniard poniarded poniarding poniards ponied ponies pons pontes ponthieu pontiac pontic pontifex pontiff pontiffs pontifical pontifically pontificals pontificate pontificated pontificates pontificating pontification pontifications pontificator pontificators pontifices pontil pontils pontine pontonier pontoniers pontoon pontoons pontus pony ponying ponytail ponytailed ponytails ponzi pooch pooches pood poodle poodled poodles poodling poods poof poofs pooftah poofter poofters pooh poohed poohing poohs pool pooled pooler poolers pooling poolroom poolrooms pools poolside poolsides poon poona poons poop pooped pooper pooping poops poor poorer poorest poorhouse poorhouses poori pooris poorish poorly poormouth poormouthed poormouthing poormouths poorness poove pooves pop popcorn pope popedom popedoms popery popes popeyed popgun popguns popinjay popinjays popish popishly popishness poplar poplars poplin poplins popliteal popocatépetl popover popovers poppa poppas popped popper poppers poppet poppets poppied poppies popping popple poppled popples poppling poppy poppycock poppyhead poppyheads pops popsicle popsicles populace populaces popular popularity popularization popularizations popularize popularized popularizer popularizers popularizes popularizing popularly populate populated populates populating population populational populations populi populism populist populistic populists populous populously populousness popup porbeagle porbeagles porcelain porcelainize porcelainized porcelainizes porcelainizing porcelainlike porcelains porcelaneous porcellaneous porch porches porcine porcini porcino porcupine porcupines pore pored pores porgies porgy poriferal poriferan poriferans poriferous poring pork porker porkers porkier porkies porkiest porkpie porkpies porky porn pornier porniest porno pornographer pornographers pornographic pornographically pornography porny poromeric poromerics porosities porosity porous porously porousness porphyria porphyrias porphyric porphyries porphyrin porphyrins porphyritic porphyritical porphyroid porphyroids porphyropsin porphyropsins porphyry porpoise porpoises porrect porridge porridges porridgy porringer porringers port portability portable portableness portables portably portage portaged portages portaging portal portals portamenti portamento portamentos portapack portapacks portapak portapaks portative portcullis portcullises porte ported portend portended portending portends portent portentous portentously portentousness portents porter porterage porterages porteress porteresses porterhouse porterhouses porters portfolio portfolios porthole portholes portia portico porticoed porticoes porticos portiere portieres porting portion portionable portioned portioner portioners portioning portionless portions portière portières portland portlander portlanders portlier portliest portliness portly portmanteau portmanteaus portmanteaux portofino portrait portraitist portraitists portraits portraiture portraitures portray portrayable portrayal portrayals portrayed portrayer portrayers portraying portrays portress portresses ports portside portugal portuguese portulaca portulacas posable posada posadas pose posed poseidon poser posers poses poseur poseurs posh poshly poshness posies posigrade posing posit positano posited positing position positional positionally positioned positioner positioners positioning positions positive positively positiveness positives positivism positivist positivistic positivistically positivists positivity positron positronium positrons posits posology posse posses possess possessed possessedly possessedness possesses possessing possession possessional possessionless possessions possessive possessively possessiveness possessives possessor possessors possessory posset possets possibilities possibility possible possibly possum possums post postabortion postaccident postadolescent postage postages postal postally postamputation postapocalyptic postarrest postatomic postattack postaxial postaxially postbaccalaureate postbag postbags postbase postbellum postbiblical postbourgeois postbox postboxes postboy postboys postburn postcapitalist postcard postcardlike postcards postcava postcaval postcavas postclassic postclassical postcode postcodes postcoital postcollege postcollegiate postcolonial postconception postconcert postcondition postconditions postconquest postconsonantal postconvention postcopulatory postcoronary postcoup postcranial postcranially postcrash postcrisis postdate postdated postdates postdating postdeadline postdebate postdebutante postdelivery postdepositional postdepression postdevaluation postdiluvial postdiluvian postdive postdivestiture postdivorce postdoc postdocs postdoctoral postdoctorate postdrug poste posted postediting postelection postembryonal postembryonic postemergence postemergency postencephalitic postepileptic poster posterior posteriori posteriority posteriorly posteriors posterity postern posterns posterolateral posters posteruptive postexercise postexilian postexilic postexperience postexperimental postexposure postface postfaces postfault postfeminist postfire postfix postfixal postfixed postfixes postfixial postfixing postflight postfracture postfreeze postfrontal postgame postganglionic postglacial postgraduate postgraduates postgraduation postharvest posthaste posthemorrhagic posthole postholes postholiday postholocaust posthospital posthumous posthumously posthumousness posthypnotic postiche postiches postilion postilions postillion postillions postimpact postimperial postimpressionism postimpressionist postimpressionistic postimpressionists postinaugural postindependence postindustrial postinfection posting postings postinjection postinoculation postirradiation postischemic postisolation postlanding postlapsarian postlaunch postliberation postliterate postlude postludes postman postmarital postmark postmarked postmarking postmarks postmastectomy postmaster postmasters postmastership postmasterships postmating postmedieval postmen postmenopausal postmenstrual postmeridian postmidnight postmillenarian postmillenarianism postmillenarians postmillennial postmillennialism postmillennialist postmillennialists postmillennian postmistress postmistresses postmodern postmodernism postmodernist postmodernists postmortem postmortems postnasal postnatal postnatally postneonatal postnuptial postnuptially postoperative postoperatively postorbital postorgasmic postovulatory postpaid postpartum postpollination postponable postpone postponed postponement postponements postponer postponers postpones postponing postpose postposed postposes postposing postposition postpositional postpositionally postpositions postpositive postpositively postpositives postprandial postprandially postpresidential postprimary postprison postprocessor postprocessors postproduction postproductions postpsychoanalytic postpuberty postpubescent postrace postrecession postresurrection postretirement postrevolutionary postriot postromantic posts postscript postscripts postseason postsecondary postshow poststimulation poststimulatory poststimulus poststrike postsurgical postsynaptic postsynaptically posttax postteen posttension posttensioned posttensioning posttensions posttest posttests posttranscriptional posttransfusion posttranslational posttraumatic posttreatment posttrial postulancy postulant postulants postulantship postulate postulated postulates postulating postulation postulational postulations postulator postulators postural posture postured posturer posturers postures posturing posturist posturists postvaccinal postvaccination postvagotomy postvasectomy postvertebral postvocalic postwar postweaning postworkshop posy pot potability potable potableness potables potage potages potamoplankton potamoplanktons potash potashes potassic potassium potation potations potato potatoes potatory potawatomi potawatomis potbellied potbellies potbelly potboil potboiled potboiler potboilers potboiling potboils potbound potboy potboys poteen poteens potemkin potence potences potencies potency potent potentate potentates potential potentialities potentiality potentialize potentialized potentializes potentializing potentially potentials potentiate potentiated potentiates potentiating potentiation potentiations potentiator potentiators potentilla potentillas potentiometer potentiometers potentiometric potently potentness potful potfuls pothead potheads potheen potheens pother potherb potherbs pothered pothering pothers potholder potholders pothole potholed potholes pothook pothooks pothouse pothouses pothunter pothunters pothunting potiche potiches potion potions potiphar potlatch potlatches potline potlines potluck potlucks potomac potometer potometers potpie potpies potpourri potpourris pots potsdam potshard potshards potsherd potsherds potshot potshots potshotting potstone potstones pottage potted potter pottered potterer potterers potteries pottering potteringly potters pottery pottier potties pottiest potting pottle pottles potto pottos potty potzer potzers pouch pouched pouches pouchier pouchiest pouching pouchy pouf poufed pouffe pouffed pouffes pouffy poufs pouilly poulard poularde poulardes poulards poult poulter poulterer poulterers poultice poulticed poultices poulticing poultry poultryman poultrymen poults pounce pounced pouncer pouncers pounces pouncet pouncets pouncing pound poundage poundal poundals pounded pounder pounders pounding pounds pour pourable pourboire pourboires poured pourer pourers pouring pouringly pourparler pourparlers pourpoint pourpoints pours pousse poussette poussetted poussettes poussetting poussin pout pouted pouter pouters pouting pouts pouty poverty pow powder powdered powderer powderers powdering powderless powderlike powders powdery powell power powerboat powerboats powered powerful powerfully powerfulness powerhouse powerhouses powering powerless powerlessly powerlessness powerlifting powerliftings powers powerwalking powhatan powhatans pows powwow powwowed powwowing powwows powys pox poxes poxvirus poxviruses pozzolan pozzolana pozzolanas pozzolanic pozzolans pozzuolana pozzuolanas pozzuolanic pozzuoli ppm pq praam praams practicability practicable practicableness practicably practical practicalities practicality practically practicalness practice practiced practicer practicers practices practicing practicum practicums practise practised practises practising practitioner practitioners pradesh prado praecipe praecipes praecox praedial praemunire praemunires praenomen praenomens praenomina praenominal praesidium praesidiums praetor praetorial praetorian praetorians praetors praetorship praetorships pragmatic pragmatical pragmatically pragmaticism pragmaticist pragmaticists pragmatics pragmatism pragmatist pragmatistic pragmatists prague prahu prahus prairie prairies praise praised praiseful praiser praisers praises praiseworthier praiseworthiest praiseworthily praiseworthiness praiseworthy praising prakrit prakritic prakrits praline pralines pralltriller pralltrillers pram prams prance pranced prancer prancers prances prancing prancingly prandial prandially prang pranged pranging prangs prank pranked pranking prankish prankishly prankishness pranks prankster pranksters prase praseodymium prases prat prate prated prater praters prates pratfall pratfalls pratincole pratincoles prating pratingly pratique pratiques prato prats prattle prattled prattler prattlers prattles prattling prattlingly prau praus prawn prawned prawner prawners prawning prawns praxeological praxeology praxes praxiology praxis praxiteles pray prayed prayer prayerful prayerfully prayerfulness prayerlessness prayers praying prays prazosin prazosins pre preach preached preacher preachers preaches preachier preachiest preachification preachifications preachified preachifies preachify preachifying preachily preachiness preaching preachingly preachment preachments preachy preadaptation preadaptations preadapted preadaptive preadmission preadmissions preadolescence preadolescent preadolescents preadult preagricultural preamble preambles preambulary preamp preamplified preamplifier preamplifiers preamps preanesthetic preannounce preannounced preannounces preannouncing preapprehension preapprove preapproved preapproves preapproving prearrange prearranged prearrangement prearrangements prearranges prearranging preassembled preassign preassigned preassigning preassigns preatomic preaxial preaxially prebake prebaked prebakes prebaking prebattle prebattled prebattles prebattling prebend prebendal prebendaries prebendary prebends prebiblical prebiologic prebiological prebiologist prebiologists prebiology prebiotic prebook prebooked prebooking prebooks prebreakfast prebreakfasts prebuilt precalculus precambrian precancel precanceled precanceling precancellation precancellations precancelled precancelling precancels precancer precancerous precancers precapitalist precarious precariously precariousness precast precasting precasts precative precatory precaution precautional precautionary precautions precava precavae precaval precede preceded precedence precedency precedent precedential precedents precedes preceding precensor precensored precensoring precensors precentor precentorial precentors precentorship precentorships precept preceptive preceptively preceptor preceptorial preceptorially preceptories preceptors preceptorship preceptorships preceptory precepts precess precessed precesses precessing precession precessional precessions prechill prechilled prechilling prechills prechristmas precieuse precieux precinct precincts preciosities preciosity precious preciously preciousness precipe precipes precipice precipices precipitable precipitance precipitancy precipitant precipitantly precipitantness precipitants precipitate precipitated precipitately precipitateness precipitates precipitating precipitation precipitations precipitative precipitator precipitators precipitin precipitinogen precipitinogens precipitins precipitous precipitously precipitousness precise precisely preciseness precisian precisianism precisians precision precisionism precisionist precisionists precisions preclear preclearance precleared preclearing preclears preclinical preclude precluded precludes precluding preclusion preclusive preclusively precocial precocious precociously precociousness precocity precode precoded precodes precoding precognition precognitions precognitive precognizant precoital precollege precollegiate precolonial precombustion precommitment precommitments precompute precomputed precomputer precomputes precomputing preconceive preconceived preconceives preconceiving preconception preconceptions preconcert preconcerted preconcerting preconcerts precondition preconditioned preconditioning preconditions preconquest preconscious preconsciously preconsonantal preconstructed precontact precontract precontracted precontracting precontracts precontrived preconvention preconviction preconvictions precook precooked precooking precooks precool precooled precooling precools precopulatory precrash precrease precreased precreases precreasing precrisis precritical precursive precursor precursors precursory precut precuts precutting predaceous predaceousness predacious predaciousness predacity predate predated predates predating predation predations predator predatorily predatoriness predators predatory predawn predawns predecease predeceased predeceases predeceasing predecessor predecessors predefine predefined predefines predefining predefinition predefinitions predelivery predeparture predesignate predesignated predesignates predesignating predesignation predesignations predestinarian predestinarianism predestinarians predestinate predestinated predestinates predestinating predestination predestinator predestinators predestine predestined predestines predestining predeterminate predetermination predeterminations predetermine predetermined predeterminer predeterminers predetermines predetermining predevaluation predevelopment prediabetes prediabetic prediabetics predial predicability predicable predicableness predicables predicament predicamental predicamentally predicaments predicate predicated predicates predicating predication predicational predications predicative predicatively predicator predicators predicatory predict predictability predictable predictably predicted predicting prediction predictions predictive predictively predictiveness predictor predictors predicts predigest predigested predigesting predigestion predigestions predigests predilection predilections predinner predischarge prediscoveries prediscovery predispose predisposed predisposes predisposing predisposition predispositions predive prednisolone prednisolones prednisone prednisones predoctoral predominance predominancy predominant predominantly predominate predominated predominately predominates predominating predominatingly predomination predominations predominator predominators predrill predrilled predrilling predrills predynastic preeclampsia preeclamptic preelection preelectric preembargo preemergence preemergent preemie preemies preeminence preeminent preeminently preemployment preemployments preempt preempted preempting preemption preemptions preemptive preemptively preemptor preemptors preemptory preempts preen preened preener preeners preengineered preening preenrollment preens preerect preerected preerecting preerects preestablish preestablished preestablishes preestablishing preethical preexilian preexilic preexist preexisted preexistence preexistent preexisting preexists preexperiment prefab prefabed prefabing prefabricate prefabricated prefabricates prefabricating prefabrication prefabrications prefabricator prefabricators prefabs preface prefaced prefacer prefacers prefaces prefacing prefade prefaded prefades prefading prefascist prefatorily prefatory prefect prefects prefectural prefecture prefectures prefer preferability preferable preferableness preferably preference preferences preferential preferentialism preferentialist preferentialists preferentially preferment preferments preferred preferrer preferrers preferring prefers prefeudal prefight prefiguration prefigurations prefigurative prefiguratively prefigurativeness prefigure prefigured prefigurement prefigurements prefigures prefiguring prefile prefiled prefiles prefiling prefilled prefinance prefinanced prefinances prefinancing prefinished prefire prefix prefixal prefixally prefixed prefixes prefixing preflame preflight preflighted preflighting preflights prefocus prefocused prefocuses prefocusing preform preformat preformation preformationist preformationists preformations preformats preformatted preformatting preformed preforming preforms preformulate preformulated preformulates preformulating prefreshman prefreshmen prefrontal prefrozen pregame preganglionic pregenital pregnability pregnable pregnancies pregnancy pregnant pregnantly pregnenolone pregnenolones preharvest preheadache preheat preheated preheater preheaters preheating preheats prehensile prehensility prehension prehensions prehiring prehistorian prehistorians prehistoric prehistorical prehistorically prehistories prehistory preholiday prehominid prehominids prehuman preignition preignitions preimplantation preinaugural preincorporation preinduction preindustrial preinstall preinstalled preinstalling preinstalls preinterview preinvasion prejudge prejudged prejudgement prejudgements prejudger prejudgers prejudges prejudging prejudgment prejudgments prejudice prejudiced prejudices prejudicial prejudicially prejudicialness prejudicing prejudicious prejudiciously prekindergarten prelacies prelacy prelapsarian prelate prelates prelateship prelateships prelatic prelature prelatures prelaunch prelaw prelect prelected prelecting prelection prelections prelector prelectors prelects prelibation prelibations prelife prelim preliminaries preliminarily preliminary prelims preliterary preliterate preliterates preloaded prelogical prelude preluded preluder preluders preludes preludial preluding prelunch preluncheon prelusion prelusions prelusive prelusively premade premalignant preman premanufacture premarital premaritally premarket premarketed premarketing premarkets premarriage premature prematurely prematureness prematurity premaxilla premaxillae premaxillary premeal premeasure premeasured premeasures premeasuring premed premedical premedieval premeditate premeditated premeditatedly premeditates premeditating premeditation premeditative premeditator premeditators premeds premeet premeiotic premenopausal premenstrual premenstrually premerger premie premier premiere premiered premieres premiering premiers premiership premierships premies premigration premillenarian premillenarianism premillenarians premillennial premillennialism premillennialist premillennialists premillennially premise premised premises premising premiss premisses premium premiums premix premixed premixes premixing première premièred premières premièring premodern premodification premodified premodifies premodify premodifying premoisten premoistened premoistening premoistens premolar premolars premold premolded premolding premolds premolt premonish premonished premonishes premonishing premonition premonitions premonitorily premonitory premonstratensian premonstratensians premoral premorse premune premunition premunitions premycotic prename prenames prenatal prenatally prenominate prenominated prenominates prenominating prenomination prenominations prenoon prenotification prenotifications prenotified prenotifies prenotify prenotifying prenotion prenotions prentice prenticed prentices prenticing prenumber prenumbered prenumbering prenumbers prenuptial preoccupancy preoccupation preoccupations preoccupied preoccupies preoccupy preoccupying preopening preoperational preoperative preoperatively preoral preorbital preordain preordained preordaining preordainment preordainments preordains preorder preordered preordering preorders preordination preordinations preovulatory preowned prep prepack prepackage prepackaged prepackages prepackaging prepacked prepacking prepacks prepaid preparation preparations preparative preparatively preparatives preparator preparatorily preparators preparatory prepare prepared preparedly preparedness preparer preparers prepares preparing prepaste prepasted prepastes prepasting prepay prepaying prepayment prepayments prepays prepense prepensely preperformance prepill preplan preplanned preplanning preplans preplant preplanting preponderance preponderancy preponderant preponderantly preponderate preponderated preponderately preponderates preponderating preponderation preponderations preportion preportioned preportioning preportions preposition prepositional prepositionally prepositioned prepositioning prepositions prepositive prepositively prepositives prepossess prepossessed prepossesses prepossessing prepossessingly prepossessingness prepossession prepossessions preposterous preposterously preposterousness prepotencies prepotency prepotent prepotently prepped preppie preppies preppily preppiness prepping preppy preprandial prepreg preprepared prepresidential preprice prepriced preprices prepricing preprimaries preprimary preprint preprinted preprinting preprints preprocess preprocessed preprocesses preprocessing preprocessor preprocessors preproduction preproductions preprofessional preprogram preprogramed preprograming preprogrammed preprogramming preprograms preps prepsychedelic prepuberal prepubertal prepuberty prepubescence prepubescent prepubescents prepublication prepuce prepuces prepunch prepunched prepunches prepunching prepupa prepupae prepupal prepupas prepurchase prepurchased prepurchases prepurchasing preputial prequalification prequalified prequalifies prequalify prequalifying prequel prequels prerace prerecession prerecord prerecorded prerecording prerecords preregister preregistered preregistering preregisters preregistration preregistrations prerehearsal prerelease prereleases prerequire prerequired prerequires prerequiring prerequisite prerequisites preretirement preretirements prereturn prereview prerevisionist prerevolution prerevolutionary prerinse prerinsed prerinses prerinsing preriot prerock prerogative prerogatived prerogatives preromantic presage presaged presageful presager presagers presages presaging presale presales presanctified presbyope presbyopes presbyopia presbyopic presbyter presbyterate presbyterates presbyterial presbyterially presbyterian presbyterianism presbyterians presbyteries presbyters presbytery preschedule prescheduled preschedules prescheduling preschool preschooler preschoolers preschooling preschools prescience prescient prescientific presciently prescind prescinded prescinding prescinds prescore prescored prescores prescoring prescreen prescreened prescreening prescreens prescribe prescribed prescriber prescribers prescribes prescribing prescript prescriptibility prescriptible prescription prescriptions prescriptive prescriptively prescriptiveness prescriptivist prescriptivists prescripts preseason preseasons preselect preselected preselecting preselection preselections preselects presell preselling presells presence present presentability presentable presentableness presentably presentation presentational presentations presentative presentativeness presented presentee presentees presentence presentencing presenter presenters presentient presentiment presentimental presentiments presenting presentism presentist presentists presently presentment presentments presentness presents preservability preservable preservation preservationism preservationist preservationists preservations preservative preservatives preserve preserved preserver preservers preserves preservice preserving preset presets presettable presetting presettlement preshow preshrank preshrink preshrinks preshrunk preside presided presidencies presidency president presidential presidentially presidents presidentship presidentships presider presiders presides presidia presidial presidiary presiding presidio presidios presidium presidiums presignified presignifies presignify presignifying preslaughter presleep preslice presliced preslices preslicing presoak presoaked presoaking presoaks presold presong presort presorted presorting presorts prespecified prespecifies prespecify prespecifying presplit press pressboard pressboards pressed presser pressers presses pressing pressingly pressings pressman pressmark pressmarks pressmen pressor pressroom pressrooms pressrun pressruns pressure pressured pressureless pressures pressuring pressurization pressurizations pressurize pressurized pressurizer pressurizers pressurizes pressurizing presswork prest prestamp prestamped prestamping prestamps prestellar prester presterilize presterilized presterilizes presterilizing presternum presternums prestidigitation prestidigitations prestidigitator prestidigitators prestige prestigeful prestigious prestigiously prestigiousness prestissimo prestissimos presto prestorage prestos prestress prestressed prestresses prestressing prestrike prestructure prestructured prestructures prestructuring presumable presumably presume presumed presumedly presumer presumers presumes presuming presumingly presummit presumption presumptions presumptive presumptively presumptuous presumptuously presumptuousness presuppose presupposed presupposes presupposing presupposition presuppositional presuppositions presurgery presweeten presweetened presweetening presweetens presymptomatic presynaptic presynaptically pretape pretaped pretapes pretaping pretax pretechnological preteen preteenager preteenagers preteens pretelevision pretence pretences pretend pretended pretendedly pretender pretenders pretending pretends pretense pretenses pretension pretensionless pretensions pretentious pretentiously pretentiousness preterit preterite preterition preteritions preterits preterm preterminal pretermination pretermission pretermissions pretermit pretermits pretermitted pretermitter pretermitters pretermitting preterms preternatural preternaturalism preternaturally preternaturalness pretest pretested pretesting pretests pretext pretexted pretexting pretexts pretheater preticket preticketed preticketing pretickets pretor pretoria pretorian pretorians pretors pretournament pretrain pretravel pretreat pretreated pretreating pretreatment pretreatments pretreats pretrial pretrials pretrimmed prettied prettier pretties prettiest prettification prettifications prettified prettifier prettifiers prettifies prettify prettifying prettily prettiness pretty prettying prettyish pretype pretyped pretypes pretyping pretzel pretzels preunification preuniversity prevail prevailed prevailer prevailers prevailing prevailingly prevailingness prevails prevalence prevalent prevalently prevaricate prevaricated prevaricates prevaricating prevarication prevarications prevaricator prevaricators prevenience preveniences prevenient preveniently prevent preventability preventable preventative preventatively preventatives prevented preventer preventers preventibility preventible preventing prevention preventions preventive preventively preventiveness preventives prevents preverb preverbal preverbs previable preview previewed previewer previewers previewing previews previous previously previousness previse prevised previses prevising prevision previsional previsionary previsioned previsioning previsions previsor previsors prevocalic prevocational prevue prevued prevues prevuing prewar prewarn prewarned prewarning prewarns prewash prewashed prewashes prewashing preweaning prework prewrap prewrapped prewrapping prewraps prewriting prex prexes prexies prexy prey preyed preyer preyers preying preys prez prezes priam priapean priapic priapism priapus priapuses pribilof price priceable priced priceless pricelessly pricer pricers prices pricey priceyness pricier priciest pricily pricing prick pricked pricker prickers pricket prickets prickier prickiest pricking prickle prickled prickles pricklier prickliest prickliness prickling prickly pricks pricky pricy pride prided prideful pridefully pridefulness prides priding pried prier priers pries priest priested priestess priestesses priesthood priesting priestley priestlier priestliest priestliness priestly priests prig prigged priggery prigging priggish priggishly priggishness priggism prigs prill prilled prilling prills prim prima primacies primacy primal primality primaries primarily primary primate primates primateship primatial primatological primatologist primatologists primatology primavera primaveras prime primed primely primeness primer primero primers primes primeval primevally primi priming primings primipara primiparae primiparas primiparity primiparous primitive primitively primitiveness primitives primitivism primitivist primitivistic primitivists primitivity primly primmed primmer primmest primming primness primo primogenital primogenitary primogenitor primogenitors primogeniture primogenitures primordia primordial primordially primordials primordium primos primp primped primping primps primrose primroses prims primula primus primuses prince princedom princedoms princelet princelets princelier princeliest princeliness princeling princelings princely princes princeship princeships princess princesse princesses princeton principal principalities principality principally principals principalship principalships principe principia principium principle principled principles princox prink prinked prinker prinkers prinking prinks print printability printable printed printer printer's printeries printers printery printhead printheads printing printings printless printmaker printmakers printmaking printout printouts prints prion prions prior priorate priorates prioress prioresses priori priories priorities prioritization prioritizations prioritize prioritized prioritizes prioritizing priority priorly priors priorship priorships priory pris prise prised prises prising prism prismatic prismatical prismatically prismatoid prismatoidal prismatoids prismoid prismoidal prismoids prisms prison prisoned prisoner prisoners prisoning prisons prissier prissiest prissily prissiness prissy pristane pristanes pristine pristinely prithee privacy privatdocent privatdocents private privateer privateered privateering privateers privately privateness privates privation privations privatism privatist privatistic privatists privative privatively privatives privatization privatizations privatize privatized privatizes privatizing privet privets privies privilege privileged privileges privileging privily privities privity privy prix prize prized prizefight prizefighter prizefighters prizefighting prizefights prizer prizers prizes prizewinner prizewinners prizewinning prizing pro proa proabortion proaction proactions proactive proactively proas probabilism probabilist probabilistic probabilistically probabilists probabilities probability probable probably proband probands probang probangs probate probated probates probating probation probational probationally probationary probationer probationers probations probative probatory probe probed probenecid probenecids prober probers probes probing probingly probit probits probity problem problematic problematical problematically problematization problematize problematized problematizes problematizing problems proboscidean proboscideans proboscides proboscidian proboscidians proboscis proboscises procaine procaines procambial procambium procambiums procarbazine procarbazines procaryote procaryotes procathedral procathedrals procedural procedurally procedurals procedure procedures proceed proceeded proceeder proceeders proceeding proceedings proceeds procephalic procercoid procercoids process processability processable processed processes processibility processible processing procession processional processionally processionals processioned processioning processions processor processors proclaim proclaimed proclaimer proclaimers proclaiming proclaims proclamation proclamations proclamatory proclitic proclitics proclivities proclivity procoagulant procoagulants procommunist procommunists proconsul proconsular proconsulate proconsulates proconsuls proconsulship proconsulships procrastinate procrastinated procrastinates procrastinating procrastination procrastinations procrastinative procrastinator procrastinators procrastinatory procreant procreate procreated procreates procreating procreation procreations procreative procreativity procreator procreators procrustean procryptic proctitis proctodaea proctodaeum proctodaeums proctodea proctodeum proctodeums proctologic proctological proctologically proctologist proctologists proctology proctor proctored proctorial proctoring proctors proctorship proctorships proctoscope proctoscopes proctoscopic proctoscopy procumbent procurable procurance procuration procurations procurator procuratorial procurators procure procured procurement procurements procurer procurers procures procuress procuresses procuring procyon procès prod prodded prodder prodders prodding prodigal prodigalities prodigality prodigally prodigals prodigies prodigious prodigiously prodigiousness prodigy prodromal prodromata prodrome prodromes prodromic prodrug prodrugs prods produce produceable produced producer producers produces producible producing product production productional productions productive productively productiveness productivity products proem proemial proems proenzyme proenzymes proestrus proestruses prof profanation profanations profanatory profane profaned profanely profaneness profaner profaners profanes profaning profanities profanity profess professed professedly professes professing profession professional professionalism professionalization professionalizations professionalize professionalized professionalizes professionalizing professionally professionals professions professor professorate professorates professorial professorially professoriat professoriate professoriates professoriats professors professorship professorships proffer proffered profferer profferers proffering proffers proficiencies proficiency proficient proficiently proficients profile profiled profiler profilers profiles profiling profit profitability profitable profitableness profitably profited profiteer profiteered profiteering profiteers profiterole profiteroles profiting profitless profits profitwise profligacy profligate profligately profligates profluent profound profounder profoundest profoundly profoundness profs profundis profundities profundity profundo profundos profuse profusely profuseness profusion progenies progenitor progenitors progeny progeria progestational progesterone progestin progestins progestogen progestogenic progestogens proglottic proglottid proglottidean proglottides proglottids proglottis prognathic prognathism prognathous prognoses prognosis prognostic prognosticate prognosticated prognosticates prognosticating prognostication prognostications prognosticative prognosticator prognosticators prognosticatory prognostics prograde program programed programer programers programing programmability programmable programmatic programmatically programmed programmer programmers programming programs progress progressed progresses progressing progression progressional progressions progressive progressively progressiveness progressives progressivism progressivist progressivistic progressivists progressivities progressivity prohibit prohibited prohibiting prohibition prohibitionism prohibitionist prohibitionists prohibitions prohibitive prohibitively prohibitiveness prohibitory prohibits proinsulin proinsulins project projectable projected projectile projectiles projecting projection projectional projectionist projectionists projections projective projectively projector projectors projects projet projets prokaryote prokaryotes prokaryotic prokofiev prolactin prolactins prolamin prolamine prolamines prolamins prolan prolans prolapse prolapsed prolapses prolapsing prolapsus prolate prolately prolateness prole proleg prolegomena prolegomenon prolegomenous prolegs prolepses prolepsis proleptic proleptical proleptically proles proletarian proletarianism proletarianization proletarianizations proletarianize proletarianized proletarianizes proletarianizing proletarians proletariat proletariats proliferate proliferated proliferates proliferating proliferation proliferations proliferative proliferator proliferators proliferous proliferously prolific prolificacy prolifically prolificity prolificness proline prolines prolix prolixity prolixly prolocutor prolocutors prolog prologize prologized prologizes prologizing prologs prologue prologues prologuize prologuized prologuizes prologuizing prolong prolongate prolongated prolongates prolongating prolongation prolongations prolonged prolonger prolongers prolonging prolongs prolusion prolusions prolusory prom promenade promenaded promenader promenaders promenades promenading promethean prometheans prometheus promethium prominence prominences prominency prominent prominently promiscuities promiscuity promiscuous promiscuously promiscuousness promise promised promisee promisees promiser promisers promises promising promisingly promisor promisors promissory promo promontories promontory promos promotability promotable promote promoted promoter promoters promotes promoting promotion promotional promotionally promotions promotive promotiveness prompt promptbook promptbooks prompted prompter prompters promptest prompting promptitude promptly promptness prompts proms promulgate promulgated promulgates promulgating promulgation promulgations promulgator promulgators pronatalism pronatalist pronatalistic pronatalists pronate pronated pronates pronating pronation pronations pronator pronators prone pronely proneness pronephra pronephric pronephroi pronephros prong pronged pronghorn pronghorns pronging prongs pronograde pronominal pronominally pronoun pronounce pronounceability pronounceable pronounced pronouncedly pronouncedness pronouncement pronouncements pronouncer pronouncers pronounces pronouncing pronouns pronto prontosil pronuclear pronuclei pronucleus pronunciamento pronunciamentoes pronunciamentos pronunciation pronunciational pronunciations proof proofed proofer proofers proofing proofread proofreader proofreaders proofreading proofreads proofroom proofrooms proofs prop propaedeutic propaedeutics propagable propaganda propagandism propagandist propagandistic propagandistically propagandists propagandize propagandized propagandizer propagandizers propagandizes propagandizing propagate propagated propagates propagating propagation propagational propagations propagative propagator propagators propagule propagules propane propanoate propanoic propanol propel propellant propellants propelled propellent propellents propeller propellers propelling propellor propellors propels propend propended propending propends propene propenes propense propensities propensity proper properdin properdins properly properness propertied properties propertius property propertyless propertylessness prophage prophages prophase prophases prophasic prophecies prophecy prophesied prophesier prophesiers prophesies prophesy prophesying prophet prophetess prophetesses prophethood prophetic prophetical prophetically propheticalness prophets prophylactic prophylactically prophylactics prophylaxes prophylaxis propinquity propionaldehyde propionaldehydes propionate propionates propionic propitiable propitiate propitiated propitiates propitiating propitiatingly propitiation propitiations propitiative propitiator propitiatorily propitiators propitiatory propitious propitiously propitiousness propjet propjets proplastid proplastids propman propmen propolis propolises propone proponed proponent proponents propones proponing proportion proportionable proportionably proportional proportionality proportionally proportionals proportionate proportionated proportionately proportionateness proportionates proportionating proportioned proportioner proportioners proportioning proportionment proportionments proportions proposal proposals propose proposed proposer proposers proposes proposing propositi proposition propositional propositionally propositioned propositioning propositions propositus propound propounded propounder propounders propounding propounds propoxyphene propoxyphenes propped propping propraetor propraetorial propraetorian propraetors propranolol propranolols propre propretor propretors propria propriae proprietaries proprietarily proprietary proprieties proprietor proprietorial proprietorially proprietors proprietorship proprietorships proprietress proprietresses propriety proprioception proprioceptions proprioceptive proprioceptor proprioceptors props proptoses proptosis propulsion propulsions propulsive propulsory propyl propyla propylaea propylaeum propylene propylic propylon propyls proratable prorate prorated prorates prorating proration prorations prorogate prorogated prorogates prorogating prorogation prorogations prorogue prorogued prorogues proroguing pros prosaic prosaically prosaicness prosaism prosaisms prosaist prosaists prosateur prosateurs prosauropod prosauropods proscenia proscenium prosceniums prosciutti prosciutto prosciuttos proscribe proscribed proscriber proscribers proscribes proscribing proscription proscriptions proscriptive proscriptively prose prosector prosectors prosecutable prosecute prosecuted prosecutes prosecuting prosecution prosecutions prosecutor prosecutorial prosecutors prosed proselyte proselyted proselyter proselyters proselytes proselytical proselyting proselytism proselytisms proselytization proselytizations proselytize proselytized proselytizer proselytizers proselytizes proselytizing proseminar proseminars prosencephalic prosencephalon prosencephalons prosenchyma prosenchymas prosenchymatous prosequi prosequitur proser proserpine prosers proses prosier prosiest prosily prosimian prosimians prosiness prosing prosit proslavery proso prosobranch prosobranchs prosodic prosodical prosodically prosodies prosodist prosodists prosody prosoma prosomal prosomas prosopographical prosopography prosopopeia prosopopeial prosopopeias prosopopoeia prosopopoeias prospect prospected prospecting prospective prospectively prospector prospectors prospects prospectus prospectuses prosper prospered prospering prosperity prosperous prosperously prosperousness prospers prost prostacyclin prostacyclins prostaglandin prostaglandins prostate prostatectomies prostatectomy prostates prostatic prostatism prostatisms prostatitis prostheses prosthesis prosthetic prosthetically prosthetics prosthetist prosthetists prosthodontia prosthodontic prosthodontics prosthodontist prosthodontists prostitute prostituted prostitutes prostituting prostitution prostitutions prostitutor prostitutors prostomia prostomial prostomium prostrate prostrated prostrates prostrating prostration prostrations prostrator prostrators prostyle prosy protactinium protagonist protagonists protamin protamine protamines protamins protandrous protandry protanopia protanopias protanopic protases protasis protatic protea protean proteas protease proteases protect protectant protectants protected protecter protecters protecting protectingly protection protectional protectionism protectionist protectionists protections protective protectively protectiveness protectives protector protectoral protectorate protectorates protectories protectors protectorship protectorships protectory protectress protectresses protects protei proteid proteids protein proteinaceous proteinase proteinases proteinic proteinoid proteinoids proteins proteinuria proteinurias protend protended protending protends protensive protensively proteoclastic proteoglycan proteoglycans proteolyses proteolysis proteolytic proteolytically proteose proteoses proteron proterozoic protest protestant protestantism protestants protestation protestations protested protester protesters protesting protestingly protestor protestors protests proteus prothalamia prothalamion prothalamium prothalli prothallia prothallial prothallium prothallus protheses prothesis prothetic prothetically prothonotarial prothonotaries prothonotary prothoraces prothoracic prothorax prothoraxes prothrombin prothrombins protist protista protistan protistans protistology protists protium protiums protocol protocolar protocolary protocoled protocoling protocolled protocolling protocols protocontinent protocontinents protoctist protoctists protoderm protodermal protoderms protogalaxies protogalaxy protogynous protogyny protohistorian protohistorians protohistoric protohistory protohuman protohumans protolanguage protolanguages protolithic protomartyr protomartyrs protomorph protomorphic protomorphs proton protonate protonated protonates protonating protonation protonations protonema protonemal protonemata protonematal protonic protonotaries protonotary protons protopathic protopathy protophloem protophloems protoplanet protoplanetary protoplanets protoplasm protoplasmal protoplasmatic protoplasmic protoplast protoplastic protoplasts protoporphyrin protoporphyrins protostar protostars protostele protosteles protostelic protostome protostomes prototroph prototrophic prototrophs prototrophy prototypal prototype prototyped prototypes prototypic prototypical prototypically prototyping protoxylem protoxylems protozoa protozoal protozoan protozoans protozoic protozoological protozoologist protozoologists protozoology protozoon protract protracted protractedly protractedness protractible protractile protractility protracting protraction protractions protractive protractor protractors protracts protreptic protreptics protrude protruded protrudent protrudes protruding protrusible protrusile protrusility protrusion protrusions protrusive protrusively protrusiveness protuberance protuberances protuberancies protuberancy protuberant protuberantly protuberate protuberated protuberates protuberating protuberation protuberations protégé protégée protégées protégés proud prouder proudest proudful proudhearted proudly proudness proust proustian proustite proustites provability provable provableness provably provascular prove proved proven provenance provenances provence provender provenience proveniences provenly proventricular proventriculi proventriculus provençal provençale provençals provençaux prover proverb proverbial proverbially proverbs provers proves provide provided providence provident providential providentially providently provider providers provides providing province provinces provincial provincialism provincialist provincialists provinciality provincialization provincializations provincialize provincialized provincializes provincializing provincially provincials proving proviral provirus proviruses provision provisional provisionally provisionals provisionary provisioned provisioner provisioners provisioning provisions proviso provisoes provisorily provisory provisos provitamin provitamins provo provocateur provocateurs provocation provocations provocative provocatively provocativeness provocatives provoke provoked provoker provokers provokes provoking provokingly provolone provos provost provosts prow prowess prowl prowled prowler prowlers prowling prowls prows proxemic proxemics proxies proximal proximally proximate proximately proximateness proximity proximo proxy prude prudence prudent prudential prudentially prudently pruderies prudery prudes prudish prudishly prudishness pruinose prune pruned prunella prunellas prunelle prunelles prunello prunellos pruner pruners prunes pruning prunus prurience pruriency prurient pruriently pruriginous prurigo prurigos pruritic pruritus prurituses prussia prussian prussianism prussianization prussianizations prussianize prussianized prussianizes prussianizing prussians prussiate prussiates prussic pruta prutah prutot prutoth pry pryer pryers prying pryingly przewalski précis précised précises précising príncipe ps psalm psalmbook psalmbooks psalmed psalming psalmist psalmists psalmodies psalmodist psalmodists psalmody psalms psalter psalteria psalterial psalteries psalterium psalters psaltery psaltries psaltry psephological psephologist psephologists psephology pseudaxis pseudaxises pseudepigraph pseudepigrapha pseudepigraphal pseudepigraphic pseudepigraphical pseudepigraphon pseudepigraphous pseudepigraphs pseudepigraphy pseudo pseudoallele pseudoalleles pseudobulb pseudobulbs pseudocarp pseudocarpous pseudocarps pseudocholinesterase pseudocholinesterases pseudoclassic pseudoclassicism pseudoclassics pseudocoel pseudocoelom pseudocoelomate pseudocoelomates pseudocoeloms pseudocoels pseudocyesis pseudogene pseudogenes pseudohermaphrodite pseudohermaphrodites pseudohermaphroditic pseudohermaphroditism pseudomonad pseudomonades pseudomonads pseudomonas pseudomorph pseudomorphic pseudomorphism pseudomorphous pseudomorphs pseudonym pseudonymity pseudonymous pseudonymously pseudonymousness pseudonyms pseudoparenchyma pseudoparenchymatous pseudopod pseudopodal pseudopodia pseudopodial pseudopodium pseudopods pseudopregnancies pseudopregnancy pseudopregnant pseudorandom pseudoscience pseudoscientific pseudoscientist pseudoscientists pseudoscorpion pseudoscorpions pseudosophisticated pseudosophistication pseudotuberculosis pshaw psi psilocin psilocins psilocybin psilomelane psilomelanes psilophyte psilophytes psilophytic psittacine psittacoses psittacosis psittacotic psoas psoases psocid psocids psoralen psoralens psoriases psoriasis psoriatic psych psychasthenia psychasthenias psychasthenic psyche psyched psychedelia psychedelias psychedelic psychedelically psychedelics psyches psychiatric psychiatrical psychiatrically psychiatrist psychiatrists psychiatry psychic psychical psychically psychics psyching psycho psychoacoustic psychoacoustical psychoacoustics psychoactive psychoanalyses psychoanalysis psychoanalyst psychoanalysts psychoanalytic psychoanalytical psychoanalytically psychoanalyze psychoanalyzed psychoanalyzes psychoanalyzing psychobabble psychobabbler psychobabblers psychobabbles psychobiographer psychobiographers psychobiographic psychobiographical psychobiographies psychobiography psychobiologic psychobiological psychobiologically psychobiologist psychobiologists psychobiology psychochemical psychochemicals psychodrama psychodramas psychodramatic psychodynamic psychodynamically psychodynamics psychogenesis psychogenetic psychogenetically psychogenic psychogenically psychograph psychographic psychographics psychographs psychohistorian psychohistorians psychohistorical psychohistories psychohistory psychokineses psychokinesis psychokinetic psychokinetically psycholinguist psycholinguistic psycholinguistics psycholinguists psychologic psychological psychologically psychologies psychologism psychologist psychologists psychologize psychologized psychologizes psychologizing psychology psychometric psychometrical psychometrically psychometrician psychometricians psychometrics psychometrist psychometrists psychometry psychomotor psychoneuroses psychoneurosis psychoneurotic psychoneurotics psychopath psychopathic psychopathically psychopathologic psychopathological psychopathologically psychopathologist psychopathologists psychopathology psychopaths psychopathy psychopharmacologic psychopharmacological psychopharmacologist psychopharmacologists psychopharmacology psychophysical psychophysically psychophysicist psychophysicists psychophysics psychophysiologic psychophysiological psychophysiologically psychophysiologist psychophysiologists psychophysiology psychos psychoses psychosexual psychosexuality psychosexually psychosis psychosocial psychosocially psychosomatic psychosomatically psychosomatics psychosurgeon psychosurgeons psychosurgeries psychosurgery psychosurgical psychosynthesis psychotechnical psychotechnician psychotechnicians psychotechnics psychotherapeutic psychotherapeutically psychotherapeutics psychotherapies psychotherapist psychotherapists psychotherapy psychotic psychotically psychotics psychotomimetic psychotomimetically psychotomimetics psychotropic psychotropics psychrometer psychrometers psychrometric psychrometry psychrophile psychrophiles psychrophilic psylla psyllas psyllid psyllids psyllium psylliums psywar psywars pt pta ptarmigan ptarmigans ptas pteranodon pteranodons pteridine pteridines pteridological pteridologist pteridologists pteridology pteridophyte pteridophytes pteridophytic pteridophytous pteridosperm pteridosperms pterin pterins pterodactyl pterodactyloid pterodactylous pterodactyls pteropod pteropodan pteropodans pteropods pterosaur pterosaurs pteroylglutamic pterygia pterygial pterygium pterygiums pterygoid pterygoids pteryla pterylae ptisan ptisans ptolemaic ptolemaist ptolemaists ptolemies ptolemy ptomaine ptoses ptosis ptotic ptyalin ptyalism ptyalisms pub puberal pubertal puberty puberulent puberulous pubes pubescence pubescent pubic pubis public publica publically publican publicans publication publications publicist publicists publicity publicize publicized publicizes publicizing publicly publicness publico publics publish publishable published publisher publishers publishes publishing pubs puccini puccoon puccoons puce puck pucka pucker puckered puckering puckers puckery puckish puckishly puckishness pucks pudding puddings puddingstone puddingstones puddle puddled puddler puddlers puddles puddling puddlings puddly pudency pudenda pudendal pudendum pudgier pudgiest pudginess pudgy pudibund pueblo pueblos puerile puerilely puerileness puerilism puerilisms puerilities puerility puerperal puerperia puerperium puerto puff puffball puffballs puffed puffer puffers puffery puffier puffiest puffily puffin puffiness puffing puffins puffs puffy pug pugaree pugarees puget puggaree puggarees pugged pugging puggree puggrees pugil pugilism pugilist pugilistic pugilists pugmark pugmarks pugnacious pugnaciously pugnaciousness pugnacity pugs puisne puisnes puissance puissant puissantly puke puked pukes puking pukka pul pula pulas pulaski pulchritude pulchritudinous pule puled puler pulers pules puli pulik puling pulis pulitzer pull pullback pullbacks pulled puller pullers pullet pullets pulley pulleys pulling pullman pullmans pullorum pullout pullouts pullover pullovers pulls pullulate pullulated pullulates pullulating pullulation pullulations pullulative pulmonale pulmonalia pulmonary pulmonate pulmonates pulmonic pulmotor pulmotors pulp pulpal pulpally pulped pulper pulpers pulpier pulpiest pulpiness pulping pulpit pulpits pulpous pulps pulpwood pulpy pulque pulques puls pulsant pulsar pulsars pulsate pulsated pulsates pulsatile pulsating pulsation pulsations pulsator pulsators pulsatory pulse pulsed pulsejet pulsejets pulser pulsers pulses pulsing pulsometer pulsometers pulverable pulverizable pulverization pulverizations pulverizator pulverizators pulverize pulverized pulverizer pulverizers pulverizes pulverizing pulverous pulverulent pulvilli pulvillus pulvinate pulvinated pulvini pulvinus puma pumas pumelo pumelos pumice pumiced pumiceous pumicer pumicers pumices pumicing pumicite pumicites pummel pummeled pummeling pummelled pummelling pummelo pummelos pummels pump pumped pumper pumpernickel pumpernickels pumpers pumping pumpkin pumpkins pumpkinseed pumpkinseeds pumps pun puna punch punchball punchboard punchboards punchbowl punchbowls punched puncheon puncheons puncher punchers punches punchier punchiest punchily punchinello punchinelloes punchinellos punchiness punching punchless punchy punctate punctated punctation punctations punctilio punctilios punctilious punctiliously punctiliousness punctual punctuality punctually punctualness punctuate punctuated punctuates punctuating punctuation punctuations punctuative punctuator punctuators puncturable puncture punctured punctures puncturing pundit punditry pundits pung pungency pungent pungently pungle pungled pungles pungling pungs punic punier puniest punily puniness punish punishability punishable punishably punished punisher punishers punishes punishing punishment punishments punition punitions punitive punitively punitiveness punitory punjab punjabi punjabis punji punk punka punkah punkahs punkas punker punkers punkie punkier punkies punkiest punkin punkiness punkins punkish punks punky punned punnet punnets punnier punniest punning punningly punny puns punster punsters punt punted punter punters punties punting punts punty punxsutawney puny pup pupa pupae pupal puparia puparium pupas pupate pupated pupates pupating pupation pupations pupfish pupfishes pupil pupilage pupilages pupilar pupillage pupillages pupillary pupils pupiparous pupped puppet puppeteer puppeteers puppetlike puppetries puppetry puppets puppies pupping puppis puppy puppyhood puppyish puppylike pups purana puranas puranic purblind purblindly purblindness purcell purchasability purchasable purchase purchased purchaser purchasers purchases purchasing purdah purdahs pure pureblood pureblooded purebloods purebred purebreds puree pureed pureeing purees purely pureness purer purest purfle purfled purfles purfling purgation purgations purgative purgatives purgatorial purgatories purgatory purge purgeable purged purger purgers purges purging puri purification purifications purificator purificators purificatory purified purifier purifiers purifies purify purifying purim purine purines puris purism purisms purist puristic puristically purists puritan puritanical puritanically puritanicalness puritanism puritans purity purkinje purl purled purlieu purlieus purlin purline purlines purling purlins purloin purloined purloiner purloiners purloining purloins purls puromycin puromycins purple purpled purpleheart purplehearts purpler purples purplest purpling purplish purply purport purported purportedly purporting purports purpose purposed purposeful purposefully purposefulness purposeless purposelessly purposelessness purposely purposes purposing purposive purposively purposiveness purpura purpuras purpure purpures purpuric purpurin purpurins purr purred purring purringly purrs purse pursed purselike purser pursers purses pursestrings pursier pursiest pursiness pursing purslane pursuable pursuance pursuant pursue pursued pursuer pursuers pursues pursuing pursuit pursuits pursuivant pursuivants pursy purtenance purtenances purty purulence purulent purulently purvey purveyance purveyed purveying purveyor purveyors purveys purview purviews purée puréed puréeing purées puréing pus pusey puseyism puseyite puseyites push pushback pushbacks pushball pushballs pushbutton pushbuttons pushcart pushcarts pushchair pushchairs pushdown pushdowns pushed pusher pushers pushes pushful pushfulness pushier pushiest pushily pushiness pushing pushingly pushkin pushover pushovers pushpin pushpins pushrod pushrods pushtu pushtun pushtuns pushup pushups pushy pusillanimity pusillanimous pusillanimously puss pusses pussier pussies pussiest pussley pussy pussycat pussycats pussyfoot pussyfooted pussyfooter pussyfooters pussyfooting pussyfoots pussytoes pustulant pustulants pustular pustulate pustulated pustulates pustulating pustulation pustulations pustule pustules put putamen putamina putaminous putative putatively putdown putdownable putdowns putlog putlogs putnam putoff putoffs putonghua putout putouts putrefacient putrefaction putrefactive putrefied putrefies putrefy putrefying putrescence putrescent putrescible putrescine putrescines putrid putridity putridly putridness puts putsch putsches putschist putschists putt putted puttee puttees putter puttered putterer putterers puttering putters putti puttied putties putting puttingly putto puttrefied puttrefies puttrefying putts putty puttying puttyless puttylike puttyroot puttyroots putz putzed putzes putzing puzzle puzzled puzzleheaded puzzleheadedness puzzlement puzzler puzzlers puzzles puzzling puzzlingly pvc pycnidia pycnidial pycnidium pycnogonid pycnogonids pycnometer pycnometers pyelitic pyelitis pyelitises pyelogram pyelograms pyelographic pyelography pyelonephritic pyelonephritis pyelonephritises pyemia pyemic pygidia pygidial pygidium pygmaean pygmalion pygmean pygmies pygmoid pygmy pyknic pyknics pylon pylons pylori pyloric pylorus pylos pyoderma pyodermas pyodermic pyogenesis pyogenic pyoid pyongyang pyorrhea pyorrheal pyorrheas pyorrhoea pyorrhoeas pyosis pyracantha pyracanthas pyralid pyralidid pyralidids pyralids pyramid pyramidal pyramidally pyramided pyramidic pyramidical pyramiding pyramids pyramus pyran pyrans pyrargyrite pyrargyrites pyre pyrene pyrenean pyrenees pyrenes pyrenoid pyrenoids pyres pyrethrin pyrethrins pyrethroid pyrethroids pyrethrum pyrethrums pyretic pyrex pyrexia pyrexial pyrexias pyrexic pyrheliometer pyrheliometers pyrheliometric pyric pyridic pyridine pyridines pyridoxal pyridoxals pyridoxamine pyridoxamines pyridoxin pyridoxine pyridoxines pyridoxins pyriform pyrimethamine pyrimethamines pyrimidine pyrimidines pyrite pyrites pyritic pyritical pyrocellulose pyrocelluloses pyrochemical pyrochemically pyroclastic pyroelectric pyroelectricity pyroelectrics pyrogallic pyrogallol pyrogallols pyrogen pyrogenic pyrogenicity pyrogenous pyrogens pyrograph pyrographer pyrographers pyrographic pyrographies pyrographs pyrography pyroligneous pyrolusite pyrolusites pyrolysis pyrolytic pyrolytically pyrolyze pyrolyzed pyrolyzes pyrolyzing pyromancy pyromania pyromaniac pyromaniacal pyromaniacs pyromantic pyrometallurgical pyrometallurgies pyrometallurgy pyrometer pyrometers pyrometric pyrometrical pyrometrically pyrometry pyromorphite pyromorphites pyronine pyronines pyrope pyropes pyrophoric pyrophosphate pyrophosphates pyrophosphatic pyrophosphoric pyrophyllite pyrophyllites pyrosis pyrostat pyrostats pyrosulfate pyrosulfates pyrosulfuric pyrotechnic pyrotechnical pyrotechnically pyrotechnics pyrotechnist pyrotechnists pyrotechny pyroxene pyroxenes pyroxenic pyroxenite pyroxenites pyroxenitic pyroxenoid pyroxenoids pyroxylin pyroxyline pyroxylines pyroxylins pyrrhic pyrrhics pyrrhonism pyrrhonist pyrrhonists pyrrhotine pyrrhotines pyrrhotite pyrrhotites pyrrhuloxia pyrrhuloxias pyrrhus pyrrole pyrroles pyrrolic pyruvate pyruvates pyruvic pythagoras pythagorean pythagoreanism pythagoreans pythiad pythiads pythian pythias pythic python pythoness pythonesses pythonic pythons pyuria pyurias pyx pyxes pyxides pyxidia pyxidium pyxie pyxies pyxis páros pátmos pâte pâté pâtés pépin périgord pétanque père q qantas qatar qatari qataris qattara qed qilian qindarka qindarkas qindars qinghai qintar qintars qiviut qiviuts qoph qophs qt qty qua quaalude quaaludes quack quacked quackery quacking quackish quackishly quacks quacksalver quacksalvers quacky quad quadded quadding quadragenarian quadragesima quadragesimal quadrangle quadrangles quadrangular quadrangularly quadrangularness quadrant quadrantal quadrantid quadrants quadraphonic quadraphonically quadraphonics quadraphony quadrasonic quadrat quadrate quadrated quadrates quadratic quadratically quadratics quadrating quadrats quadrature quadratures quadrennia quadrennial quadrennially quadrennials quadrennium quadrenniums quadric quadricentennial quadricentennials quadriceps quadricipital quadrics quadrifid quadriga quadrigae quadrilateral quadrilaterals quadrille quadrilles quadrillion quadrillions quadrillionth quadrillionths quadrinomial quadripartite quadriphonic quadriphonics quadriphony quadriplegia quadriplegic quadriplegics quadrisect quadrivalence quadrivalency quadrivalent quadrivia quadrivial quadrivium quadroon quadroons quadrophonic quadrumanal quadrumanous quadrumvir quadrumvirate quadrumvirates quadrumvirs quadruped quadrupedal quadrupeds quadruple quadrupled quadruples quadruplet quadruplets quadruplicate quadruplicated quadruplicately quadruplicates quadruplicating quadruplication quadruplications quadruplicity quadrupling quadruply quadrupole quadrupoles quads quaere quaeres quaestor quaestorial quaestors quaestorship quaestorships quaff quaffed quaffer quaffers quaffing quaffs quag quagga quaggas quaggier quaggiest quaggy quagmire quagmires quags quahaug quahaugs quahog quahogs quai quaich quaiches quaigh quaighs quail quailed quailing quails quaint quainter quaintest quaintly quaintness quake quaked quakeproof quakeproofed quakeproofing quakeproofs quaker quakerish quakerism quakerly quakers quakes quaking quaky quale qualia qualifiable qualification qualifications qualificatory qualified qualifiedly qualifier qualifiers qualifies qualify qualifying qualitative qualitatively qualities quality qualm qualmish qualmishly qualmishness qualms qualmy quamash quamashes quandang quandangs quandaries quandary quandong quandongs quango quangos quant quanta quantal quantally quantasome quantasomes quanted quantic quantics quantifiability quantifiable quantifiably quantification quantificational quantificationally quantifications quantified quantifier quantifiers quantifies quantify quantifying quanting quantitate quantitated quantitates quantitating quantitation quantitations quantitative quantitatively quantitativeness quantities quantity quantization quantizations quantize quantized quantizer quantizers quantizes quantizing quants quantum quapaw quapaws quarantinable quarantine quarantined quarantines quarantining quark quarks quarrel quarreled quarreler quarrelers quarreling quarrelled quarreller quarrellers quarrelling quarrels quarrelsome quarrelsomely quarrelsomeness quarried quarrier quarriers quarries quarry quarrying quarryman quarrymen quart quartan quartans quarter quarterage quarterages quarterback quarterbacked quarterbacking quarterbacks quarterdeck quarterdecks quartered quarterfinal quarterfinalist quarterfinalists quarterfinals quartering quarterlies quarterly quartermaster quartermasters quartern quarterns quarters quartersaw quartersawed quartersawing quartersawn quartersaws quarterstaff quarterstaves quartertone quartertones quartet quartets quartette quartettes quartic quartics quartile quartiles quarto quartos quarts quartz quartzes quartziferous quartzite quartzitic quartzose quasar quasars quash quashed quashes quashing quasi quasiliquid quasimodo quasiparticle quasiparticles quasiperiodic quasiperiodicity quassia quassias quatercentenaries quatercentenary quaternaries quaternary quaternion quaternions quaternities quaternity quatorze quatrain quatrains quatre quatrefoil quatrefoils quattrocento quattrocentos quattuordecillion quattuordecillions quaver quavered quavering quaveringly quavers quavery quay quayage quayages quays quayside quaysides quean queans queasier queasiest queasily queasiness queasy queazier queaziest queazy quebec quebecer quebecers quebecker quebeckers quebecois quebracho quebrachos quechan quechua quechuan quechuas quechumaran quechumarans queen queen's queened queening queenlier queenliest queenliness queenly queens queensberry queenship queenships queenside queensides queensland queer queered queerer queerest queering queerish queerly queerness queers queleas quell quelled queller quellers quelling quells quem quench quenchable quenched quencher quenchers quenches quenching quenchless quenelle quenelles quercetin quercetins quercitron quercitrons queried querier queriers queries querist querists quern querns querulous querulously querulousness query querying quesadilla quesadillas quest quested quester questers questing question questionability questionable questionableness questionably questionaries questionary questioned questioner questioners questioning questioningly questionings questionless questionnaire questionnaires questions questor questors quests quetzal quetzalcoatl quetzales quetzals queue queued queueing queuer queuers queues queuing quibble quibbled quibbler quibblers quibbles quibbling quiberon quiche quiches quiché quichés quick quicken quickened quickener quickeners quickening quickens quicker quickest quickie quickies quicklime quickly quickness quicks quicksand quicksands quickset quicksets quicksilver quickstep quickstepped quickstepping quicksteps quid quiddities quiddity quidnunc quidnuncs quids quiescence quiescent quiescently quiet quieted quieten quietened quietening quietens quieter quietest quieting quietism quietisms quietist quietistic quietists quietly quietness quiets quietude quietus quietuses quiff quiffs quill quillback quillbacks quilled quiller quilling quills quillwork quillworks quillwort quillworts quilt quilted quilter quilters quilting quilts quinacrine quinalizarin quinalizarins quinary quinate quince quincentenary quincentennial quinces quincey quincuncial quincuncially quincunx quincunxes quincunxial quincy quindecennial quindecennials quindecillion quindecillions quinella quinellas quinidine quinidines quiniela quinielas quinine quinines quinnat quinoa quinoas quinoid quinoidine quinoidines quinoids quinoline quinolines quinone quinones quinonoid quinquagenarian quinquagenarians quinquagesima quinquagesimas quinquennia quinquennial quinquennially quinquennials quinquennium quinquenniums quinquevalence quinquevalent quinsy quint quinta quintain quintains quintal quintals quintan quintas quintessence quintessential quintessentially quintet quintets quintette quintettes quintic quintics quintile quintiles quintilian quintillion quintillions quintillionth quintillionths quints quintuple quintupled quintuples quintuplet quintuplets quintuplicate quintuplicated quintuplicates quintuplicating quintupling quintuply quinze quip quipped quipper quippers quipping quippy quips quipster quipsters quipu quipus quire quires quirinal quirinus quirk quirked quirkier quirkiest quirkily quirkiness quirking quirkish quirks quirky quirt quirts quisling quislingism quislings quit quitch quitclaim quitclaimed quitclaiming quitclaims quite quito quitrent quitrents quits quittance quittances quitted quitter quitters quitting quittor quittors quiver quivered quivering quiveringly quivers quivery quixote quixotes quixotic quixotical quixotically quixotism quixotry quiz quizmaster quizmasters quizzed quizzer quizzers quizzes quizzical quizzicality quizzically quizzing quo quod quodlibet quodlibets quoi quoin quoined quoining quoins quoit quoits quokka quokkas quondam quonset quorum quorums quos quota quotability quotable quotably quotas quotation quotational quotationally quotations quote quoted quoter quoters quotes quoth quotha quotidian quotient quotients quoting quran qurush qurushes québec québecois qwerty r ra rabat rabato rabatos rabats rabbet rabbeted rabbeting rabbets rabbi rabbin rabbinate rabbinates rabbinic rabbinical rabbinically rabbinism rabbinist rabbinistic rabbinists rabbinitic rabbins rabbis rabbit rabbitbrush rabbited rabbiter rabbiters rabbiting rabbitries rabbitry rabbits rabbity rabble rabbled rabblement rabblements rabbler rabblers rabbles rabbling rabe rabelais rabelaisian rabi rabia rabic rabid rabidity rabidly rabidness rabies rabietic raccoon raccoons race racecar racecars racecourse racecourses raced racehorse racehorses racemate racemates raceme racemes racemic racemiform racemism racemization racemizations racemize racemized racemizes racemizing racemose racemosely racer racers racerunner racerunners races racetrack racetracker racetrackers racetracks racewalker racewalkers racewalking raceway raceways rachel rachial rachides rachilla rachillae rachis rachises rachitic rachitis rachmaninoff rachmanism racial racialism racialist racialistic racialists racially racier raciest racily racine raciness racing racism racist racists rack racked racker rackers racket racketed racketeer racketeered racketeering racketeers racketing rackets rackety rackful rackfuls racking rackingly racks raclette raclettes raclopride racon racons raconteur raconteurs racoon racoons racquet racquetball racquets racy rad radar radars radarscope radarscopes raddle raddled raddles raddling radial radially radials radian radiance radiancy radians radiant radiantly radiants radiate radiated radiately radiates radiating radiation radiational radiationless radiations radiative radiator radiators radical radicalism radicalization radicalizations radicalize radicalized radicalizes radicalizing radically radicalness radicals radicand radicands radicchio radicchios radices radicle radicles radicular radii radio radioactive radioactively radioactivity radioallergosorbent radioastronomy radioautograph radioautographic radioautographs radioautography radiobiologic radiobiological radiobiologically radiobiologist radiobiologists radiobiology radiobroadcast radiobroadcasted radiobroadcaster radiobroadcasters radiobroadcasting radiobroadcasts radiocarbon radiocast radiocasts radiochemical radiochemically radiochemist radiochemistry radiochemists radiochromatogram radiochromatograms radioecological radioecologist radioecologists radioecology radioed radioelement radioelements radiogenic radiogram radiograms radiograph radiographed radiographer radiographers radiographic radiographically radiographing radiographs radiography radioimmunoassay radioimmunoassayable radioimmunological radioimmunology radioing radioiodine radioiodines radioisotope radioisotopes radioisotopic radioisotopically radiolabel radiolabeled radiolabeling radiolabelled radiolabelling radiolabels radiolarian radiolarians radiolocation radiologic radiological radiologically radiologist radiologists radiology radiolucency radiolucent radiolyses radiolysis radiolytic radioman radiomen radiometer radiometers radiometric radiometrically radiometry radiomimetic radionuclide radionuclides radiopacity radiopaque radiopharmaceutical radiopharmaceuticals radiophone radiophones radiophonic radiophoto radiophotograph radiophotographs radiophotography radiophotos radioprotection radioprotections radioprotective radios radioscopic radioscopical radioscopy radiosensitive radiosensitivity radiosonde radiosondes radiostrontium radiotelegraph radiotelegraphic radiotelegraphs radiotelegraphy radiotelemetric radiotelemetry radiotelephone radiotelephones radiotelephonic radiotelephony radiotherapies radiotherapist radiotherapists radiotherapy radiothorium radiotoxic radiotoxicity radiotracer radiotracers radish radishes radium radius radiuses radix radixes radome radomes radon rads radula radulae radular radwaste raeburn raff raffia raffias raffinate raffinates raffinose raffinoses raffish raffishly raffishness raffle raffled raffler rafflers raffles rafflesia rafflesias raffling raft rafted rafter raftered rafters rafting rafts raftsman raftsmen rag raga ragamuffin ragamuffins ragas ragbag ragbags rage raged rages ragged raggedier raggediest raggedly raggedness raggedy ragging raggle ragi raging ragis raglan raglans ragman ragmen ragnarok ragout ragouts ragpicker ragpickers rags ragtag ragtime ragtop ragtops ragusa ragweed ragwort ragworts rah raiatea raid raided raider raiders raiding raids rail railbird railbirds railbus railcar railcars railed railer railers railhead railheads railing railings railleries raillery railroad railroaded railroader railroaders railroading railroadings railroads rails railway railways raiment rain rainbird rainbirds rainbow rainbowlike rainbows raincoat raincoats raindrop raindrops rained rainfall rainfalls rainforest rainforests rainier rainiest raininess raining rainless rainmaker rainmakers rainmaking rainout rainouts rainproof rains rainspout rainspouts rainsquall rainsqualls rainstorm rainstorms rainwash rainwater rainwear rainy raise raised raiser raisers raises raisin raising raisingly raisings raisins raison raisonné raisonnés raisons raj raja rajab rajabs rajah rajahs rajas rajasthan rajasthani rajpoot rajpoots rajput rajputana rajputs rajs rake raked rakee rakees rakehell rakehells rakehelly raker rakers rakes raki raking rakis rakish rakishly rakishness rale raleigh rales ralik rallentando rallentandos rallied rallies ralliform rally rallye rallyes rallying ralph ralphed ralphing ralphs ram rama ramada ramadan ramadas ramadhan ramakrishna raman ramate ramayana ramble rambled rambler ramblers rambles rambling ramblingly ramblings rambo rambos rambouillet rambouillets rambunctious rambunctiously rambunctiousness rambutan rambutans ramekin ramekins ramequin ramequins rameses ramet ramets rami ramie ramification ramifications ramified ramifies ramiform ramify ramifying ramillies ramism ramist ramists ramjet ramjets rammed rammer rammers ramming ramona ramonas ramose ramous ramp rampage rampaged rampageous rampageously rampageousness rampager rampagers rampages rampaging rampancy rampant rampantly rampart ramparted ramparting ramparts ramped rampike rampikes ramping rampion rampions ramps ramrod ramrodded ramrodding ramrods rams ramses ramshackle ramshorn ramshorns ramson ramsons ramtil ramtilla ramtillas ramtils ramulose ramus ran ranch ranched rancher rancheria rancherias ranchero rancheros ranchers ranches ranching ranchman ranchmen rancho ranchos rancid rancidity rancidness rancor rancorous rancorously rancorousness rancors rand randan randans randier randiest random randomization randomizations randomize randomized randomizer randomizers randomizes randomizing randomly randomness rands randy ranee ranees rang range ranged rangefinder rangefinders rangeland rangelands ranger rangers ranges rangier rangiest ranginess ranging rangoon rangy rani ranid ranids ranis rank ranked ranker rankers rankest rankine ranking rankings rankle rankled rankles rankling rankly rankness ranks ransack ransacked ransacker ransackers ransacking ransacks ransom ransomed ransomer ransomers ransoming ransoms rant ranted ranter ranters ranting rantingly rantings rants ranula ranulas ranunculi ranunculus ranunculuses rap rapacious rapaciously rapaciousness rapacity rapallo rape raped raper rapers rapes rapeseed rapeseeds raphae raphael raphaelesque raphaelite raphaelites raphaelitism raphe raphia raphias raphide raphides raphis rapid rapider rapidest rapidity rapidly rapidness rapids rapier rapierlike rapiers rapine rapines raping rapini rapist rapists rapparee rapparees rapped rappee rappees rappel rappelled rappelling rappels rappen rapper rappers rapping rappini rapport rapporteur rapporteurs rapprochement rapprochements raps rapscallion rapscallions rapt raptly raptness raptor raptorial raptors rapture raptured raptures rapturing rapturous rapturously rapturousness rara rarae rare rarebit rarebits raree rarefaction rarefactional rarefactions rarefactive rarefiable rarefication rarefied rarefies rarefy rarefying rarely rareness rarer rareripe rareripes rarest rarified rarifies rarify rarifying raring rarities rarity rarotonga rasa rasae rasbora rasboras rascal rascalities rascality rascally rascals rase rased rases rash rasher rashers rashes rashest rashly rashness rasing rasorial rasp raspberries raspberry rasped rasper raspers raspier raspiest rasping raspingly rasps rasputin raspy rasselas rasta rastafarian rastafarianism rastafarians rastas raster rasters rat rata ratability ratable ratableness ratables ratably ratafee ratafees ratafia ratafias ratak rataplan rataplans ratatouille ratatouilles ratbag ratbags ratchet ratcheted ratcheting ratchets rate rateable rated ratel ratels ratemaking ratemakings ratemeter ratemeters ratepayer ratepayers rater raters rates ratfink ratfinks ratfish ratfishes rathe rather rathskeller rathskellers raticide raticides ratifiable ratification ratifications ratified ratifier ratifiers ratifies ratify ratifying ratine ratines rating ratings ratiné ratio ratiocinate ratiocinated ratiocinates ratiocinating ratiocination ratiocinations ratiocinative ratiocinator ratiocinators ration rational rationale rationales rationalism rationalist rationalistic rationalistically rationalists rationalities rationality rationalizable rationalization rationalizations rationalize rationalized rationalizer rationalizers rationalizes rationalizing rationally rationalness rationed rationing rations ratios ratite ratites ratlike ratlin ratline ratlines ratlins ratoon ratooned ratooning ratoons rats ratsbane ratsbanes rattail rattails rattan rattans ratted ratteen ratteens ratter ratters rattier rattiest ratting rattle rattlebox rattleboxes rattlebrain rattlebrained rattlebrains rattled rattler rattlers rattles rattlesnake rattlesnakes rattletrap rattletraps rattling rattlingly rattly rattoon rattooned rattooning rattoons rattrap rattraps ratty raucity raucous raucously raucousness raunch raunchier raunchiest raunchily raunchiness raunchy rauwolfia rauwolfias ravage ravaged ravagement ravagements ravager ravagers ravages ravaging rave raved ravel raveled raveler ravelers raveling ravelings ravelled ravelling ravellings ravello ravelment ravelments ravels raven ravened ravener raveners ravening raveningly ravenings ravenna ravenous ravenously ravenousness ravens raver ravers raves ravigote ravigotes ravigotte ravigottes ravin ravine ravined ravines raving ravingly ravings ravins ravioli raviolis ravish ravished ravisher ravishers ravishes ravishing ravishingly ravishment ravishments raw rawalpindi rawboned rawer rawest rawhide rawhided rawhides rawhiding rawinsonde rawinsondes rawly rawness ray rayed raying rayleigh rayless raylessness raynaud rayon rayonism rayonist rayonistic rayonists rays raze razed razee razees razer razers razes razing razor razorback razorbacks razorbill razorbills razorblade razorblades razors razz razzed razzes razzing razzle razzmatazz rca rd re rea reabsorb reabsorbed reabsorbing reabsorbs reabsorption reabsorptions reaccelerate reaccelerated reaccelerates reaccelerating reaccept reaccepted reaccepting reaccepts reaccession reaccessioned reaccessioning reaccessions reacclimatize reacclimatized reacclimatizes reacclimatizing reaccredit reaccreditation reaccreditations reaccredited reaccrediting reaccredits reach reachable reached reacher reachers reaches reaching reacquaint reacquainted reacquainting reacquaints reacquire reacquired reacquires reacquiring reacquisition reacquisitions react reactance reactant reactants reacted reacting reaction reactionaries reactionary reactionaryism reactions reactivate reactivated reactivates reactivating reactivation reactivations reactive reactively reactiveness reactivity reactor reactors reacts read readability readable readableness readably readapt readapted readapting readapts readdress readdressed readdresses readdressing reader readerly readers readership readerships readied readier readies readiest readily readiness reading readings readjust readjusted readjuster readjusters readjusting readjustment readjustments readjusts readmission readmissions readmit readmits readmitted readmitting readopt readopted readopting readopts readout readouts reads ready readying readymade reaffirm reaffirmation reaffirmations reaffirmed reaffirming reaffirms reaffix reaffixed reaffixes reaffixing reagent reagents reaggregate reaggregated reaggregates reaggregating reaggregation reaggregations reagin reaginic reaginically reagins real realer reales realest realgar realgars realia realign realigned realigning realignment realignments realigns realism realist realistic realistically realists realities reality realizability realizable realizably realization realizationism realizationist realizationists realizations realize realized realizer realizers realizes realizing reallocate reallocated reallocates reallocating reallocation reallocations really realm realms realness realpolitik realpolitiker realpolitikers realpolitiks reals realties realtor realtors realty ream reamed reamer reamers reaming reams reanalyses reanalysis reanalyze reanalyzed reanalyzes reanalyzing reanimate reanimated reanimates reanimating reanimation reanimations reannex reannexation reannexations reannexed reannexes reannexing reap reaped reaper reapers reaphook reaphooks reaping reappear reappearance reappearances reappeared reappearing reappears reapplication reapplications reapplied reapplies reapply reapplying reappoint reappointed reappointing reappointment reappointments reappoints reapportion reapportioned reapportioning reapportionment reapportionments reapportions reappraisal reappraisals reappraise reappraised reappraises reappraising reappropriate reappropriated reappropriates reappropriating reapprove reapproved reapproves reapproving reaps rear reared rearer rearers rearguard rearguards reargue reargued reargues rearguing reargument rearguments rearing rearm rearmament rearmaments rearmed rearming rearmost rearms rearousal rearousals rearouse rearoused rearouses rearousing rearrange rearranged rearrangement rearrangements rearranges rearranging rearrest rearrested rearresting rearrests rears rearticulate rearticulated rearticulates rearticulating rearview rearward rearwards reascend reascended reascending reascends reascent reascents reason reasonability reasonable reasonableness reasonably reasoned reasoner reasoners reasoning reasonings reasonless reasonlessly reasons reassemblage reassemblages reassemble reassembled reassembles reassemblies reassembling reassembly reassert reasserted reasserting reassertion reassertions reasserts reassess reassessed reassesses reassessing reassessment reassessments reassign reassigned reassigning reassignment reassignments reassigns reassume reassumed reassumes reassuming reassurance reassurances reassure reassured reassures reassuring reassuringly reata reatas reattach reattached reattaches reattaching reattachment reattachments reattain reattained reattaining reattains reattempt reattempted reattempting reattempts reattribute reattributed reattributes reattributing reattribution reattributions reaumur reauthorization reauthorizations reauthorize reauthorized reauthorizes reauthorizing reave reaved reaver reavers reaves reaving reawake reawaked reawaken reawakened reawakening reawakens reawakes reawaking reb rebait rebaited rebaiting rebaits rebalance rebalanced rebalances rebalancing rebaptism rebaptisms rebaptize rebaptized rebaptizes rebaptizing rebar rebarbative rebarbatively rebars rebate rebated rebater rebaters rebates rebating rebato rebatos rebbe rebbes rebec rebecca rebeck rebecks rebecs rebegan rebegin rebeginning rebegins rebegun rebel rebelled rebelling rebellion rebellions rebellious rebelliously rebelliousness rebels rebid rebidden rebidding rebids rebilling rebind rebinding rebinds rebirth rebirths reblend reblended reblending reblends reblochon rebloom rebloomed reblooming reblooms reboant reboard reboarded reboarding reboards reboil reboiled reboiling reboils rebook rebooked rebooking rebooks reboot rebooted rebooting reboots rebore rebored rebores reboring reborn rebottle rebottled rebottles rebottling rebought rebound rebounded rebounder rebounders rebounding rebounds rebozo rebozos rebranch rebranched rebranches rebranching rebred rebreed rebreeding rebreeds rebroadcast rebroadcasted rebroadcasting rebroadcasts rebs rebuff rebuffed rebuffing rebuffs rebuild rebuilding rebuilds rebuilt rebuke rebuked rebuker rebukers rebukes rebuking reburial reburials reburied reburies rebury reburying rebus rebuses rebut rebuts rebuttable rebuttal rebuttals rebutted rebutter rebutters rebutting rebuy rebuying rebuys rec recalcitrance recalcitrancy recalcitrant recalcitrants recalculate recalculated recalculates recalculating recalculation recalculations recalescence recalescences recalescent recalibrate recalibrated recalibrates recalibrating recalibration recalibrations recall recallability recallable recalled recaller recallers recalling recalls recamier recamiers recanalization recanalizations recanalize recanalized recanalizes recanalizing recant recantation recantations recanted recanter recanters recanting recants recap recapitalization recapitalizations recapitalize recapitalized recapitalizes recapitalizing recapitulate recapitulated recapitulates recapitulating recapitulation recapitulations recapitulative recapitulatory recappable recapped recapping recaps recapture recaptured recaptures recapturing recast recasting recasts recce recces recd recede receded recedes receding receipt receipted receipting receipts receivable receivables receive received receiver receivers receivership receiverships receives receiving recency recension recensions recent recently recentness recentralization recentrifuge recentrifuged recentrifuges recentrifuging receptacle receptacles reception receptionist receptionists receptions receptive receptively receptiveness receptivity receptor receptors recertification recertifications recertified recertifies recertify recertifying recess recessed recesses recessing recession recessional recessionals recessionary recessions recessive recessively recessiveness recessives rechallenge rechallenged rechallenges rechallenging rechannel rechanneled rechanneling rechannels recharge rechargeable recharged recharger rechargers recharges recharging recharter rechartered rechartering recharters recheat recheats recheck rechecked rechecking rechecks recherché rechoreograph rechoreographed rechoreographing rechoreographs rechristen rechristened rechristening rechristens rechromatograph rechromatography recidivate recidivism recidivist recidivistic recidivists recidivous recipe recipes recipience recipiency recipient recipients reciprocal reciprocality reciprocally reciprocalness reciprocals reciprocate reciprocated reciprocates reciprocating reciprocation reciprocations reciprocative reciprocator reciprocators reciprocities reciprocity recirculate recirculated recirculates recirculating recirculation recirculations recision recisions recital recitalist recitalists recitals recitation recitations recitative recitatives recitativi recitativo recitativos recite recited reciter reciters recites reciting reck recked recking reckless recklessly recklessness reckon reckoned reckoner reckoners reckoning reckonings reckons recks reclad recladding reclads reclaim reclaimable reclaimant reclaimants reclaimed reclaimer reclaimers reclaiming reclaims reclamation reclamations reclassification reclassifications reclassified reclassifies reclassify reclassifying reclinate reclination reclinations recline reclined recliner recliners reclines reclining reclosable reclothe reclothed reclothes reclothing recluse recluses reclusion reclusions reclusive reclusively reclusiveness recock recocked recocking recocks recodification recodifications recodified recodifies recodify recodifying recognition recognitions recognitive recognitory recognizability recognizable recognizably recognizance recognizances recognizant recognize recognized recognizer recognizers recognizes recognizing recoil recoiled recoiler recoilers recoiling recoilless recoils recoin recoinage recoined recoining recoins recollect recollected recollecting recollection recollections recollective recollectively recollects recolonization recolonize recolonized recolonizes recolonizing recolor recolored recoloring recolors recombinant recombinants recombinase recombinases recombination recombinational recombinations recombine recombined recombines recombining recommence recommenced recommencement recommencements recommences recommencing recommend recommendable recommendation recommendations recommendatory recommended recommender recommenders recommending recommends recommission recommissioned recommissioning recommissions recommit recommitment recommitments recommits recommittal recommittals recommitted recommitting recompense recompensed recompenses recompensing recompilation recompilations recompile recompiled recompiles recompiling recompose recomposed recomposes recomposing recomposition recompositions recompress recompressed recompresses recompressing recompression recompressions recomputation recomputations recompute recomputed recomputes recomputing recon reconceive reconceived reconceives reconceiving reconcentrate reconcentrated reconcentrates reconcentrating reconcentration reconcentrations reconception reconceptions reconceptualization reconceptualizations reconceptualize reconceptualized reconceptualizes reconceptualizing reconcilability reconcilable reconcilableness reconcilably reconcile reconciled reconcilement reconcilements reconciler reconcilers reconciles reconciliation reconciliations reconciliatory reconciling recondense recondensed recondenses recondensing recondite reconditely reconditeness recondition reconditioned reconditioning reconditions reconfiguration reconfigurations reconfigure reconfigured reconfigures reconfiguring reconfirm reconfirmation reconfirmations reconfirmed reconfirming reconfirms reconnaissance reconnaissances reconnect reconnected reconnecting reconnection reconnections reconnects reconnoissance reconnoissances reconnoiter reconnoitered reconnoiterer reconnoiterers reconnoitering reconnoiters reconnoitre reconnoitred reconnoitres reconnoitring reconquer reconquered reconquering reconquers reconquest reconquests recons reconsecrate reconsecrated reconsecrates reconsecrating reconsecration reconsecrations reconsider reconsideration reconsiderations reconsidered reconsidering reconsiders reconsolidate reconsolidated reconsolidates reconsolidating reconsolidation reconsolidations reconstitute reconstituted reconstitutes reconstituting reconstitution reconstitutions reconstruct reconstructed reconstructible reconstructing reconstruction reconstructionism reconstructionist reconstructionists reconstructions reconstructive reconstructor reconstructors reconstructs recontact recontacted recontacting recontacts recontaminate recontaminated recontaminates recontaminating recontamination recontextualize recontextualized recontextualizes recontextualizing recontour recontoured recontouring recontours reconvene reconvened reconvenes reconvening reconvention reconversion reconversions reconvert reconverted reconverting reconverts reconvey reconveyance reconveyances reconveyed reconveying reconveys reconvict reconvicted reconvicting reconviction reconvictions reconvicts reconvince reconvinced reconvinces reconvincing recopied recopies recopy recopying record recordable recordation recordations recorded recorder recorders recording recordings recordist recordists records recork recorked recorking recorks recount recountal recountals recounted recounter recounters recounting recounts recoup recoupable recouped recouping recoupment recoupments recoups recourse recourses recover recoverability recoverable recoverably recovered recoverer recoverers recoveries recovering recovers recovery recreance recreancy recreant recreantly recreants recreate recreated recreates recreating recreation recreational recreationally recreationist recreationists recreations recreative recrement recremental recrements recriminate recriminated recriminates recriminating recrimination recriminations recriminative recriminator recriminators recriminatory recross recrossed recrosses recrossing recrudesce recrudesced recrudescence recrudescent recrudesces recrudescing recruit recruited recruiter recruiters recruiting recruitment recruitments recruits recrystallization recrystallizations recrystallize recrystallized recrystallizes recrystallizing recta rectal rectally rectangle rectangles rectangular rectangularity rectangularly recti rectifiability rectifiable rectification rectifications rectified rectifier rectifiers rectifies rectify rectifying rectilinear rectilinearly rectitude rectitudinous recto rector rectorate rectorates rectorial rectories rectors rectorship rectorships rectory rectos rectrices rectrix rectum rectums rectus recultivate recultivated recultivates recultivating recumbence recumbency recumbent recumbently recuperate recuperated recuperates recuperating recuperation recuperations recuperative recuperatory recur recurred recurrence recurrences recurrent recurrently recurring recurs recursion recursions recursive recursively recursiveness recurvate recurvation recurvations recurve recurved recurves recurving recusal recusancies recusancy recusant recusants recuse recused recuses recusing recut recuts recutting recyclable recyclables recycle recycled recycler recyclers recycles recycling red redact redacted redacting redaction redactional redactor redactors redacts redargue redargued redargues redarguing redate redated redates redating redbait redbaited redbaiter redbaiters redbaiting redbaitings redbaits redbelly redbird redbirds redbone redbones redbreast redbreasts redbrick redbud redbuds redbug redbugs redcap redcaps redcoat redcoats redden reddened reddener reddeners reddening reddens redder reddest reddish reddishness reddle reddled reddles reddling rede redear redecorate redecorated redecorates redecorating redecoration redecorations redecorator redecorators reded rededicate rededicated rededicates rededicating rededication rededications redeem redeemable redeemably redeemed redeemer redeemers redeeming redeems redefect redefine redefined redefines redefining redefinition redefinitions redeliver redelivered redeliveries redelivering redelivers redelivery redemption redemptional redemptioner redemptioners redemptions redemptive redemptorist redemptorists redemptory redeploy redeployed redeploying redeployment redeployments redeploys redeposit redeposited redepositing redeposits redes redescribe redescribed redescribes redescribing redescription redescriptions redesign redesigned redesigning redesigns redetect redetected redetects redetermination redeterminations redetermine redetermined redetermines redetermining redevelop redeveloped redeveloper redevelopers redeveloping redevelopment redevelopments redevelops redeye redeyes redfish redfishes redhead redheaded redheads redhorse redhorses redia rediae redial redialed redialing redialled redialling redials redias redid redifferentiation redifferentiations redigestion reding redingote redingotes redintegrate redintegrated redintegrates redintegrating redintegration redintegrations redintegrative redintegrator redintegrators redirect redirected redirecting redirection redirections redirector redirectors redirects rediscount rediscountable rediscounted rediscounting rediscounts rediscover rediscovered rediscoveries rediscovering rediscovers rediscovery rediscuss rediscussed rediscusses rediscussing redisplay redisplayed redisplaying redisplays redispose redisposed redisposes redisposing redisposition redispositions redissolve redissolved redissolves redissolving redistill redistillation redistillations redistilled redistilling redistills redistribute redistributed redistributes redistributing redistribution redistributional redistributionist redistributionists redistributions redistributive redistrict redistricted redistricting redistricts redivide redivided redivides redividing redivision redivisions redivivus redleg redlegs redline redlined redlines redlining redly redneck rednecked rednecks redness redo redoes redoing redolence redolency redolent redolently redon redone redonned redonning redons redouble redoubled redoubles redoubling redoubt redoubtable redoubtably redoubts redound redounded redounding redounds redout redouts redox redoxes redpoll redpolls redraft redrafted redrafting redrafts redraw redrawing redrawn redraws redream redreamed redreaming redreams redreamt redress redressed redresser redressers redresses redressing redressor redressors redrew redrill redrilled redrilling redrills redroot redroots reds redshank redshanks redshift redshifted redshifts redshirt redshirted redshirting redshirts redshouldered redskin redskins redstart redstarts redtop redtops redub redubbed redubbing redubs reduce reduced reducer reducers reduces reducibility reducible reducibly reducing reductant reductants reductase reductases reductio reduction reductional reductiones reductionism reductionist reductionistic reductionists reductions reductive reductively reductiveness reductivism reductivist reductivists redundancies redundancy redundant redundantly reduplicate reduplicated reduplicates reduplicating reduplication reduplications reduplicative reduplicatively reduviid reduviids redux redware redwing redwings redwood redwoods reecho reechoed reechoes reechoing reed reedbird reedbirds reedbuck reedbucks reeded reedier reediest reedified reedifies reedify reedifying reediness reeding reedings reedit reedited reediting reedition reeditions reedits reedlike reedling reedlings reedman reedmen reeds reeducate reeducated reeducates reeducating reeducation reeducations reeducative reedy reef reefable reefed reefer reefers reefing reefs reefy reek reeked reeker reekers reeking reeks reeky reel reelable reelect reelected reelecting reelection reelections reelects reeled reeler reelers reeligibility reeligible reeling reels reembroider reembroidered reembroidering reembroiders reemerge reemerged reemergence reemergences reemerges reemerging reemission reemissions reemit reemits reemitted reemitting reemphases reemphasis reemphasize reemphasized reemphasizes reemphasizing reemploy reemployed reemploying reemployment reemployments reemploys reenact reenacted reenacting reenactment reenactments reenacts reencounter reencountered reencountering reencounters reendow reendowed reendowing reendows reenergize reenergized reenergizes reenergizing reenforce reenforced reenforces reenforcing reengage reengaged reengagement reengagements reengages reengaging reengineer reengineered reengineering reengineers reengrave reengraved reengraves reengraving reenlist reenlisted reenlisting reenlistment reenlistments reenlists reenroll reenrolled reenrolling reenrolls reenter reentered reentering reenters reenthrone reenthroned reenthrones reenthroning reentrance reentrances reentrant reentrants reentries reentry reequip reequipment reequipped reequipping reequips reerect reerected reerecting reerects reescalate reescalated reescalates reescalating reescalation reescalations reestablish reestablished reestablishes reestablishing reestablishment reestimate reestimated reestimates reestimating reevaluate reevaluated reevaluates reevaluating reevaluation reevaluations reeve reeved reeves reeving reexamination reexaminations reexamine reexamined reexamines reexamining reexperience reexperienced reexperiences reexperiencing reexplore reexplored reexplores reexploring reexport reexportation reexportations reexported reexporting reexports reexpose reexposed reexposes reexposing reexposure reexposures reexpress reexpressed reexpresses reexpressing ref reface refaced refaces refacing refashion refashioned refashioning refashions refasten refastened refastening refastens refect refected refecting refection refections refectories refectory refects refed refeed refeeding refeeds refeel refeeling refeels refelt refence refenced refences refencing refer referable referee refereed refereeing referees reference referenced referencer referencers references referencing referenda referendum referendums referent referential referentiality referentially referents referral referrals referred referrer referrers referring refers refight refighting refights refigure refigured refigures refiguring refile refiled refiles refiling refill refillable refilled refilling refills refinance refinanced refinancer refinancers refinances refinancier refinanciers refinancing refind refinding refinds refine refined refinement refinements refiner refineries refiners refinery refines refining refinish refinished refinisher refinishers refinishes refinishing refire refired refires refiring refit refits refitted refitting refix refixed refixes refixing reflag reflagged reflagging reflags reflate reflated reflates reflating reflation reflationary reflect reflectance reflected reflecting reflection reflectional reflections reflective reflectively reflectiveness reflectivities reflectivity reflectometer reflectometers reflectometry reflector reflectorize reflectorized reflectorizes reflectorizing reflectors reflects reflex reflexed reflexes reflexing reflexive reflexively reflexiveness reflexives reflexivity reflexly reflexologist reflexologists reflexology refloat refloated refloating refloats reflow reflowed reflowing reflows refluence refluent reflux refluxed refluxes refluxing refocus refocused refocuses refocusing refocussed refocussing refold refolded refolding refolds reforecast reforecasting reforecasts reforest reforestation reforestations reforested reforesting reforests reforge reforged reforges reforging reform reformability reformable reformat reformate reformates reformation reformational reformations reformative reformatories reformatory reformats reformatted reformatting reformed reformer reformers reforming reformism reformist reformists reforms reformulate reformulated reformulates reformulating reformulation reformulations refortification refortified refortifies refortify refortifying refought refound refoundation refoundations refounded refounding refounds refract refracted refractile refracting refraction refractional refractive refractively refractiveness refractivity refractometer refractometers refractometric refractometry refractor refractories refractorily refractoriness refractors refractory refracts refrain refrained refrainer refrainers refraining refrainment refrainments refrains reframe reframed reframes reframing refrangibility refrangible refrangibleness refreeze refreezes refreezing refresh refreshed refreshen refreshened refreshening refreshens refresher refreshers refreshes refreshing refreshingly refreshment refreshments refried refries refrigerant refrigerants refrigerate refrigerated refrigerates refrigerating refrigeration refrigerations refrigerative refrigerator refrigerators refrigeratory refringence refringences refringent refroze refrozen refry refrying refs reft refuel refueled refueling refuelled refuelling refuels refuge refuged refugee refugeeism refugees refuges refugia refuging refugium refulgence refulgency refulgent refulgently refund refundability refundable refunded refunder refunders refunding refundment refundments refunds refurbish refurbished refurbisher refurbishers refurbishes refurbishing refurbishment refurbishments refurnish refurnished refurnishes refurnishing refusal refusals refuse refused refusednik refusedniks refusenik refuseniks refuser refusers refuses refusing refusnik refusniks refutability refutable refutably refutal refutals refutation refutations refute refuted refuter refuters refutes refuting regain regained regainer regainers regaining regains regal regale regaled regalement regalements regales regalia regaling regalities regality regally regard regardant regarded regardful regardfully regardfulness regarding regardless regardlessly regardlessness regards regather regathered regathering regathers regatta regattas regave regear regeared regearing regears regelate regelated regelates regelating regelation regelations regencies regency regenerable regeneracy regenerate regenerated regenerately regenerateness regenerates regenerating regeneration regenerations regenerative regeneratively regenerator regenerators regensburg regent regental regents regerminate regerminated regerminates regerminating regermination reggae reggaes reggio regicidal regicide regicides regild regilded regilding regilds regime regimen regimens regiment regimental regimentally regimentals regimentation regimentations regimented regimenting regiments regimes regina region regional regionalism regionalisms regionalist regionalistic regionalists regionalization regionalizations regionalize regionalized regionalizes regionalizing regionally regionals regions regisseurs register registerable registered registerer registerers registering registers registrable registrant registrants registrar registrars registration registrations registries registry regius regive regiven regives regiving reglaze reglazed reglazes reglazing reglet reglets regna regnal regnant regnum regolith regoliths regorge regorged regorges regorging regosol regosols regrade regraded regrades regrading regraft regrafted regrafting regrafts regrant regranted regranting regrants regreen regreened regreening regreens regress regressed regresses regressing regression regressions regressive regressively regressiveness regressivity regressor regressors regret regretful regretfully regretfulness regretless regrets regrettable regrettably regretted regretter regretters regretting regrew regrind regrinding regrinds regroom regroomed regrooming regrooms regroove regrooved regrooves regrooving reground regroup regrouped regrouping regroups regrow regrowing regrown regrows regrowth regrowths regular regularities regularity regularization regularizations regularize regularized regularizer regularizers regularizes regularizing regularly regulars regulate regulated regulates regulating regulation regulations regulative regulator regulators regulatory reguli reguline regulus reguluses regurgitant regurgitate regurgitated regurgitates regurgitating regurgitation regurgitations regurgitative rehab rehabbed rehabber rehabbers rehabbing rehabilitant rehabilitants rehabilitatable rehabilitate rehabilitated rehabilitates rehabilitating rehabilitation rehabilitations rehabilitative rehabilitator rehabilitators rehabs rehandle rehandled rehandles rehandling rehang rehanged rehanging rehangs rehash rehashed rehashes rehashing rehear reheard rehearing rehearings rehears rehearsal rehearsals rehearse rehearsed rehearser rehearsers rehearses rehearsing reheat reheated reheating reheats rehinge rehinged rehinges rehinging rehire rehired rehires rehiring rehospitalization rehospitalizations rehospitalize rehospitalized rehospitalizes rehospitalizing rehouse rehoused rehouses rehousing rehumanize rehumanized rehumanizes rehumanizing rehung rehydratable rehydrate rehydrated rehydrates rehydrating rehydration rehydrations rehypnotize rehypnotized rehypnotizes rehypnotizing reich reichsmark reichsmarks reichstag reidentified reidentifies reidentify reidentifying reification reifications reificatory reified reifier reifiers reifies reify reifying reign reigned reigning reignite reignited reignites reigniting reignition reigns reimage reimagine reimagined reimagines reimagining reimbursable reimburse reimbursed reimbursement reimbursements reimburses reimbursing reimmerse reimmersed reimmerses reimmersing reimplant reimplantation reimplanted reimplanting reimplants reimport reimportation reimportations reimported reimporting reimports reimpose reimposed reimposes reimposing reimposition reimpositions reimpression reimpressions rein reincarnate reincarnated reincarnates reincarnating reincarnation reincarnations reincorporate reincorporated reincorporates reincorporating reincorporation reincorporations reindeer reindeers reindict reindicted reindicting reindictment reindictments reindicts reindustrialization reindustrialize reindustrialized reindustrializes reindustrializing reined reinfection reinfections reinfestation reinfestations reinflate reinflated reinflates reinflating reinflation reinforce reinforceable reinforced reinforcement reinforcements reinforcer reinforcers reinforces reinforcing reinhabit reinhabited reinhabiting reinhabits reining reinitialization reinitializations reinitialize reinitialized reinitializer reinitializers reinitializes reinitializing reinitiate reinitiated reinitiates reinitiating reinject reinjected reinjecting reinjection reinjections reinjects reinjure reinjured reinjures reinjuries reinjuring reinjury reink reinked reinking reinks reinnervate reinnervated reinnervates reinnervating reinnervation reinoculate reinoculated reinoculates reinoculating reinoculation reinoculations reins reinsert reinserted reinserting reinsertion reinsertions reinserts reinsman reinsmen reinspect reinspected reinspecting reinspection reinspections reinspects reinspire reinspired reinspires reinspiring reinstall reinstallation reinstalled reinstalling reinstalls reinstate reinstated reinstatement reinstatements reinstates reinstating reinstitute reinstituted reinstitutes reinstituting reinstitution reinstitutionalization reinsurance reinsurances reinsure reinsured reinsurer reinsurers reinsures reinsuring reintegrate reintegrated reintegrates reintegrating reintegration reintegrations reintegrative reinter reinterpret reinterpretation reinterpretations reinterpreted reinterpreting reinterprets reinterred reinterring reinterrogate reinterrogated reinterrogates reinterrogating reinterrogation reinterrogations reinters reinterview reinterviewed reinterviewing reinterviews reintroduce reintroduced reintroduces reintroducing reintroduction reintroductions reinvade reinvaded reinvades reinvading reinvasion reinvasions reinvent reinvented reinventing reinvention reinvents reinvest reinvested reinvestigate reinvestigated reinvestigates reinvestigating reinvestigation reinvestigations reinvesting reinvestment reinvestments reinvests reinvigorate reinvigorated reinvigorates reinvigorating reinvigoration reinvigorations reinvigorator reinvigorators reis reissue reissued reissues reissuing reiter reiterate reiterated reiterates reiterating reiteration reiterations reiterative reiteratively reiterator reiterators reith rejacket rejacketed rejacketing rejackets reject rejected rejectee rejectees rejecter rejecters rejecting rejectingly rejection rejections rejective rejectivist rejector rejectors rejects rejig rejigged rejigger rejiggered rejiggering rejiggers rejigging rejigs rejoice rejoiced rejoicer rejoicers rejoices rejoicing rejoicingly rejoicings rejoin rejoinder rejoinders rejoined rejoining rejoins rejudge rejudged rejudges rejudging rejuggle rejuggled rejuggles rejuggling rejuvenate rejuvenated rejuvenates rejuvenating rejuvenation rejuvenations rejuvenator rejuvenators rejuvenescence rejuvenescences rejuvenescent rekey rekeyboard rekeyed rekeying rekeys rekindle rekindled rekindles rekindling reknit reknits reknitted reknitting relabel relabeled relabeling relabels relacquer relacquered relacquering relacquers relaid relandscape relandscaped relandscapes relandscaping relapse relapsed relapser relapsers relapses relapsing relatable relate related relatedly relatedness relater relaters relates relating relation relational relationally relations relationship relationships relative relatively relativeness relatives relativism relativist relativistic relativistically relativists relativity relativize relativized relativizes relativizing relator relators relaunch relaunched relaunches relaunching relax relaxable relaxant relaxants relaxation relaxations relaxed relaxedly relaxedness relaxer relaxers relaxes relaxin relaxing relay relayed relaying relays relearn relearned relearning relearns relearnt releasability releasable releasably release released releaser releasers releases releasing relegate relegated relegates relegating relegation relegations relend relending relends relent relented relenting relentless relentlessly relentlessness relents relevance relevancy relevant relevantly reliability reliable reliableness reliably reliance reliant reliantly relic relicense relicensed relicenses relicensing relicensure relics relict reliction relictions relicts relied relief reliefs relier reliers relies relievable relieve relieved relievedly reliever relievers relieves relieving relievo relievos relight relighted relighting relights religion religionism religionist religionists religionless religions religiose religiosity religious religiously religiousness reline relined relines relining relink relinked relinking relinks relinquish relinquished relinquisher relinquishers relinquishes relinquishing relinquishment relinquishments reliquaries reliquary reliquefied reliquefies reliquefy reliquefying reliquiae relish relishable relished relishes relishing relit relive relived relives reliving reload reloaded reloading reloads relocatable relocate relocated relocatee relocatees relocates relocating relocation relocations relock relocked relocking relocks relook relooked relooking relooks relubricate relubricated relubricates relubricating relubrication relubrications relucent reluct reluctance reluctancy reluctant reluctantly reluctate reluctated reluctates reluctating reluctation reluctations relucted relucting reluctivity relucts relume relumed relumes reluming rely relying rem remade remain remainder remaindered remaindering remainders remained remaining remains remake remaker remakers remakes remaking reman remand remanded remanding remandment remandments remands remanence remanent remanned remanning remans remanufacture remanufactured remanufacturer remanufacturers remanufactures remanufacturing remap remapped remapping remaps remark remarkable remarkableness remarkably remarked remarker remarkers remarket remarketed remarketing remarkets remarking remarks remarque remarques remarriage remarriages remarried remarries remarry remarrying remaster remastered remastering remasters rematch rematches remate remated rematerialize rematerialized rematerializes rematerializing remates remating rembrandt remeasure remeasured remeasurement remeasurements remeasures remeasuring remediability remediable remediableness remediably remedial remedially remediate remediated remediates remediating remediation remediations remedied remedies remediless remedy remedying remeet remeeting remeets remelt remelted remelting remelts remember rememberability rememberable remembered rememberer rememberers remembering remembers remembrance remembrancer remembrancers remembrances remerge remerged remerges remerging remet remex remiges remigial remigration remigrations remilitarization remilitarizations remilitarize remilitarized remilitarizes remilitarizing remind reminded reminder reminders remindful reminding reminds remington reminisce reminisced reminiscence reminiscences reminiscent reminiscential reminiscently reminiscer reminiscers reminisces reminiscing remint reminted reminting remints remise remised remises remising remiss remissibility remissible remissibly remission remissions remissly remissness remit remitment remitments remits remittable remittal remittals remittance remittances remitted remittence remittency remittent remittently remitter remitters remitting remix remixed remixes remixing remnant remnants remo remobilization remobilizations remobilize remobilized remobilizes remobilizing remodel remodeled remodeler remodelers remodeling remodelled remodelling remodels remodification remodifications remodified remodifies remodify remodifying remoisten remoistened remoistening remoistens remold remolded remolding remolds remonetization remonetizations remonetize remonetized remonetizes remonetizing remonstrance remonstrances remonstrant remonstrantly remonstrants remonstrate remonstrated remonstrates remonstrating remonstration remonstrations remonstrative remonstratively remonstrator remonstrators remora remoras remorse remorseful remorsefully remorsefulness remorseless remorselessly remorselessness remote remotely remoteness remoter remotes remotest remotion remotions remotivate remotivated remotivates remotivating remotivation remotivations remoulins remount remounted remounting remounts removability removable removableness removably removal removals remove removed removedly removedness remover removers removes removing rems remuda remudas remunerability remunerable remunerably remunerate remunerated remunerates remunerating remuneration remunerations remunerative remuneratively remunerativeness remunerator remunerators remuneratory remus remy remythologize remythologized remythologizes remythologizing renail renailed renailing renails renaissance renal rename renamed renames renaming renascence renascences renascent renationalization renationalizations renationalize renationalized renationalizes renationalizing renaturation renaturations renature renatured renatures renaturing rencontre rencontres rencounter rencountered rencountering rencounters rend rended render renderable rendered renderer renderers rendering renderings renders rendezvous rendezvoused rendezvousing rending rendition renditions rends rendzina rendzinas renegade renegaded renegades renegading renege reneged reneger renegers reneges reneging renegotiable renegotiate renegotiated renegotiates renegotiating renegotiation renegotiations renest renested renesting renests renew renewability renewable renewably renewal renewals renewed renewedly renewer renewers renewing renews reniform renin renins renitence renitency renitent renminbi rennet rennin renninogen renninogens reno renogram renograms renographic renography renoir renominate renominated renominates renominating renomination renominations renormalization renormalizations renormalize renormalized renormalizes renormalizing renounce renounced renouncement renouncements renouncer renouncers renounces renouncing renovascular renovate renovated renovates renovating renovation renovations renovative renovator renovators renown renowned rent rentability rentable rental rentals rented renter renters rentier rentiers renting rents renumber renumbered renumbering renumbers renunciation renunciations renunciative renunciatory reobserve reobserved reobserves reobserving reoccupation reoccupied reoccupies reoccupy reoccupying reoccur reoccurred reoccurrence reoccurrences reoccurring reoccurs reoffer reoffered reoffering reoffers reoil reoiled reoiling reoils reopen reopened reopening reopens reoperate reoperated reoperates reoperating reoperation reoperations reorchestrate reorchestrated reorchestrates reorchestrating reorchestration reorchestrations reorder reordered reordering reorders reorganization reorganizational reorganizations reorganize reorganized reorganizer reorganizers reorganizes reorganizing reorient reorientate reorientated reorientates reorientating reorientation reorientations reoriented reorienting reorients reoutfit reoutfits reoutfitted reoutfitting reovirus reoviruses reoxidation reoxidations reoxidize reoxidized reoxidizes reoxidizing rep repack repackage repackaged repackager repackagers repackages repackaging repacked repacking repacks repaginate repaginated repaginates repaginating repagination repaid repaint repainted repainting repaints repair repairability repairable repairably repaired repairer repairers repairing repairman repairmen repairperson repairpersons repairs repairwoman repairwomen repand reparability reparable reparably reparation reparations reparative reparatory repark reparked reparking reparks repartee repartees repartition repartitioned repartitioning repartitions repass repassage repassages repassed repasses repassing repast repasted repasting repasts repatch repatched repatches repatching repatriate repatriated repatriates repatriating repatriation repatriations repattern repatterned repatterning repatterns repave repaved repaves repaving repay repayable repaying repayment repayments repays repeal repealable repealed repealer repealers repealing repeals repeat repeatability repeatable repeated repeatedly repeater repeaters repeating repeats repechage repechages repeg repegged repegging repegs repel repellant repelled repellence repellency repellent repellently repellents repeller repellers repelling repels repent repentance repentant repentantly repented repenter repenters repenting repents repeople repeopled repeoples repeopling repercussion repercussions repercussive repertoire repertoires repertorial repertories repertory repetend repetends repetition repetitional repetitions repetitious repetitiously repetitiousness repetitive repetitively repetitiveness rephotograph rephotographed rephotographing rephotographs rephrase rephrased rephrases rephrasing repine repined repiner repiners repines repining replace replaceable replaced replacement replacements replacer replacers replaces replacing replan replanned replanning replans replant replantation replantations replanted replanting replants replaster replastered replastering replasters replate replated replates replating replay replayed replaying replays repleader repleaders repledge repledged repledges repledging replenish replenishable replenished replenisher replenishers replenishes replenishing replenishment replenishments replete repleteness repletion repleviable replevied replevies replevin replevined replevines replevining replevins replevy replevying replica replicability replicable replicas replicase replicases replicate replicated replicates replicating replication replications replicative replicon replicons replied replier repliers replies replot replots replotted replotting replumb replumbed replumbing replumbs reply replying repo repolarization repolarizations repolarize repolarized repolarizes repolarizing repolish repolished repolishes repolishing repoll repolled repolling repolls repopularize repopularized repopularizes repopularizing repopulate repopulated repopulates repopulating repopulation report reportable reportage reported reportedly reporter reporters reporting reportorial reportorially reports repos reposal reposals repose reposed reposeful reposefully reposefulness reposer reposers reposes reposing reposit reposited repositing reposition repositioned repositioning repositions repositories repository reposits repossess repossessed repossesses repossessing repossession repossessions repossessor repossessors repot repots repotted repotting repoussé repower repowered repowering repowers repp repps reprehend reprehended reprehending reprehends reprehensibility reprehensible reprehensibleness reprehensibly reprehension reprehensions reprehensive represent representability representable representation representational representationalism representationalist representationalists representationally representations representative representatively representativeness representatives representativity represented representer representers representing represents repress repressed represser repressers represses repressibility repressible repressing repression repressionist repressionists repressions repressive repressively repressiveness repressor repressors repressurize repressurized repressurizes repressurizing reprice repriced reprices repricing reprievable reprieval reprievals reprieve reprieved reprieves reprieving reprimand reprimanded reprimanding reprimands reprint reprinted reprinter reprinters reprinting reprints reprisal reprisals reprise reprised reprises reprising repristinate repristinated repristinates repristinating repristination repristinations reprivatization reprivatizations reprivatize reprivatized reprivatizes reprivatizing repro reproach reproachable reproachableness reproachably reproached reproacher reproachers reproaches reproachful reproachfully reproachfulness reproaching reproachingly reprobance reprobances reprobate reprobated reprobates reprobating reprobation reprobations reprobative reprobatory reprocess reprocessed reprocesses reprocessing reproduce reproduced reproducer reproducers reproduces reproducibility reproducible reproducibly reproducing reproduction reproductions reproductive reproductively reproductiveness reproductives reprogram reprogramed reprograming reprogrammability reprogrammable reprogrammed reprogramming reprograms reprographer reprographers reprographic reprographics reprography reproof reproofing reproofs repros reprovable reprove reproved reprover reprovers reproves reproving reprovingly reprovision reprovisioned reprovisioning reprovisions reps reptant reptile reptilelike reptiles reptilia reptilian reptilians reptilium republic republican republicanism republicanization republicanizations republicanize republicanized republicanizes republicanizing republicans republication republications republics republish republished republisher republishers republishes republishing repudiate repudiated repudiates repudiating repudiation repudiationist repudiationists repudiations repudiative repudiator repudiators repugn repugnance repugnancies repugnancy repugnant repugnantly repugned repugning repugns repulse repulsed repulser repulsers repulses repulsing repulsion repulsions repulsive repulsively repulsiveness repump repumped repumping repumps repunctuation repurchase repurchased repurchases repurchasing repurified repurifies repurify repurifying reputability reputable reputably reputation reputational reputations repute reputed reputedly reputes reputing request requested requester requesters requesting requestor requestors requests requiem requiems requiescat requiescats requirable require required requirement requirements requirer requirers requires requiring requisite requisitely requisiteness requisites requisition requisitioned requisitioning requisitions requitable requital requitals requite requited requiter requiters requites requiting rerack reracked reracking reracks reradiate reradiated reradiates reradiating reradiation reradiations reraise reraised reraises reraising reran reread rereading rereadings rereads rerecord rerecorded rerecording rerecords reredos reredoses reregister reregistered reregistering reregisters reregistration reregistrations reregulate reregulated reregulates reregulating reregulation rerelease rereleased rereleases rereleasing reremind rereminded rereminding rereminds rerepeat rerepeated rerepeating rerepeats rereview rereviewed rereviewing rereviews rereward rerewards rerig rerigged rerigging rerigs reroof reroofed reroofing reroofs reroute rerouted reroutes rerouting rerun rerunning reruns res resail resailed resailing resails resalable resale resales resample resampled resamples resampling resat resaw resawed resawing resawn resaws rescale rescaled rescales rescaling rescan rescanned rescanning rescans reschedule rescheduled reschedules rescheduling reschool reschooled reschooling reschools rescind rescindable rescinded rescinder rescinders rescinding rescindment rescindments rescinds rescission rescissions rescissory rescore rescored rescores rescoring rescreen rescreened rescreening rescreens rescript rescripts rescuable rescue rescued rescuer rescuers rescues rescuing resculpt resculpted resculpting resculpts reseal resealable resealed resealing reseals research researchable researched researcher researchers researches researching researchist researchists reseason reseasoned reseasoning reseasons reseat reseated reseating reseats reseau resect resectability resectable resected resecting resection resections resectoscope resectoscopes resects resecure resecured resecures resecuring reseda resedas resee reseed reseeded reseeding reseeds reseeing reseen resees resegregate resegregated resegregates resegregating resegregation resegregations reselect reselected reselecting reselection reselections reselects resell reseller resellers reselling resells resemblance resemblances resemblant resemble resembled resembler resemblers resembles resembling resend resending resends resensitize resensitized resensitizes resensitizing resent resented resentence resentenced resentences resentencing resentful resentfully resentfulness resenting resentment resentments resents reserpine reserpines reservable reservation reservationist reservationists reservations reserve reserved reservedly reservedness reserver reservers reserves reservice reserviced reservices reservicing reserving reservist reservists reservoir reservoirs reset resets resettable resetter resetters resetting resettle resettled resettlement resettlements resettles resettling resew resewed resewing resewn resews resh reshape reshaped reshaper reshapers reshapes reshaping reshes reshingle reshingled reshingles reshingling reship reshipment reshipments reshipped reshipping reships reshod reshoe reshoed reshoeing reshoes reshoot reshooting reshoots reshot reshow reshowed reshowing reshown reshows reshuffle reshuffled reshuffles reshuffling resid reside resided residence residences residencies residency resident residential residentially residentiaries residentiary residents resider residers resides residing resids residua residual residually residuals residuary residue residues residuum resift resifted resifting resifts resight resighted resighting resights resign resignation resignations resigned resignedly resignedness resigner resigners resigning resigns resile resiled resiles resilience resiliency resilient resiliently resilin resiling resilins resilver resilvered resilvering resilvers resin resinate resinated resinates resinating resined resines resiniferous resining resinoid resinoids resinous resins resist resistance resistances resistant resisted resister resisters resistibility resistible resistibly resisting resistive resistively resistiveness resistivities resistivity resistless resistlessly resistlessness resistor resistors resists resit resite resited resites resiting resits resitting resittings resituate resituated resituates resituating resize resized resizes resizing reslate reslated reslates reslating resoak resoaked resoaking resoaks resocialization resocialize resocialized resocializes resocializing resod resodded resodding resods resold resolder resoldered resoldering resolders resole resoled resoles resolidification resolidified resolidifies resolidify resolidifying resoling resolubility resoluble resolubleness resolute resolutely resoluteness resolution resolutions resolvability resolvable resolvableness resolve resolved resolvedly resolvent resolvents resolver resolvers resolves resolving resonance resonances resonant resonantly resonate resonated resonates resonating resonation resonations resonator resonators resorb resorbed resorbing resorbs resorcin resorcinol resorcinols resorcins resorption resorptions resorptive resort resorted resorter resorters resorting resorts resound resounded resounding resoundingly resounds resource resourceful resourcefully resourcefulness resources resow resowed resowing resown resows respect respectability respectable respectableness respectably respected respecter respecters respectful respectfully respectfulness respecting respective respectively respectiveness respects respell respelled respelling respells respelt respirability respirable respiration respirational respirations respirator respirators respiratory respire respired respires respiring respiritualize respiritualized respiritualizes respiritualizing respirometer respirometers respirometric respirometry respite respited respites respiting resplendence resplendency resplendent resplendently respond responded respondence respondency respondent respondents responder responders responding responds responsa response responses responsibilities responsibility responsible responsibleness responsibly responsions responsive responsively responsiveness responsorial responsories responsory responsum respot respots respotted respotting respray resprayed respraying resprays respring respringing resprings resprout resprouted resprouting resprouts resprung ressentiment ressentiments rest restabilize restabilized restabilizes restabilizing restack restacked restacking restacks restage restaged restages restaging restamp restamped restamping restamps restante restart restartable restarted restarting restarts restate restated restatement restatements restates restating restaurant restauranteur restauranteurs restaurants restaurateur restaurateurs rested rester resters restful restfully restfulness restharrow restharrows restick resticking resticks restiform restimulate restimulated restimulates restimulating restimulation resting restitute restituted restitutes restituting restitution restitutions restive restively restiveness restless restlessly restlessness restock restocked restocking restocks restoke restoked restokes restoking restorability restorable restoral restorals restoration restorations restorative restoratively restorativeness restoratives restore restored restorer restorers restores restoring restrain restrainable restrained restrainedly restrainer restrainers restraining restrains restraint restraints restrengthen restrengthened restrengthening restrengthens restress restressed restresses restressing restrict restricted restrictedly restricter restricters restricting restriction restrictionism restrictionist restrictionists restrictions restrictive restrictively restrictiveness restrictor restrictors restricts restrike restrikes restriking restring restringing restrings restroom restrooms restruck restructure restructured restructures restructuring restrung rests restuck restudied restudies restudy restudying restuff restuffed restuffing restuffs restyle restyled restyles restyling resublime resublimed resublimes resubliming resubmission resubmissions resubmit resubmits resubmitted resubmitting result resultant resultantly resultants resulted resultful resultfulness resulting resultless results resumable resume resumed resumer resumers resumes resuming resummon resummoned resummoning resummons resumption resumptions resumé resumés resupinate resupination resupinations resupine resupplied resupplies resupply resupplying resurface resurfaced resurfacer resurfacers resurfaces resurfacing resurge resurged resurgence resurgent resurgently resurges resurging resurrect resurrected resurrecting resurrection resurrectional resurrectionist resurrectionists resurrections resurrector resurrectors resurrects resurvey resurveyed resurveying resurveys resuscitable resuscitate resuscitated resuscitates resuscitating resuscitation resuscitations resuscitative resuscitator resuscitators resveratrol resynchronization resynchronize resyntheses resynthesis resynthesize resynthesized resynthesizes resynthesizing resystematize resystematized resystematizes resystematizing ret retable retables retackle retackled retackles retackling retag retagged retagging retags retail retailed retailer retailers retailing retails retain retainability retainable retained retainer retainers retaining retainment retainments retains retake retaken retakes retaking retaliate retaliated retaliates retaliating retaliation retaliations retaliative retaliator retaliators retaliatory retard retardant retardants retardate retardates retardation retardations retarded retarder retarders retarding retards retarget retargeted retargeting retargets retaste retasted retastes retasting retaught retch retched retches retching rete reteach reteaches reteaching reteam reteamed reteaming reteams retell retelling retellings retells retene retenes retention retentions retentive retentively retentiveness retentivity retest retested retesting retests retexture retextured retextures retexturing rethink rethinker rethinkers rethinking rethinks rethought rethread rethreaded rethreading rethreads retia retiary reticence reticencies reticency reticent reticently reticle reticles reticula reticular reticulate reticulated reticulately reticulates reticulating reticulation reticulations reticule reticules reticulocyte reticulocytes reticulocytic reticuloendothelial reticulum retie retied reties retiform retighten retightened retightening retightens retile retiled retiles retiling retime retimed retimes retiming retina retinacula retinacular retinaculum retinae retinal retinas retinene retinenes retinitis retinoblastoma retinoblastomas retinoblastomata retinoic retinoid retinoids retinol retinols retinopathic retinopathies retinopathy retinoscope retinoscopes retinoscopic retinoscopies retinoscopy retinotectal retinue retinues retinula retinulae retinular retirant retirants retire retired retiredly retiredness retiree retirees retirement retirements retires retiring retiringly retiringness retold retook retool retooled retooling retools retorsion retorsions retort retorted retorter retorters retorting retortion retortions retorts retouch retouched retoucher retouchers retouches retouching retrace retraceable retraced retracement retracements retracer retracers retraces retracing retract retractability retractable retractation retractations retracted retractibility retractible retractile retractility retracting retraction retractions retractive retractively retractiveness retractor retractors retracts retrain retrainable retrained retrainee retrainees retraining retrains retral retrally retransfer retransferred retransferring retransfers retransform retransformation retransformations retransformed retransforming retransforms retranslate retranslated retranslates retranslating retranslation retranslations retransmission retransmissions retransmit retransmits retransmitted retransmitting retread retreaded retreading retreads retreat retreatant retreatants retreated retreater retreaters retreating retreats retrench retrenched retrencher retrenchers retrenches retrenching retrenchment retrenchments retrial retrials retribution retributions retributive retributively retributory retried retries retrievability retrievable retrievably retrieval retrievals retrieve retrieved retriever retrievers retrieves retrieving retro retroact retroacted retroacting retroaction retroactions retroactive retroactively retroactivity retroacts retrocede retroceded retrocedes retroceding retrocession retrocessions retrodict retrodicted retrodicting retrodiction retrodictions retrodictive retrodicts retrofire retrofired retrofires retrofiring retrofit retrofits retrofittable retrofitted retrofitter retrofitters retrofitting retroflection retroflections retroflex retroflexed retroflexes retroflexion retroflexions retrogradation retrogradations retrograde retrograded retrogradely retrogrades retrograding retrogress retrogressed retrogresses retrogressing retrogression retrogressions retrogressive retrogressively retrolental retroocular retropack retropacks retroperitoneal retroperitoneally retropharyngeal retroreflection retroreflections retroreflective retroreflector retroreflectors retrorocket retrorockets retrorse retrorsely retros retrospect retrospected retrospecting retrospection retrospections retrospective retrospectively retrospectives retrospects retroussé retroversion retroversions retroviral retrovirus retroviruses retry retrying rets retsina retted retting retune retuned retunes retuning return returnable returnables returned returnee returnees returner returners returning returns retuse retying retype retyped retypes retyping reuben reunification reunifications reunified reunifies reunify reunifying reunion reunionism reunionist reunionistic reunionists reunions reunite reunited reunites reuniting reupholster reupholstered reupholstering reupholsters reusability reusable reuse reused reuses reusing reuter reutilization reutilize reutilized reutilizes reutilizing rev revaccinate revaccinated revaccinates revaccinating revaccination revaccinations revalidate revalidated revalidates revalidating revalidation revalidations revalorization revalorizations revalorize revalorized revalorizes revalorizing revaluate revaluated revaluates revaluating revaluation revaluations revalue revalued revalues revaluing revamp revamped revamping revampment revampments revamps revanche revanches revanchism revanchist revanchistic revanchists revascularization revascularizations reveal revealable revealed revealer revealers revealing revealingly revealment revealments reveals revegetate revegetated revegetates revegetating revegetation revegetations reveille reveilles revel revelation revelations revelator revelators revelatory reveled reveler revelers reveling revelled reveller revellers revelling revelries revelrous revelry revels revenant revenants revenge revenged revengeful revengefully revengefulness revenger revengers revenges revenging revenue revenuer revenuers revenues reverb reverbed reverberant reverberantly reverberate reverberated reverberates reverberating reverberation reverberations reverberative reverberatively reverberator reverberatories reverberators reverberatory reverbing reverbs revere revered reverence reverenced reverencer reverencers reverences reverencing reverend reverends reverent reverential reverentially reverently reveres reverie reveries reverification revering revers reversal reversals reverse reversed reversely reverser reversers reverses reversibility reversible reversibleness reversibles reversibly reversing reversion reversional reversionary reversioner reversioners reversions revert revertant revertants reverted reverter reverters revertible reverting revertive reverts revery revest revested revesting revests revet revetment revetments revets revetted revetting revictual revictualed revictualing revictuals review reviewable reviewed reviewer reviewers reviewing reviews revile reviled revilement revilements reviler revilers reviles reviling revilingly revillagigedo revisable revisal revisals revise revised reviser revisers revises revising revision revisionary revisionism revisionist revisionists revisions revisit revisitation revisitations revisited revisiting revisits revisor revisors revisory revisualization revisualizations revitalization revitalizations revitalize revitalized revitalizes revitalizing revivable revival revivalism revivalist revivalistic revivalists revivals revive revived reviver revivers revives revivification revivifications revivified revivifies revivify revivifying reviving reviviscence reviviscent revocability revocable revocation revocations revocatory revoir revoirs revokable revoke revoked revoker revokers revokes revoking revolt revolted revolter revolters revolting revoltingly revolts revolute revolution revolutionaries revolutionarily revolutionariness revolutionary revolutionist revolutionists revolutionize revolutionized revolutionizer revolutionizers revolutionizes revolutionizing revolutions revolvable revolve revolved revolver revolvers revolves revolving revote revoted revotes revoting revs revue revues revulsed revulsion revulsive revved revving rewake rewaked rewaken rewakened rewakening rewakens rewakes rewaking reward rewardable rewarded rewarder rewarders rewarding rewardingly rewards rewarm rewarmed rewarming rewarms rewash rewashed rewashes rewashing reweave reweaves reweaving reweigh reweighed reweighing reweighs rewet rewets rewetted rewetting rewind rewinder rewinders rewinding rewinds rewire rewired rewires rewiring rewoke rewoken reword reworded rewording rewordings rewords rework reworked reworking reworks rewound rewove rewoven rewrap rewrapped rewrapping rewraps rewrite rewriter rewriters rewrites rewriting rewritten rewrote rex rexes reye reykjavik reykjavík reynard reynards reynolds rezone rezoned rezones rezoning rhabdocoele rhabdocoeles rhabdom rhabdomancer rhabdomancers rhabdomancy rhabdome rhabdomere rhabdomeres rhabdomes rhabdoms rhabdomyoma rhabdomyomas rhabdomyomata rhabdomyosarcoma rhabdomyosarcomas rhabdomyosarcomata rhabdovirus rhabdoviruses rhadamanthine rhadamanthus rhadamanthys rhaetia rhaetian rhaetians rhamnose rhamnoses rhaphe rhapsode rhapsodes rhapsodic rhapsodical rhapsodically rhapsodies rhapsodist rhapsodists rhapsodize rhapsodized rhapsodizes rhapsodizing rhapsody rhatanies rhatany rhea rheas rhebok rheboks rhenish rhenishes rhenium rheological rheologically rheologist rheologists rheology rheometer rheometers rheostat rheostatic rheostats rheotactic rheotaxis rheotaxises rhesus rhesuses rhetor rhetoric rhetorical rhetorically rhetorician rhetoricians rhetors rheum rheumatic rheumatically rheumatics rheumatism rheumatoid rheumatoidal rheumatoidally rheumatologist rheumatologists rheumatology rheumy rhinal rhine rhineland rhinencephala rhinencephalic rhinencephalon rhinestone rhinestoned rhinestones rhinitis rhino rhinoceros rhinoceroses rhinologist rhinologists rhinology rhinopharyngitis rhinoplastic rhinoplasties rhinoplasty rhinos rhinoscopies rhinoscopy rhinovirus rhinoviruses rhizanthous rhizobia rhizobial rhizobium rhizocephalan rhizocephalans rhizocephalous rhizoctonia rhizoctonias rhizogenetic rhizogenic rhizoid rhizoidal rhizoids rhizomatous rhizome rhizomes rhizomic rhizophagous rhizoplane rhizoplanes rhizopod rhizopodan rhizopodans rhizopodous rhizopods rhizopus rhizopuses rhizosphere rhizospheres rhizotomies rhizotomy rho rhodamine rhodamines rhode rhodes rhodesia rhodesian rhodesians rhodium rhodochrosite rhodochrosites rhododendron rhododendrons rhodolite rhodolites rhodomontade rhodomontaded rhodomontades rhodomontading rhodonite rhodonites rhodope rhodopsin rhodopsins rhodora rhodoras rhomb rhombencephalic rhombencephalon rhombencephalons rhombi rhombic rhombohedra rhombohedral rhombohedron rhombohedrons rhomboid rhomboidal rhomboidei rhomboideus rhomboids rhombs rhombus rhombuses rhonchal rhonchi rhonchial rhonchus rhone rhos rhubarb rhubarbs rhumb rhumba rhumbaed rhumbaing rhumbas rhumbs rhus rhuses rhyme rhymed rhymeless rhymer rhymers rhymes rhymester rhymesters rhyming rhynchocephalian rhynchocephalians rhyolite rhyolites rhyolitic rhythm rhythmic rhythmical rhythmically rhythmicity rhythmics rhythmist rhythmists rhythmization rhythmizations rhythmize rhythmized rhythmizes rhythmizing rhythms rhytidectomies rhytidectomy rhytidome rhytidomes rhyton rhytons rhône rial rials rialto rialtos riant riantly riata riatas rib ribald ribaldries ribaldry ribalds riband ribands ribavirin ribavirins ribband ribbands ribbed ribbentrop ribber ribbers ribbing ribbings ribbon ribboned ribbonfish ribbonfishes ribboning ribbonlike ribbons ribbony ribby ribcage ribcages ribes ribgrass ribgrasses riblet riblets riboflavin ribonuclease ribonucleases ribonucleic ribonucleoprotein ribonucleoproteins ribonucleoside ribonucleosides ribonucleotide ribonucleotides ribose ribosomal ribosome ribosomes ribozymes ribs ribwort ribworts rica rican ricans riccio riccocheted riccocheting riccochets rice ricebird ricebirds riced ricer ricercar ricercare ricercari ricercars ricers rices rich richard riche richelieu richen richened richening richens richer riches richest richfield richly richmond richness richter richweed richweeds ricin ricing ricinoleic ricins rick ricked ricketier ricketiest ricketiness rickets rickettsia rickettsiae rickettsial rickettsioses rickettsiosis rickety rickey rickeys ricking rickrack ricks ricksha rickshas rickshaw rickshaws rico ricochet ricocheted ricocheting ricochets ricotta ricottas ricrac rictal rictus rictuses rid ridable riddance ridded ridden ridder ridders ridding riddle riddled riddler riddlers riddles riddling ride rideable rider riderless riders ridership riderships rides ridesharing ridesharings ridge ridgeback ridgebacks ridged ridgeline ridgelines ridgeling ridgelings ridgepole ridgepoles ridges ridgier ridgiest ridging ridgling ridglings ridgy ridicule ridiculed ridiculer ridiculers ridicules ridiculing ridiculous ridiculously ridiculousness riding ridings ridley ridleys ridotto ridottos rids riel riels riemann riemannian riesling rieslings rifampicin rifampicins rifampin rifampins rifamycin rifamycins rife rifely rifer rifest riff riffed riffian riffians riffing riffle riffled riffler rifflers riffles riffling riffraff riffs rifle riflebird riflebirds rifled rifleman riflemen rifler riflers riflery rifles riflescope riflescopes rifling rift rifted rifting rifts rig rigadoon rigadoons rigamarole rigamaroles rigatoni rigaudon rigaudons rigel rigged rigger riggers rigging riggings right righted righteous righteously righteousness righter righters rightest rightful rightfully rightfulness righties righting rightish rightism rightist rightists rightly rightmost rightness righto rights rightward rightwards righty rigid rigidification rigidifications rigidified rigidifies rigidify rigidifying rigidities rigidity rigidly rigidness rigmarole rigmaroles rigor rigorism rigorist rigoristic rigorists rigorous rigorously rigorousness rigors rigs rigueur rijstafel rijstafels rijstaffel rijstaffels rijsttafel rijsttaffel rijsttaffels riksmaal riksmal rile riled riles riley riling rill rille rilles rillet rillets rillettes rills rim rima rimbaud rime rimed rimer rimers rimes rimester rimesters rimfire rimier rimiest riming rimini rimland rimlands rimless rimmed rimming rimose rimosely rimosity rimple rimpled rimples rimpling rimrock rims rimsky rimy rind rinded rinderpest rinderpests rinds rinforzando ring ringbark ringbarked ringbarking ringbarks ringbolt ringbolts ringbone ringbones ringdove ringdoves ringed ringent ringer ringers ringgit ringgits ringhals ringhalses ringing ringingly ringleader ringleaders ringlet ringleted ringlets ringlike ringmaster ringmasters ringneck ringnecks rings ringside ringsider ringsiders ringsides ringstraked ringtail ringtails ringtaw ringtoss ringworm ringworms rink rinks rinky rinsable rinse rinsed rinser rinsers rinses rinsible rinsing rio rioja riot rioted rioter rioters rioting riotous riotously riotousness riots rip riparian ripcord ripcords ripe ripely ripen ripened ripener ripeners ripeness ripening ripens riper ripest ripieni ripieno ripienos riposte riposted ripostes riposting ripped ripper rippers ripping ripple rippled ripplegrass ripplegrasses rippler ripplers ripples ripplet ripplets ripplier rippliest rippling ripplingly ripply riprap riprapped riprapping ripraps rips ripsaw ripsaws ripsnorter ripsnorters ripsnorting ripstop riptide riptides ripuarian ripuarians rise risen riser risers rises risibilities risibility risible risibles risibly rising risings risk risked risker riskers riskier riskiest riskiness risking riskless risks risky risorgimento risotto risottos risqué rissole rissoles rissolé ritalin ritard ritardando ritards rite rites ritornelli ritornello ritornellos ritter ritual ritualism ritualist ritualistic ritualistically ritualists rituality ritualization ritualizations ritualize ritualized ritualizes ritualizing ritually rituals ritz ritzier ritziest ritziness ritzy rivage rivages rival rivaled rivaling rivalled rivalling rivalries rivalrous rivalry rivals rive rived riven river riverbank riverbanks riverbed riverbeds riverboat riverboats riverfront riverfronts riverhead riverheads riverine riverines rivers riverside riversides riverward riverwards riverweed riverweeds rives rivet riveted riveter riveters riveting rivetingly rivets riviera riving rivière rivulet rivulets riyadh riyal rizzio rna rns roach roached roaches roaching road roadability roadbed roadbeds roadblock roadblocks roadholding roadhouse roadhouses roadie roadies roadkill roadkills roadless roadrunner roadrunners roads roadside roadsides roadstead roadsteads roadster roadsters roadway roadways roadwork roadworthier roadworthiest roadworthiness roadworthy roady roam roamed roamer roamers roaming roams roan roanoke roans roar roared roarer roarers roaring roaringly roars roast roasted roaster roasters roasting roasts rob robalo robalos roband robands robbed robber robberies robbers robbery robbing robe robed robert robertson robes robespierre robin robing robins robinson roble robles roborant roborants robot robotic robotically roboticize roboticized roboticizes roboticizing robotics robotism robotistic robotization robotizations robotize robotized robotizes robotizing robots robs robust robusta robustious robustiously robustiousness robustly robustness roc rocaille rocambole rocamboles roche rochefoucauld rochelle roches rochester rochet rochets rock rock'n'roll rockabilly rockaby rockabye rockaway rockaways rockbound rocked rockefeller rocker rockeries rockers rockery rocket rocketed rocketeer rocketeers rocketing rocketry rockets rocketsonde rocketsondes rockfall rockfalls rockfish rockfishes rockhopper rockhoppers rockhounding rockier rockies rockiest rockiness rocking rockingly rocklike rockling rocklings rockoon rockoons rockrose rockroses rocks rockshaft rockshafts rockslide rockslides rockweed rockweeds rockwork rocky rococo rocs rod rodded rodding rode rodent rodenticide rodenticides rodents rodeo rodeos rodes rodin rodless rodlike rodman rodmen rodomontade rodomontaded rodomontades rodomontading rods roe roebuck roebucks roentgen roentgenize roentgenized roentgenizes roentgenizing roentgenogram roentgenograms roentgenograph roentgenographic roentgenographically roentgenographs roentgenography roentgenologic roentgenological roentgenologically roentgenologist roentgenologists roentgenology roentgenoscope roentgenoscopes roentgenoscopic roentgenoscopy roentgenotherapies roentgenotherapy roentgens roes rogation rogations rogatory roger roget rogue rogued rogueing rogueries roguery rogues roguing roguish roguishly roguishness roil roiled roilier roiliest roiling roils roily roister roistered roisterer roisterers roistering roisterous roisterously roisters rolamite rolamites roland role roles rolf rolfed rolfer rolfers rolfing rolfs roll rollaway rollback rollbacks rolle rolled roller rollers rollick rollicked rollicking rollickingly rollicks rollicksome rollicky rolling rollmops rollout rollouts rollover rollovers rolls rolltop rollway rollways rolodex roly roma romagna romaic romaine roman romance romanced romancer romancers romances romancing romanesque romania romanian romanians romanic romanics romanies romanism romanist romanistic romanists romanization romanizations romanize romanized romanizes romanizing romano romanoff romanoffs romanov romanovs romans romansch romansh romantic romantically romanticism romanticist romanticists romanticization romanticizations romanticize romanticized romanticizes romanticizing romantics romany romaunt romaunts romblon rome romeldale romeldales romeo romeos romish romishly romishness rommel romney romp romped romper rompers romping romps roms romulus roncevaux rondeau rondeaux rondel rondelet rondelets rondelle rondelles rondels rondo rondos rondure rondures ronnel ronnels ronyon ronyons rood roods roof roofed roofer roofers roofing roofless rooflike roofline rooflines roofs rooftop rooftops rooftree rooftrees rook rooked rookeries rookery rookie rookies rooking rooks rooky room roomed roomer roomers roomette roomettes roomful roomfuls roomier roomiest roomily roominess rooming roommate roommates rooms roomy roorback roorbacks roosevelt roost roosted rooster roosterfish roosterfishes roosters roosting roosts root rootage rootages rooted rootedness rooter rooters roothold rootholds rootier rootiest rootiness rooting rootless rootlessness rootlet rootlets rootlike roots rootstalk rootstalks rootstock rootstocks rootworm rootworms rooty rope roped ropedancer ropedancers ropedancing ropelike roper ropers ropery ropes ropewalk ropewalker ropewalkers ropewalks ropeway ropeways ropey ropier ropiest ropily ropiness roping ropy roque roquefort roquelaure roquelaures roquet roqueted roqueting roquets roquette rorqual rorquals rorschach rosa rosacea rosaceous rosalind rosanilin rosaniline rosanilines rosanilins rosarian rosarians rosaries rosary roscius roscoe roscoes rose roseate roseately rosebay rosebays rosebud rosebuds rosebush rosebushes rosefish rosefishes roselle roselles rosemaries rosemary rosencrantz roseola roseolar roseolas roseroot roseroots roses rosetta rosette rosettes rosewater rosewood rosewoods rosh rosicrucian rosicrucianism rosicrucians rosier rosiest rosily rosin rosined rosiness rosining rosins rosinweed rosinweeds rosiny rossetti rossini rostella rostellar rostellate rostellum roster rosters rostock rostra rostral rostrally rostrate rostrum rostrums rosy rosé rosés rot rota rotameter rotameters rotarian rotarians rotaries rotary rotas rotatable rotate rotated rotates rotating rotation rotational rotationally rotations rotative rotatively rotator rotatores rotators rotatory rotavirus rotaviruses rote rotenone rotes rotgut rothschild rothschilds roti rotifer rotiferal rotiferous rotifers rotiform rotisserie rotisseries rotl rotls roto rotogravure rotogravures rotor rotorcraft rotorcrafts rotors rotos rototill rototilled rototiller rototillers rototilling rototills rots rotted rotten rottener rottenest rottenly rottenness rottenstone rottenstones rotter rotterdam rotters rotting rottweiler rottweilers rotund rotunda rotundas rotundity rotundly rotundness roturier roturiers rouble roubles rouen rouge rouged rouges rough roughage roughback roughbacks roughcast roughcaster roughcasters roughcasting roughcasts roughdried roughdries roughdry roughdrying roughed roughen roughened roughening roughens rougher roughers roughest roughhew roughhewed roughhewing roughhewn roughhews roughhouse roughhoused roughhouses roughhousing roughies roughing roughish roughleg roughlegs roughly roughneck roughnecks roughness roughrider roughriders roughs roughshod roughy rouging rouille roulade roulades rouleau rouleaus rouleaux roulette rouletted roulettes rouletting roumanian round roundabout roundaboutness roundabouts rounded roundedness roundel roundelay roundelays roundels rounder rounders roundest roundhead roundheaded roundheadedness roundheads roundhouse roundhouses rounding roundish roundishness roundlet roundlets roundly roundness roundoff rounds roundsman roundsmen roundtable roundtables roundtrip roundtrips roundup roundups roundwood roundworm roundworms roup roups rouse rouseabout rouseabouts roused rousement rousements rouser rousers rouses rousing rousingly rousseau rousseauism rousseauist rousseauistic rousseauists roussillon roust roustabout roustabouts rousted rouster rousters rousting rousts rout route routed routeman routemen router routers routes routeway routeways routine routinely routines routing routings routinism routinist routinists routinization routinizations routinize routinized routinizes routinizing routs roux roué roués rove roved rover rovers roves roving row rowan rowanberries rowanberry rowans rowboat rowboats rowdier rowdies rowdiest rowdily rowdiness rowdy rowdyish rowdyism rowed rowel roweled roweling rowels rowen rowens rower rowers rowing rowlandson rowlock rowlocks rows royal royalism royalist royalists royally royalmast royalmasts royals royalties royalty rpm rsvp ruana ruanas rub rubaiyat rubasse rubasses rubato rubatos rubbed rubber rubberier rubberiest rubberize rubberized rubberizes rubberizing rubberlike rubberneck rubbernecked rubbernecker rubberneckers rubbernecking rubbernecks rubbers rubberstamp rubberstamps rubbery rubbing rubbings rubbish rubbishing rubbishy rubble rubbled rubbles rubblework rubbling rubbly rubdown rubdowns rube rubefacient rubefacients rubefaction rubefactions rubella rubellite rubellites rubenesque rubens rubeola rubeolar rubes rubescence rubescent rubicon rubicund rubicundity rubidium rubies rubiginose rubiginous rubik rubious ruble rubles ruboff ruboffs rubout rubouts rubredoxin rubredoxins rubric rubrical rubrically rubricate rubricated rubricates rubricating rubrication rubrications rubricator rubricators rubrician rubricians rubrics rubs rubus ruby rubythroat rubythroats rubáiyát ruche ruched ruches ruching ruck rucked rucking rucks rucksack rucksacks ruckus ruckuses ruction ructions rudbeckia rudd rudder rudderfish rudderfishes rudderless rudderpost rudderposts rudders rudderstock rudderstocks ruddier ruddiest ruddily ruddiness ruddle ruddled ruddles ruddling ruddock ruddocks rudds ruddy rude rudely rudeness rudenesses ruder ruderal ruderals rudest rudiment rudimental rudimentarily rudimentariness rudimentary rudiments rudolf rue rued rueful ruefully ruefulness ruer ruers rues rufescence rufescent ruff ruffe ruffed ruffes ruffian ruffianism ruffianly ruffians ruffing ruffle ruffled ruffler rufflers ruffles ruffling ruffly ruffs rufiyaa rufiyaas rufous rufus rug ruga rugae rugate rugby rugged ruggedization ruggedizations ruggedize ruggedized ruggedizes ruggedizing ruggedly ruggedness rugola rugosa rugose rugosely rugosity rugous rugs rugulose ruin ruinable ruinate ruination ruinations ruined ruiner ruiners ruing ruining ruinous ruinously ruinousness ruins rulable rule ruled ruleless ruler rulers rulership rulerships rules rulier ruliest ruling rulings ruly rum rumaki rumakis rumania rumanian rumanians rumba rumbaed rumbaing rumbas rumble rumbled rumbler rumblers rumbles rumbling rumblingly rumblings rumbly rumbustious rumbustiously rumbustiousness rumen rumens rumina ruminal ruminant ruminantly ruminants ruminate ruminated ruminates ruminating rumination ruminations ruminative ruminatively ruminator ruminators rummage rummaged rummager rummagers rummages rummaging rummer rummers rummest rummier rummies rummiest rummy rumor rumored rumoring rumormonger rumormongered rumormongering rumormongers rumors rump rumpelstiltskin rumple rumpled rumples rumplier rumpliest rumpling rumply rumps rumpus rumpuses rumrunner rumrunners rums run runabout runabouts runagate runagates runaround runarounds runaway runaways runback runbacks runcible runcinate rundle rundles rundlet rundlets rundown rundowns rune runes rung rungs runic runless runlet runlets runnable runnel runnels runner runners runnier runniest running runnings runny runnymede runoff runoffs runout runouts runover runovers runs runt runtime runtiness runtish runts runty runway runways runza runzas rupee rupees rupiah rupiahs rupicolous rupturable rupture ruptured ruptures rupturing rural ruralism ruralist ruralists ruralities rurality ruralization ruralizations ruralize ruralized ruralizes ruralizing rurally rurban ruritan ruritania ruritanian ruritans ruse ruses rush rushed rushee rushees rusher rushers rushes rushier rushiest rushing rushlight rushlights rushmore rushy rusine rusk ruskin ruskinian rusks russell russet russeting russets russetting russia russian russianization russianizations russianize russianized russianizes russianizing russianness russians russification russifications russified russifies russify russifying russki russkie russkies russkis russky russo russophile russophiles russophilia russophobe russophobes russophobia rust rustable rusted rustic rustical rustically rusticate rusticated rusticates rusticating rustication rustications rusticator rusticators rusticities rusticity rustics rustier rustiest rustily rustiness rusting rustle rustled rustler rustlers rustles rustless rustling rustlingly rustproof rustproofed rustproofing rustproofs rusts rusty rut rutabaga rutabagas ruth ruthenia ruthenian ruthenians ruthenic ruthenious ruthenium rutherford rutherfordium rutherfords ruthful ruthfully ruthfulness ruthless ruthlessly ruthlessness rutilant rutile rutiles ruts rutted ruttier ruttiest ruttiness rutting ruttish ruttishly ruttishness rutty ruwenzori rwanda rwandan rwandans rya ryas rye ryegrass ryegrasses ryes ryukyu râle râles réaumur réchauffé réclame régime régimes régisseur régisseurs rémoulade répondez réseau réseaus réseaux résistance résumé résumés réunion rôle rôles röntgen röntgens rügen s s'le s'n s'ns saanen saaremaa saarland saarlander saarlanders sabadilla sabadillas sabal sabals sabaoth sabayon sabayons sabbat sabbatarian sabbatarianism sabbatarians sabbath sabbaths sabbatic sabbatical sabbaticals sabbats sabellian sabellians saber sabered sabering sabermetrician sabermetricians sabermetrics sabers sabian sabians sabin sabine sabines sabins sable sablefish sablefishes sables sabot sabotage sabotaged sabotages sabotaging saboteur saboteurs sabots sabra sabras sabre sabred sabres sabring sabulose sabulosity sabulous sac sacahuista sacahuiste sacajawea sacaton sacatons saccade saccades saccadic saccate saccharase saccharases saccharate saccharates saccharic saccharide saccharides saccharification saccharifications saccharified saccharifies saccharify saccharifying saccharimeter saccharimeters saccharimetry saccharin saccharine saccharinely saccharinity saccharoid saccharoidal saccharometer saccharometers saccharomyces saccharomycete saccharomycetes saccharomycetic saccharomycetous saccharose saccharoses saccular sacculate sacculated sacculation sacculations saccule saccules sacculi sacculus sacerdotal sacerdotalism sacerdotalist sacerdotalists sacerdotally sachem sachemic sachems sacher sachet sacheted sachets sack sackbut sackbuts sackcloth sacked sacker sackers sackful sackfuls sacking sackings sacks saclike sacque sacques sacra sacral sacrament sacramental sacramentalism sacramentalist sacramentalists sacramentally sacramentals sacramentarian sacramentarianism sacramentarians sacramento sacraments sacraria sacrarium sacred sacredly sacredness sacrifice sacrificed sacrificer sacrificers sacrifices sacrificial sacrificially sacrificing sacrificingly sacrilege sacrileges sacrilegious sacrilegiously sacrilegiousness sacrilegist sacrilegists sacristan sacristans sacristies sacristy sacrococcygeal sacroiliac sacroiliacs sacrolumbar sacrosanct sacrosanctity sacrosciatic sacrum sacs sad sadden saddened saddening saddens sadder saddest saddhu saddhus saddle saddleback saddlebacks saddlebag saddlebags saddlebow saddlebows saddlebred saddlebreds saddlecloth saddlecloths saddled saddleless saddler saddleries saddlers saddlery saddles saddletree saddletrees saddling sadducean sadducee sadduceeism sadducees sadhe sadhes sadhu sadhus sadiron sadirons sadism sadist sadistic sadistically sadists sadly sadness sadnesses sadomasochism sadomasochist sadomasochistic sadomasochists safar safari safaris safe safecracker safecrackers safecracking safeguard safeguarded safeguarding safeguards safekeeping safelight safelights safely safeness safer safes safest safetied safeties safety safetying safetyman safetymen safflower safflowers saffron safranin safranine safranines safranins safrole safroles sag saga sagacious sagaciously sagaciousness sagacity sagamore sagamores sagas sage sagebrush sagebrushes sagely sageness sager sages sagest saggar saggars sagged sagger saggers sagging saggy sagitta sagittal sagittally sagittarian sagittarians sagittarius sagittate sago sagos sagrada sags saguaro saguaros sahaptian sahara saharan sahel sahelian sahib sahibs sahuaro sahuaros said saiga saigas saigon sail sailable sailboard sailboarded sailboarder sailboarders sailboarding sailboards sailboat sailboater sailboaters sailboating sailboats sailcloth sailed sailer sailers sailfish sailfishes sailing sailor sailorman sailormen sailors sailplane sailplaned sailplaner sailplaners sailplanes sailplaning sails saimin saimins sainfoin sainfoins saint saintdom sainted sainthood sainting saintlier saintliest saintlike saintliness saintly saints saintship saipan saipanese sais saith saithe saiva saivas saivism sake saker sakers sakes saki sakishima sakti saktism sal salaam salaamed salaaming salaams salability salable salableness salably salacious salaciously salaciousness salacity salad saladin salads salal salals salamanca salamander salamanders salamandrine salami salamis salariat salaried salaries salary salaryman salarymen salbutamol salbutamols salchow salchows sale saleable salem salep saleps saleratus salerno saleroom salerooms sales salesclerk salesclerks salesgirl salesgirls salesian salesians salesladies saleslady salesman salesmanship salesmen salespeople salesperson salespersons salesroom salesrooms saleswoman saleswomen salian salians salic salicin salicins salicylate salicylates salicylic salicylism salience saliences saliencies saliency salient salientian salientians saliently salientness salients saliferous salimeter salimeters salimetric salimetry salina salinas saline salinity salinization salinizations salinize salinized salinizes salinizing salinometer salinometers salinometric salinometry salique salisbury salish salishan saliva salivary salivate salivated salivates salivating salivation salivator salivators salk sallet sallets sallied sallies sallow sallowed sallower sallowest sallowing sallowish sallowly sallowness sallows sally sallying salmacis salmagundi salmagundis salmi salmis salmon salmonberries salmonberry salmonella salmonellae salmonellas salmonelloses salmonellosis salmonid salmonids salmonoid salmonoids salmons salol salols salome salometer salometers salon salonika salons saloon saloonkeeper saloonkeepers saloons saloop saloops salopian salopians salp salpa salpas salpiform salpiglossis salpingectomies salpingectomy salpinges salpingian salpingitis salpinx salps sals salsa salsas salsifies salsify salt saltarelli saltarello saltarellos saltation saltations saltatorial saltatory saltbox saltboxes saltbush saltbushes saltcellar saltcellars salted salter saltern salterns salters saltgrass saltier saltiest saltily saltimbocca saltimboccas saltine saltines saltiness salting saltire saltires saltish saltless saltlike saltness saltpeter salts saltshaker saltshakers saltwater saltworks saltwort salty salubrious salubriously salubriousness salubrity saluki salukis saluretic saluretics salutarily salutariness salutary salutation salutational salutations salutatorian salutatorians salutatories salutatory salute saluted saluter saluters salutes salutiferous saluting salvable salvador salvadoran salvadorans salvadorean salvadoreans salvadorian salvage salvageability salvageable salvaged salvager salvagers salvages salvaging salvarsan salvation salvational salvationism salvationist salvationists salve salved salver salverform salvers salves salvia salvias salvific salvifically salving salvo salvoes salvor salvors salvos salzburg samara samaras samaria samaritan samaritans samarium samarkand samarskite samarskites samba sambaed sambaing sambal sambar sambars sambas sambo sambuca sambucas sambur samburs same samekh sameness samian samians samiel samiels samisen samisens samite samites samizdat samlet samlets sammarinese sammarinesi samnite samnites samnium samoa samoan samoans samos samosa samosas samothrace samothráki samovar samovars samoyed samoyede samoyedes samoyedic samoyeds samp sampan sampans samphire samphires sample sampled sampler samplers samples sampling samplings samsara samson samsonian samsons samuel samurai samurais san san'a sana sanaa sanataria sanatarium sanatariums sanative sanatoria sanatorium sanatoriums sanbenito sanbenitos sancerre sancta sanctification sanctifications sanctified sanctifier sanctifiers sanctifies sanctify sanctifying sanctimonious sanctimoniously sanctimoniousness sanctimony sanction sanctionable sanctioned sanctioning sanctions sanctities sanctity sanctuaries sanctuary sanctum sanctums sanctus sanctuses sand sandal sandaled sandals sandalwood sandalwoods sandarac sandaracs sandbag sandbagged sandbagger sandbaggers sandbagging sandbags sandbank sandbanks sandbar sandbars sandblast sandblasted sandblaster sandblasters sandblasting sandblasts sandblindness sandbox sandboxes sandbur sandburs sanded sander sanderling sanderlings sanders sandfish sandfishes sandfly sandglass sandglasses sandgrouse sandhi sandhill sandhis sandhog sandhogs sandier sandiest sandiness sanding sandinista sandinistas sandlot sandlots sandlotter sandlotters sandman sandmen sandpainting sandpaper sandpapered sandpapering sandpapers sandpapery sandpile sandpiles sandpiper sandpipers sandpit sandpits sands sandshoe sandshoes sandsoap sandspur sandspurs sandstone sandstorm sandstorms sandwich sandwiched sandwiches sandwiching sandworm sandworms sandwort sandworts sandy sane sanely saneness saner sanest sanforized sang sangaree sangarees sangfroid sangreal sangria sangrias sanguicolous sanguinaria sanguinarias sanguinarily sanguinary sanguine sanguinely sanguineness sanguineous sanguinity sanguinolent sanhedrim sanhedrin sanicle sanicles sanidine sanidines sanies sanified sanifies sanify sanifying sanious sanitaire sanitaria sanitarian sanitarians sanitarily sanitarium sanitariums sanitary sanitate sanitated sanitates sanitating sanitation sanitization sanitizations sanitize sanitized sanitizer sanitizers sanitizes sanitizing sanitoria sanitorium sanitoriums sanity sank sankhya sannup sannups sannyasi sannyasin sannyasins sannyasis sanpaku sanpakus sans sansculotte sansculottes sansculottic sansculottish sansculottism sansei sanseis sanserif sanserifs sansevieria sansevierias sanskrit sanskritic sanskritist sanskritists santa santalol santalols santander santas santee santees santeria santiago santir santirs santo santolina santolinas santonica santonicas santonin santonins santorini santos santour santours sao sap sapajou sapajous saphar saphead sapheaded sapheads saphena saphenae saphenous sapid sapidity sapience sapiens sapient sapiently sapless saplessness sapling saplings sapodilla sapogenin sapogenins saponaceous saponaceousness saponated saponifiable saponification saponified saponifier saponifiers saponifies saponify saponifying saponin saponins saponite saponites sapor saporific saporous sapota sapotas sapote sapotes sappanwood sappanwoods sapped sapper sappers sapphic sapphics sapphire sapphires sapphirine sapphirines sapphism sappho sappier sappiest sappily sappiness sapping sappy sapraemia sapremia sapremic saprobe saprobes saprobial saprobic saprobically saprobiological saprobiologist saprobiologists saprobiology saprogenic saprogenicity saprogenous saprolite saprolites sapropel sapropelic sapropels saprophagous saprophyte saprophytes saprophytic saprophytically saprozoic saps sapsago sapsagos sapsucker sapsuckers sapwood saraband sarabande sarabandes sarabands saracen saracenic saracens saragossa sarah sarajevo saran sarape sarapes sarasvati saratoga sarawak sarcasm sarcasms sarcastic sarcastically sarcenet sarcenets sarcodinian sarcodinians sarcoid sarcoidoses sarcoidosis sarcoids sarcolactic sarcolemma sarcolemmal sarcolemmas sarcoma sarcomas sarcomata sarcomatoid sarcomatosis sarcomatous sarcomere sarcomeres sarcophagi sarcophagic sarcophagous sarcophagus sarcophaguses sarcoplasm sarcoplasmatic sarcoplasmic sarcoptic sarcosomal sarcosome sarcosomes sarcostyle sarcostyles sarcous sard sardanapalus sardar sardars sardine sardined sardines sardinia sardinian sardinians sardining sardius sardiuses sardonic sardonically sardonicism sardonyx sardonyxes sards saree sarema sargasso sargassos sargassum sargassums sarge sarges sargon sargonid sari sarin saris sark sarkese sarmatia sarmatian sarmatians sarmentose sarod sarode sarodes sarodist sarodists sarods sarong sarongs sarpedon sarracenia sarsaparilla sarsaparillas sarsenet sarsenets sartorial sartorially sartorii sartorius sartre sartrean sarum sarus sasanian sasanid sasanids sash sashay sashayed sashaying sashays sashed sashes sashimi sashimis sashing saskatchewan saskatoon saskatoons sasquatch sass sassabies sassaby sassafras sassanian sassanid sassanide sassed sasses sassier sassies sassiest sassily sassiness sassing sassoon sasswood sasswoods sassy sastruga sastrugas sat satan satang satangs satanic satanical satanically satanism satanist satanists satay satchel satcheled satchelful satchelfuls satchels sate sated sateen satellite satellites satem sates sati satiability satiable satiably satiate satiated satiates satiating satiation satiations satiety satin satinet satinets sating satinized satins satinwood satinwoods satiny satire satires satiric satirical satirically satirist satirists satirizable satirization satirize satirized satirizes satirizing satis satisfaction satisfactions satisfactorily satisfactoriness satisfactory satisfiability satisfiable satisfied satisfiedly satisfier satisfiers satisfies satisfy satisfying satisfyingly satori satrap satrapies satraps satrapy satsuma satsumas saturable saturant saturants saturate saturated saturates saturating saturation saturations saturator saturators saturday saturdays saturn saturnalia saturnalian saturnalianly saturnalias saturnian saturniid saturniids saturnine saturninely saturnism satyagraha satyr satyriasis satyric satyrical satyrid satyrids satyrs saté sauce sauceboat sauceboats saucebox sauceboxes sauced saucepan saucepans saucepot saucepots saucer saucerlike saucers sauces saucier sauciest saucily sauciness saucing saucy saudi saudis sauerbraten sauerkraut sauger saugers sauk sauks saul sault saults saumur sauna saunas saunter sauntered saunterer saunterers sauntering saunters saurel saurels saurian saurians sauries saurischian saurischians sauropod sauropodous sauropods saury sausage sausages sauterne sauternes sauté sautéed sautéing sautés sauvignon savable savage savaged savagely savageness savageries savagery savages savaging savagism savagisms savai'i savaii savanna savannah savannahs savannas savant savants savarin savarins savate save saveable saved saveloy saveloys saver savers saves savin savine savines saving savings savins savior saviors saviour saviours savoir savonarola savor savored savorer savorers savories savorily savoriness savoring savorless savorous savors savory savour savoured savouries savouring savours savoury savoy savoyard savoyards savvied savvier savvies savviest savvily savvy savvying saw sawbones sawboneses sawbuck sawbucks sawdust sawdusty sawed sawer sawers sawfish sawfishes sawflies sawfly sawhorse sawhorses sawing sawlike sawlog sawlogs sawmill sawmills sawn sawney sawneys saws sawtimber sawtimbers sawtooth sawyer sawyers sax saxatile saxe saxes saxhorn saxhorns saxicoline saxicolous saxifrage saxifrages saxitoxin saxitoxins saxon saxondom saxonies saxonism saxons saxony saxophone saxophones saxophonic saxophonist saxophonists saxtuba saxtubas say sayable sayer sayers sayest saying sayings sayonara says sayyid sazerac saëns saône scab scabbard scabbarded scabbarding scabbards scabbed scabbier scabbiest scabbily scabbiness scabbing scabble scabbled scabbles scabbling scabby scabies scabietic scabiosa scabiosas scabious scabiouses scabland scablands scabrous scabrously scabrousness scabs scad scads scaffold scaffolded scaffolding scaffoldings scaffolds scag scagliola scagliolas scalability scalable scalade scalades scalado scalados scalage scalages scalar scalare scalares scalariform scalariformly scalars scalawag scalawags scald scalded scalding scaldingly scalds scale scaled scaleless scalelike scalene scaleni scalenus scaler scalers scales scalier scaliest scaliness scaling scall scallion scallions scallop scalloped scalloper scallopers scalloping scallopini scallops scalls scallywag scallywags scalogram scalograms scaloppine scaloppini scalp scalped scalpel scalpels scalper scalpers scalping scalps scaly scam scammed scammer scammers scamming scammonies scammony scamp scamped scamper scampered scampering scampers scampi scamping scampish scamps scams scan scandal scandale scandalization scandalizations scandalize scandalized scandalizer scandalizers scandalizes scandalizing scandalmonger scandalmongering scandalmongers scandalous scandalously scandalousness scandals scandent scandia scandian scandians scandic scandinavia scandinavian scandinavians scandium scannable scanned scanner scanners scanning scans scansion scansions scansorial scant scanted scanter scantest scantier scanties scantiest scantily scantiness scanting scantling scantlings scantly scantness scants scanty scape scaped scapegoat scapegoated scapegoating scapegoatism scapegoats scapegrace scapegraces scapes scaphocephalic scaphocephaly scaphoid scaphoids scaphopod scaphopods scaping scapolite scapolites scapose scapula scapulae scapular scapulars scapulary scapulas scapuloclavicular scar scarab scarabaei scarabaeid scarabaeids scarabaeus scarabaeuses scaraboid scarabs scaramouch scaramouche scaramouches scarce scarcely scarceness scarcer scarcest scarcities scarcity scare scarecrow scarecrows scared scaredy scarehead scareheads scaremonger scaremongering scaremongers scarer scarers scares scarf scarfed scarfing scarfpin scarfpins scarfs scarfskin scarfskins scarier scariest scarification scarifications scarificator scarificators scarified scarifier scarifiers scarifies scarify scarifying scarifyingly scarily scariness scaring scariose scarious scarlatina scarlatinal scarlatinoid scarlatti scarless scarlet scarlets scarp scarped scarping scarps scarred scarring scarry scars scarum scarves scary scat scatback scatbacks scathe scathed scatheless scathes scathing scathingly scatologic scatological scatologies scatologist scatologists scatology scats scatted scatter scatteration scatterations scatterbrain scatterbrained scatterbrains scattered scatterer scatterers scattergood scattergoods scattergram scattergrams scattergun scatterguns scattering scatteringly scatterings scatters scattershot scattier scattiest scatting scatty scaup scaups scavenge scavenged scavenger scavengers scavenges scavenging scena scenario scenarios scenarist scenarists scenas scend scended scending scends scene sceneries scenery scenes sceneshifter sceneshifters scenic scenical scenically scenics scenographer scenographers scenographic scenography scent scented scenting scentless scents scepter sceptered sceptering scepters sceptic sceptical scepticism sceptics schadenfreude schadenfreudes scharnhorst schav schavs schedular schedule scheduled scheduler schedulers schedules scheduling scheelite scheelites schefflera scheffleras scheherazade schelde scheldt schema schemas schemata schematic schematically schematics schematism schematization schematizations schematize schematized schematizes schematizing scheme schemed schemer schemers schemes scheming scherzando scherzandos scherzi scherzo scherzos scheveningen schick schiff schiller schillers schilling schillings schindler schiphol schipperke schipperkes schism schismatic schismatical schismatically schismatics schismatize schismatized schismatizes schismatizing schisms schist schistocyte schistocytes schistocytoses schistocytosis schistorrhachis schistorrhachises schistose schistosity schistosomal schistosome schistosomes schistosomiases schistosomiasis schistosomula schistosomulum schistous schists schizier schiziest schizo schizoaffective schizocarp schizocarpic schizocarpous schizocarps schizogamy schizogenesis schizogenous schizogonic schizogonous schizogony schizoid schizoids schizont schizonts schizophrene schizophrenes schizophrenia schizophrenic schizophrenically schizophrenics schizophreniform schizophrenogenic schizopod schizopodous schizopods schizos schizothyme schizothymes schizothymia schizothymic schizothymics schizy schizzy schlemiel schlemiels schlep schlepp schlepped schlepper schleppers schlepping schlepps schleps schleswig schliemann schlieren schlieric schlimazel schlimazels schlock schlockmeister schlockmeisters schlocky schmaltz schmaltzier schmaltziest schmaltziness schmaltzy schmalz schmalzy schmear schmeer schmidt schmo schmoe schmoes schmoose schmoosed schmooses schmoosing schmooze schmoozed schmoozes schmoozing schmos schmuck schmucks schnapper schnappers schnapps schnauzer schnauzers schnitzel schnitzels schnook schnooks schnorrer schnorrers schnoz schnozes schnozzle schnozzles schoenberg schoenbergian scholar scholarliness scholarly scholars scholarship scholarships scholastic scholastically scholasticate scholasticates scholasticism scholastics scholia scholiast scholiastic scholiasts scholium scholiums school schoolbag schoolbags schoolbook schoolbooks schoolboy schoolboyish schoolboys schoolchild schoolchildren schooldays schooled schooler schoolers schoolfellow schoolfellows schoolgirl schoolgirls schoolhouse schoolhouses schooling schoolings schoolkid schoolkids schoolma'am schoolma'ams schoolman schoolmarm schoolmarmish schoolmarms schoolmaster schoolmasterish schoolmasterly schoolmasters schoolmate schoolmates schoolmen schoolmistress schoolmistresses schoolroom schoolrooms schools schoolteacher schoolteachers schooltime schooltimes schoolwork schoolyard schoolyards schooner schooners schopenhauer schopenhauerian schorl schorls schottische schottisches schouten schrod schrodinger schtick schticks schubert schumann schuss schussboomer schussboomers schussed schusses schussing schuylkill schwa schwann schwarmerei schwarzhorn schwarzschild schwarzwald schwas sciaenid sciaenoid sciaenoids sciatic sciatica science sciences scienter sciential scientific scientifically scientism scientist scientistic scientists scientize scientized scientizes scientizing scientology scilicet scilla scilly scimitar scimitars scincoid scincoids scintigram scintigrams scintigraph scintigraphic scintigraphically scintigraphs scintigraphy scintilla scintillant scintillantly scintillate scintillated scintillates scintillating scintillatingly scintillation scintillations scintillator scintillators scintillometer scintillometers scintiscan scintiscanner scintiscanners scintiscans sciolism sciolist sciolistic sciolists scion scions scipio scirocco sciroccos scirrhi scirrhoid scirrhous scirrhus scirrhuses scissile scission scissions scissor scissored scissoring scissors scissortail scissortails scissure scissures sciurid sciurids sciuroid sclaff sclaffed sclaffer sclaffers sclaffing sclaffs sclera scleral sclereid sclereids sclerenchyma sclerenchymas sclerenchymatous sclerite sclerites scleritic scleritis scleroderma sclerodermatous scleroid scleroma scleromas scleromata sclerometer sclerometers scleroprotein scleroproteins sclerosed scleroses sclerosing sclerosis sclerotia sclerotial sclerotic sclerotics sclerotin sclerotins sclerotium sclerotization sclerotizations sclerotized sclerotomies sclerotomy sclerous scoff scoffed scoffer scoffers scoffing scoffingly scofflaw scofflaws scoffs scold scolded scolder scolders scolding scoldingly scoldings scolds scoleces scolecite scolecites scolex scolices scoliosis scoliotic scollop scolloped scolloping scollops scolopendra scolopendrid scolopendrids scolopendrine scombroid scombroids sconce sconces scone scones scoop scooped scooper scoopers scoopful scoopfuls scooping scoops scoot scooted scooter scooters scooting scoots scop scope scoped scopes scoping scopolamine scops scopula scopulae scopulate scorbutic scorbutical scorbutically scorch scorched scorcher scorchers scorches scorching scorchingly score scoreboard scoreboards scorecard scorecards scored scorekeeper scorekeepers scorekeeping scoreless scorer scorers scores scoresby scoria scoriaceous scoriae scorification scorifications scorified scorifier scorifiers scorifies scorify scorifying scoring scorings scorn scorned scorner scorners scornful scornfully scornfulness scorning scorns scorpaenid scorpaenids scorpaenoid scorpaenoids scorpio scorpioid scorpion scorpions scorpios scorpius scot scotch scotched scotches scotching scotchman scotchmen scotchwoman scotchwomen scoter scoters scotia scotic scotism scotist scotists scotland scotoma scotomas scotomata scotomatous scotophil scotophilic scotophily scotophobic scotophobin scotophobins scotopia scotopias scotopic scots scotsman scotsmen scotswoman scotswomen scott scotticism scotticisms scottie scotties scottish scottishness scotty scotus scoundrel scoundrelly scoundrels scour scoured scourer scourers scourge scourged scourger scourgers scourges scourging scouring scourings scours scouse scouser scousers scouses scout scoutcraft scoutcrafts scouted scouter scouters scouting scoutings scoutmaster scoutmasters scouts scow scowl scowled scowler scowlers scowling scowlingly scowls scows scrabble scrabbled scrabbler scrabblers scrabbles scrabbling scrabbly scrag scragged scraggier scraggiest scraggily scragginess scragging scragglier scraggliest scraggly scraggy scrags scram scramble scrambled scrambler scramblers scrambles scrambling scramjet scramjets scrammed scramming scrams scrannel scrap scrapbook scrapbooks scrape scraped scraper scraperboard scraperboards scrapers scrapes scrapheap scrapheaps scrapie scraping scrapings scrappage scrapped scrapper scrappers scrappier scrappiest scrappily scrappiness scrapping scrapple scrappy scraps scratch scratchboard scratchboards scratched scratcher scratchers scratches scratchier scratchiest scratchily scratchiness scratching scratchpad scratchpads scratchproof scratchy scrawl scrawled scrawler scrawlers scrawling scrawls scrawly scrawnier scrawniest scrawniness scrawny screak screaked screaking screaks screaky scream screamed screamer screamers screaming screamingly screams scree screech screeched screecher screechers screeches screeching screechy screed screeds screen screenable screened screener screeners screening screenings screenland screenplay screenplays screens screenwriter screenwriters screenwriting screes screw screwable screwball screwballs screwbean screwbeans screwdriver screwdrivers screwed screwer screwers screwier screwiest screwiness screwing screwlike screws screwup screwups screwworm screwworms screwy scribal scribble scribbled scribbler scribblers scribbles scribbling scribbly scribe scribed scriber scribers scribes scribing scried scries scrim scrimmage scrimmaged scrimmager scrimmagers scrimmages scrimmaging scrimp scrimped scrimper scrimpers scrimpiness scrimping scrimps scrimption scrimpy scrims scrimshander scrimshanders scrimshaw scrimshawed scrimshawing scrimshaws scrip scrips script scripted scripter scripters scripting scriptoria scriptorium scriptoriums scripts scriptural scripturally scripture scriptures scriptwriter scriptwriters scriptwriting scrivener scriveners scrobiculate scrod scrods scrofula scrofulous scrofulously scrofulousness scroll scrollbar scrollbars scrolled scrolling scrolls scrollwork scrooch scrooched scrooches scrooching scrooge scrooges scroogie scroogies scrootch scrootched scrootches scrootching scrota scrotal scrotum scrotums scrouge scrouged scrouges scrouging scrounge scrounged scrounger scroungers scrounges scroungier scroungiest scrounging scroungy scrub scrubbable scrubbed scrubber scrubbers scrubbier scrubbiest scrubbily scrubbiness scrubbing scrubby scrubland scrublands scrubs scrubwoman scrubwomen scruff scruffier scruffiest scruffily scruffiness scruffs scruffy scrum scrummage scrummaged scrummager scrummagers scrummages scrummaging scrummed scrumming scrumptious scrumptiously scrumptiousness scrums scrunch scrunchable scrunched scrunches scrunching scruple scrupled scruples scrupling scrupulosity scrupulous scrupulously scrupulousness scrutable scrutineer scrutineers scrutinies scrutinize scrutinized scrutinizer scrutinizers scrutinizes scrutinizing scrutinizingly scrutiny scry scrying scuba scubas scud scudded scudding scudi scudo scuds scuff scuffed scuffer scuffers scuffing scuffle scuffled scuffler scufflers scuffles scuffling scuffs scull sculled sculler sculleries scullers scullery sculling scullion scullions sculls sculpin sculpins sculpt sculpted sculpting sculptor sculptors sculptress sculptresses sculpts sculptural sculpturally sculpture sculptured sculptures sculpturesque sculpturesquely sculpturing scum scumbag scumbags scumble scumbled scumbles scumbling scummed scummer scummers scummier scummiest scummily scumminess scumming scummy scums scungilli scunner scunners scup scupper scuppered scuppering scuppernong scuppernongs scuppers scups scurf scurfiness scurfy scurried scurries scurril scurrile scurrilities scurrility scurrilous scurrilously scurrilousness scurry scurrying scurvier scurviest scurvily scurviness scurvy scut scuta scutage scutages scutate scutch scutched scutcheon scutcheons scutcher scutchers scutches scutching scute scutella scutellar scutellate scutellated scutellation scutellations scutellum scutes scutiform scuts scutter scuttered scuttering scutters scuttle scuttlebutt scuttled scuttles scuttling scutum scutwork scuzzier scuzziest scuzzy scylla scyphistoma scyphistomae scyphistomas scyphozoan scyphozoans scyros scythe scythed scythes scythia scythian scythians scything scène scènes se sea seabag seabags seabed seabeds seabee seabees seabird seabirds seaboard seaboards seaboot seaboots seaborgium seaborne seacoast seacoasts seacock seacocks seacraft seadog seadogs seafarer seafarers seafaring seafloor seafloors seafood seafowl seafront seafronts seagirt seagoing seagull seagulls seahorse seahorses seajack seajacked seajacker seajackers seajacking seajackings seajacks seal sealable sealant sealants sealed sealer sealers sealift sealifted sealifting sealifts sealing seals sealskin sealskins sealyham seam seaman seamanlike seamanly seamanship seamark seamarks seamed seamen seamer seamers seamier seamiest seaminess seaming seamless seamlessly seamlessness seamlike seamount seamounts seams seamster seamsters seamstress seamstresses seamy seance seances seapiece seapieces seaplane seaplanes seaport seaports seaquake seaquakes sear search searchable searched searcher searchers searches searching searchingly searchless searchlight searchlights seared searing searingly sears seas seascape seascapes seashell seashells seashore seashores seasick seasickness seaside season seasonable seasonableness seasonably seasonal seasonality seasonally seasoned seasoner seasoners seasoning seasonings seasonless seasons seastrand seastrands seat seatback seatbacks seated seater seaters seating seatmate seatmates seatrain seatrains seats seattle seatwork seawall seawalls seaward seawards seaware seawater seaway seaways seaweed seaweeds seaworthier seaworthiest seaworthiness seaworthy sebaceous sebacic sebastian sebastopol sebiferous sebiparous seborrhea seborrheic seborrhoea sebum sec secant secants secco seccos secede seceded seceder seceders secedes seceding secern secerned secerning secernment secernments secerns secession secessional secessionism secessionist secessionists secessions sechuana seckel seclude secluded secludedly secludedness secludes secluding seclusion seclusive seclusively seclusiveness secobarbital secobarbitals seconal second secondaries secondarily secondariness secondary seconded seconder seconders secondhand secondi seconding secondly secondo seconds secondstory secrecies secrecy secret secreta secretagogue secretagogues secretarial secretariat secretariats secretaries secretary secretaryship secrete secreted secreter secreters secretes secretin secreting secretins secretion secretionary secretions secretive secretively secretiveness secretly secretor secretors secretory secrets sect sectarian sectarianism sectarianize sectarianized sectarianizes sectarianizing sectarians sectaries sectary sectile sectility section sectional sectionalism sectionalist sectionalists sectionalization sectionalizations sectionalize sectionalized sectionalizes sectionalizing sectionally sectionals sectioned sectioning sections sector sectored sectorial sectoring sectors sects secular secularism secularist secularistic secularists secularities secularity secularization secularizations secularize secularized secularizer secularizers secularizes secularizing secularly seculars secund secundines securable secure secured securely securement securements secureness securer securers secures securest securing securities securitization securitize securitized securitizes securitizing security sedan sedans sedarim sedate sedated sedately sedateness sedates sedating sedation sedations sedative sedatives sedentarily sedentariness sedentary seder seders sederunt sederunts sedge sedges sedgwick sedile sedilia sediment sedimental sedimentary sedimentation sedimentologic sedimentological sedimentologist sedimentologists sedimentology sediments sedition seditionist seditionists seditious seditiously seditiousness seduce seduceable seduced seducement seducements seducer seducers seduces seducible seducing seduction seductions seductive seductively seductiveness seductress seductresses sedulity sedulous sedulously sedulousness sedum see seeable seecatch seecatchie seed seedbed seedbeds seedcake seedcakes seedcase seedcases seedeater seedeaters seeded seeder seeders seedier seediest seedily seediness seeding seedless seedlike seedling seedlings seedpod seedpods seeds seedsman seedsmen seedtime seedtimes seedy seeing seek seeker seekers seeking seeks seel seeled seeling seels seem seemed seeming seemingly seemingness seemlier seemliest seemliness seemly seems seen seep seepage seeped seeping seeps seepy seer seeress seeresses seers seersucker sees seesaw seesawed seesawing seesaws seethe seethed seethes seething segment segmental segmentally segmentary segmentation segmentations segmented segmenting segments segno segnos sego segos segovia segregable segregant segregants segregate segregated segregates segregating segregation segregationist segregationists segregations segregative segregator segregators segue segued segueing segues seguidilla seguidillas seguing sei seicento seicentos seiche seiches seidel seidels seidlitz seigneur seigneurial seigneuries seigneurs seigneury seignior seigniorage seigniorial seigniories seigniors seigniory seignorage seignorial seignory seine seined seiner seiners seines seining seis seise seised seises seisin seising seisins seism seismic seismically seismicity seismism seismogram seismograms seismograph seismographer seismographers seismographic seismographical seismographs seismography seismologic seismological seismologically seismologist seismologists seismology seismometer seismometers seismometric seismometrical seismometry seismoscope seismoscopes seismoscopic seisms seisor seisors seizable seize seized seizer seizers seizes seizin seizing seizings seizins seizor seizors seizure seizures sejant selachian selachians seladang seladangs selaginella selaginellas selah selassie selcouth seldom seldomness select selectable selected selectee selectees selecting selection selectional selectionism selectionist selectionists selections selective selectively selectiveness selectivities selectivity selectman selectmen selectness selector selectors selects selectwoman selectwomen selenate selenates selene selenic selenide selenides seleniferous selenite selenites selenium selenocentric selenographer selenographers selenographic selenographical selenographically selenographist selenographists selenography selenological selenologist selenologists selenology selenosis seleucid seleucids self selfdom selfhood selfish selfishly selfishness selfless selflessly selflessness selfmate selfness selfridge selfsame selfsameness seljuk seljukian sell sellable sellback sellbacks seller sellers selling selloff sellout sellouts sells selsyn selsyns seltzer seltzers selva selvage selvaged selvages selvas selvedge selvedged selvedges selves semanteme semantemes semantic semantical semantically semanticist semanticists semantics semaphore semaphored semaphores semaphoric semaphorically semaphoring semasiological semasiologist semasiologists semasiology sematic semblable semblables semblably semblance seme semeiology semeiotic semeiotical semeiotics sememe sememes sememic semen semes semester semesters semestral semestrial semi semiabstract semiabstraction semiabstractions semiannual semiannually semiaquatic semiarboreal semiarid semiaridity semiattached semiautobiographical semiautomated semiautomatic semiautomatically semiautomatics semiautonomous semiautonomously semiautonomy semibreve semibreves semicentennial semicentennials semicircle semicircles semicircular semicivilized semiclassic semiclassical semiclassics semicolon semicolonial semicolonialism semicolonies semicolons semicolony semicoma semicomas semicomatose semicommercial semiconducting semiconductor semiconductors semiconscious semiconsciously semiconsciousness semiconservative semiconservatively semicrystalline semidarkness semidarknesses semideified semideifies semideify semideifying semidesert semideserts semidetached semidiameter semidiameters semidiurnal semidivine semidocumentaries semidocumentary semidome semidomed semidomes semidomesticated semidomestication semidominant semidried semidry semidrying semidwarf semidwarfs semielliptical semiempirical semierect semievergreen semifeudal semifinal semifinalist semifinalists semifinals semifinished semifitted semiflexible semiflexion semiflexions semifluid semifluidity semifluids semiformal semigloss semiglosses semiglossy semigovernmental semigroup semigroups semihard semilegendary semilethal semiliquid semiliquidity semiliquids semiliteracy semiliterate semillon semillons semilog semilogarithmic semilunar semilunate semilustrous semimajor semimat semimatt semimatte semimembranous semimetal semimetallic semimetals semimicro semiminor semimoist semimonastic semimonthlies semimonthly semimystical seminal seminally seminar seminarian seminarians seminaries seminarist seminarists seminars seminary seminatural seminiferous seminivorous seminole seminoles seminoma seminomad seminomadic seminomads seminomas seminomata seminude seminudity semiofficial semiofficially semiological semiologically semiologist semiologists semiology semiopaque semiosis semiotic semiotical semiotician semioticians semioticist semioticists semiotics semioviparous semipalmate semipalmated semiparasite semiparasites semiparasitic semiparasitism semipermanent semipermeability semipermeable semipolitical semipopular semiporcelain semiporcelains semipornographic semipornography semipostal semipostals semiprecious semiprivate semipro semiprofessional semiprofessionally semiprofessionals semipros semipublic semipublicly semiquantitative semiquantitatively semiquaver semiquavers semireligious semiretired semiretirement semiretirements semirigid semiround semirounds semirural semis semisacred semisecret semisedentary semiserious semiseriously semishrubby semiskilled semisoft semisolid semisolids semispherical semistaged semisterile semisubmersible semisubmersibles semisweet semisynthetic semite semiterrestrial semites semitic semiticist semiticists semitics semitism semitist semitists semitization semitize semitized semitizes semitizing semitonal semitonally semitone semitones semitonic semitonically semitrailer semitrailers semitranslucent semitransparent semitropic semitropical semitropics semivowel semivowels semiweeklies semiweekly semiworks semiyearlies semiyearly semolina sempervivum sempervivums sempiternal sempiternally sempiternity semplice sempre sempstress sempstresses semtex semé sen senarii senarius senary senate senates senator senatorial senatorially senatorian senators senatorship senatorships send sendal sendals sender senders sending sendoff sendoffs sends sene seneca senecas senecio senecios senectitude senega senegal senegalese senegambia senegas senesce senesced senescence senescent senesces seneschal seneschals senescing senhor senhora senhores senhorita senhors senile senilely senility senior seniorities seniority seniors seniti senna sennas sennet sennets sennight sennights sennit sennits senopia senopias senryu sensa sensate sensated sensately sensation sensational sensationalism sensationalist sensationalistic sensationalists sensationalization sensationalizations sensationalize sensationalized sensationalizes sensationalizing sensationally sensations sensatory sense sensed senseful sensei senseis senseless senselessly senselessness senses sensibilia sensibilities sensibility sensible sensibleness sensibly sensilla sensillum sensing sensitive sensitively sensitiveness sensitives sensitivities sensitivity sensitization sensitizations sensitize sensitized sensitizer sensitizers sensitizes sensitizing sensitometer sensitometers sensitometric sensitometry sensor sensoria sensorial sensorially sensorimotor sensorineural sensorium sensoriums sensors sensory sensual sensualism sensualist sensualistic sensualists sensuality sensualization sensualizations sensualize sensualized sensualizes sensualizing sensually sensualness sensum sensuosity sensuous sensuously sensuousness sensurround sent sentence sentenced sentencer sentencers sentences sentencing sentencings sententia sententiae sentential sententially sententious sententiously sententiousness sentience sentient sentiently sentiment sentimental sentimentalism sentimentalist sentimentalists sentimentalities sentimentality sentimentalization sentimentalizations sentimentalize sentimentalized sentimentalizes sentimentalizing sentimentally sentiments sentimo sentimos sentinel sentineled sentineling sentinelled sentinelling sentinels sentries sentry seoul sepal sepaled sepaline sepaloid sepalous sepals separability separable separableness separably separate separated separately separateness separates separating separation separationist separationists separations separatism separatist separatistic separatists separative separator separators sephardi sephardic sephardim sepia sepias sepiolite sepiolites sepoy sepoys seppuku seppukus sepses sepsis sept septa septage septages septal septaria septarian septarium septate septavalent septcentenary septectomies septectomy september septembers septembrist septembrists septenarii septenarius septenary septenate septendecillion septendecillions septennial septennially septennials septentrion septentrional septentrions septet septets septette septettes septic septicemia septicemic septicidal septicidally septicity septifragal septifragally septilateral septillion septillions septillionth septillionths septimal septivalent septs septuagenarian septuagenarians septuagesima septuagesimas septuagint septuagintal septum septuple septupled septuples septuplet septuplets septupling sepulcher sepulchered sepulchering sepulchers sepulchral sepulchrally sepulchre sepulchred sepulchres sepulchring sepulture sepultures seq sequacious sequaciously sequacity sequel sequela sequelae sequels sequenator sequenators sequence sequenced sequencer sequencers sequences sequencing sequency sequent sequential sequentiality sequentially sequents sequester sequestered sequestering sequesters sequestra sequestrant sequestrants sequestrate sequestrated sequestrates sequestrating sequestration sequestrations sequestrator sequestrators sequestrum sequin sequined sequining sequinned sequins sequitur sequiturs sequoia sequoias sera seraglio seraglios serai seral serape serapes seraph seraphic seraphical seraphically seraphim seraphs serapis serb serbia serbian serbians serbo serbs sere serenade serenaded serenader serenaders serenades serenading serenata serenatas serendipitous serendipitously serendipity serene serenely sereneness serener serenest serenissima serenity serer serest serf serfage serfdom serfs serge sergeancy sergeant sergeanties sergeants sergeantship sergeanty serges serging serial serialism serialist serialists serialization serializations serialize serialized serializes serializing serially serials seriate seriated seriately seriates seriatim seriating seriation sericeous sericin sericins sericteria sericterium sericultural sericulture sericulturist sericulturists seriema seriemas series serif serifed seriffed serifs serigraph serigrapher serigraphers serigraphs serigraphy serin serine serines serins seriocomic seriocomically serious seriously seriousness serjeant serjeants serjeanty sermon sermonette sermonettes sermonic sermonical sermonize sermonized sermonizer sermonizers sermonizes sermonizing sermons seroconversion seroconversions serodiagnoses serodiagnosis serodiagnostic serologic serological serologically serologies serologist serologists serology seronegative seronegativity seropositive seropositivity seropurulent serosa serosae serosal serosas serositis serositises serotherapies serotherapist serotherapists serotherapy serotinal serotine serotines serotinous serotonergic serotonin serotoninergic serotonins serotype serotyped serotypes serotyping serous serow serows serpens serpent serpentaria serpentarium serpentariums serpentine serpentinely serpentines serpents serpiginous serpiginously serpigo serpigos serranid serranids serrano serranos serrate serrated serrates serrating serration serried serriedly serriedness serries serrulate serrulated serrulation serry serrying sertoli sertoman sertularian sertularians serum serums serval servant servanthood servantless servants serve served server servers serves servibar servibars service serviceability serviceable serviceableness serviceably serviceberries serviceberry serviced serviceman servicemen servicepeople serviceperson servicepersons servicer servicers services servicewoman servicewomen servicing serviette serviettes servile servilely servileness servility serving servingly servings servite servites servitor servitors servitorship servitorships servitude servo servomechanism servomechanisms servomotor servomotors servos sesame sesames sesamoid sesamoids sesotho sesquicarbonate sesquicarbonates sesquicentenary sesquicentennial sesquicentennials sesquipedal sesquipedalian sesquipedalians sesquiterpene sesquiterpenes sessile sessility session sessional sessionally sessions sesterce sesterces sestertia sestertium sestet sestets sestina sestinas set seta setaceous setaceously setae setal setback setbacks seth setiferous setiform setigerous setline setlines setoff setoffs setose setout setouts sets setscrew setscrews setswana settable settee settees setter setters setting settings settle settleable settled settlement settlements settler settlers settles settling settlings settlor settlors setup setups seurat sevastopol seven sevenfold sevens seventeen seventeenfold seventeens seventeenth seventeenths seventh seventhly sevenths seventies seventieth seventieths seventy seventyfold sever severability severable several severalfold severally severalties severalty severance severances severe severed severely severeness severer severest severing severities severity severs severus seviche seviches seville sevres sevruga sevrugas sew sewability sewable sewage sewed sewellel sewellels sewer sewerage sewers sewing sewn sews sex sexagenarian sexagenarians sexagenaries sexagenary sexagesima sexagesimal sexagesimally sexagesimas sexcentenaries sexcentenary sexdecillion sexdecillions sexduction sexductions sexed sexennial sexennially sexennials sexes sexier sexiest sexily sexiness sexing sexism sexist sexists sexivalent sexless sexlessly sexlessness sexologic sexological sexologist sexologists sexology sexpartite sexploitation sexpot sexpots sext sextans sextant sextants sextet sextets sextile sextillion sextillions sextillionth sextillionths sexto sextodecimo sextodecimos sexton sextons sextos sexts sextuple sextupled sextuples sextuplet sextuplets sextuplicate sextuplicated sextuplicately sextuplicates sextuplicating sextuplication sextuplications sextupling sextuply sexual sexuality sexualization sexualizations sexualize sexualized sexualizes sexualizing sexually sexvalent sexy seychelles seychellois seyfert seymour seymours señor señora señores señorita señors sferics sforza sforzandi sforzando sforzandos sforzas sfumato sfumatos sgraffiti sgraffito sh sha'ban shaaban shaanxi shaba shabbat shabbier shabbiest shabbily shabbiness shabby shabu shabuoth shack shacked shacking shackle shacklebone shacklebones shackled shackler shacklers shackles shackling shacko shacks shad shadberries shadberry shadblow shadblows shadbush shadbushes shaddock shaddocks shade shaded shadeless shader shaders shades shadflies shadfly shadier shadiest shadily shadiness shading shadings shadoof shadoofs shadow shadowbox shadowboxed shadowboxes shadowboxing shadowed shadower shadowers shadowgraph shadowgraphs shadowgraphy shadowier shadowiest shadowily shadowiness shadowing shadowless shadowlike shadows shadowy shads shaduf shadufs shady shaft shafted shafting shaftings shafts shag shagbark shagbarks shagged shaggier shaggiest shaggily shagginess shagging shaggy shaggymane shaggymanes shagreen shagreens shags shah shahaptian shahaptians shahaptin shahaptins shahdom shahdoms shahs shaitan shaitans shakable shake shakeable shakedown shakedowns shaken shakeout shakeouts shaker shakerism shakers shakes shakespeare shakespearean shakespeareana shakespeareans shakespearian shakespeariana shakespearians shakeup shakeups shakier shakiest shakily shakiness shaking shako shakoes shakos shaksperean shaksperian shakta shaktas shakti shaktism shaktist shaktists shaky shale shaley shalimar shall shallied shallies shalling shalloon shalloons shallop shallops shallot shallots shallow shallowed shallower shallowest shallowing shallowly shallowness shallows shallu shallus shally shallying shallys shalom shalt sham shaman shamanic shamanism shamanist shamanistic shamanists shamans shamash shamble shambled shambles shambling shambolic shambolically shame shamed shamefaced shamefacedly shamefacedness shamefast shameful shamefully shamefulness shameless shamelessly shamelessness shames shaming shammed shammer shammers shammes shammies shamming shammosim shammy shampoo shampooed shampooer shampooers shampooing shampoos shamrock shamrocks shams shamus shamuses shan shan't shandies shandong shandy shandygaff shandygaffs shanghai shanghaied shanghaier shanghaiers shanghaiing shanghais shangri shank shanked shanking shankpiece shankpieces shanks shans shansi shanter shanters shantey shanteys shanties shantung shanty shantyman shantymen shantytown shantytowns shanxi shapable shape shapeable shaped shapeless shapelessly shapelessness shapelier shapeliest shapeliness shapely shapen shaper shapers shapes shapeup shapeups shaping sharable shard shards share shareability shareable sharecrop sharecropped sharecropper sharecroppers sharecropping sharecrops shared shareholder shareholders shareholding shareowner shareowners sharer sharers shares shareware shari'a shari'ah sharia sharif sharifian sharifs sharing shark sharked sharking sharklike sharks sharkskin sharon sharp sharped sharpen sharpened sharpener sharpeners sharpening sharpens sharper sharpers sharpest sharpie sharpies sharping sharply sharpness sharps sharpshooter sharpshooters sharpshooting sharpshootings sharpy shashlick shashlicks shashlik shashliks shaslik shasta shastra shastras shat shatter shattered shattering shatteringly shatterproof shatters shave shaved shaveling shavelings shaven shaver shavers shaves shavetail shavetails shavian shavians shaving shavings shavuot shaw shawl shawled shawling shawls shawm shawms shawnee shawnees shawwal shay shays she she'd she'll she's shea sheaf sheafed sheafing sheaflike sheafs shear sheared shearer shearers shearing shearling shearlings shears shearwater shearwaters sheatfish sheatfishes sheath sheathbill sheathbills sheathe sheathed sheather sheathers sheathes sheathing sheathings sheaths sheave sheaved sheaves sheaving shebang shebat shebats shebeen shebeens shechinah shed shedder shedders shedding shedlike shedrow shedrows sheds sheen sheenies sheeny sheep sheepberries sheepberry sheepcote sheepcotes sheepdog sheepdogs sheepfold sheepfolds sheepherder sheepherders sheepherding sheepish sheepishly sheepishness sheepshank sheepshanks sheepshead sheepsheads sheepshearer sheepshearers sheepshearing sheepshearings sheepskin sheepskins sheer sheered sheerer sheerest sheering sheerlegs sheerly sheerness sheers sheet sheeted sheeter sheeters sheetfed sheeting sheetlike sheetrock sheets shegetz sheik sheika sheikas sheikdom sheikdoms sheikh sheikha sheikhas sheikhdom sheikhdoms sheikhs sheiks sheila shekel shekels shekinah shelby sheldonian sheldrake sheldrakes shelduck shelducks shelf shelfful shelffuls shelflike shelikof shell shellac shellack shellacked shellacking shellacks shellacs shellback shellbacks shellbark shellbarks shellcracker shellcrackers shelled sheller shellers shelley shelleys shellfire shellfish shellfisheries shellfishery shellfishes shellfishing shellflower shellflowers shellier shelliest shelling shellproof shells shellshocked shellwork shelly shelta shelter shelterbelt shelterbelts sheltered shelterer shelterers sheltering shelterless shelters sheltie shelties shelty shelve shelved shelver shelvers shelves shelving shema shemini shenandoah shenanigan shenanigans shensi sheol shepherd shepherded shepherdess shepherdesses shepherding shepherds sheqalim sheqel sheraton sherbert sherberts sherbet sherbets sherd sherds shergottite shergottites sheridan sherif sheriff sheriffdom sheriffs sherifs sherlock sheroot sheroots sherpa sherpas sherries sherry shetland shetlander shetlanders shetlands shevat shevats shewbread shewbreads shi shi'ism shi'ite shi'ites shia shias shiatsu shiatzu shibah shibboleth shibboleths shied shield shielded shielder shielders shielding shields shieling shielings shier shies shiest shift shiftable shifted shifter shifters shiftier shiftiest shiftily shiftiness shifting shiftless shiftlessly shiftlessness shifts shifty shigella shigellae shigellas shigelloses shigellosis shiism shiitake shiite shiites shiitic shikar shikari shikaris shikarred shikarring shikoku shiksa shiksas shikse shikses shill shillalah shillalahs shilled shillelagh shillelaghs shilling shillings shills shilluk shilluks shilly shim shimmed shimmer shimmered shimmering shimmeringly shimmers shimmery shimmied shimmies shimming shimmy shimmying shims shin shina shinbone shinbones shindies shindig shindigs shindy shindys shine shined shiner shiners shines shingle shingled shingler shinglers shingles shingling shingly shingon shinier shiniest shininess shining shiningly shinleaf shinleafs shinleaves shinned shinneries shinnery shinney shinneys shinnied shinnies shinning shinny shinnying shinplaster shinplasters shins shinsplints shinto shintoism shintoist shintoistic shintoists shiny ship shipboard shipborne shipbuilder shipbuilders shipbuilding shipfitter shipfitters shiplap shiplapped shipload shiploads shipman shipmaster shipmasters shipmate shipmates shipmen shipment shipments shipowner shipowners shippable shipped shipper shippers shipping ships shipshape shipside shipsides shipway shipways shipworm shipworms shipwreck shipwrecked shipwrecking shipwrecks shipwright shipwrights shipyard shipyards shire shires shirk shirked shirker shirkers shirking shirks shirr shirred shirring shirrs shirt shirtdress shirtdresses shirted shirtfront shirtfronts shirtier shirtiest shirting shirtless shirtmaker shirtmakers shirts shirtsleeve shirtsleeved shirtsleeves shirttail shirttails shirtwaist shirtwaists shirty shish shit shitake shitfaced shithead shitheads shitless shitlist shitlists shits shittah shittahs shittier shittiest shittim shittimwood shittimwoods shitting shitty shiv shiva shivah shivaism shivaist shivaists shivaree shivarees shiver shivered shivering shivers shivery shivs shkotzim shlemiehl shlemiehls shlemiel shlemiels shlep shlepp shlepped shlepper shleppers shlepping shlepps shleps shlock shmear shmooze shmoozed shmoozes shmoozing shmuck shmucks shoal shoaled shoaling shoals shoat shoats shock shockable shocked shocker shockers shocking shockingly shockproof shocks shod shodden shoddier shoddies shoddiest shoddily shoddiness shoddy shoe shoebill shoebills shoeblack shoeblacks shoebox shoeboxes shoed shoehorn shoehorned shoehorning shoehorns shoeing shoelace shoelaces shoeless shoemaker shoemakers shoemaking shoepac shoepack shoepacks shoepacs shoes shoeshine shoeshines shoestring shoestrings shoetree shoetrees shofar shofars shofroth shogi shogis shogun shogunal shogunate shogunates shoguns shoji shojis shona shonas shone shoo shooed shooflies shoofly shooing shook shooks shoos shoot shootdown shootdowns shooter shooters shooting shootings shootout shootouts shoots shop shopkeeper shopkeepers shoplift shoplifted shoplifter shoplifters shoplifting shoplifts shoppe shopped shopper shoppers shoppes shopping shops shoptalk shopwindow shopwindows shopworn shoran shorans shore shorebird shorebirds shored shorefront shorefronts shoreline shorelines shores shoreside shoreward shorewards shoring shorings shorn short shortage shortages shortbread shortcake shortcakes shortchange shortchanged shortchanger shortchangers shortchanges shortchanging shortcoming shortcomings shortcut shortcuts shortcutting shorted shorten shortened shortener shorteners shortening shortenings shortens shorter shortest shortfall shortfalls shorthair shorthaired shorthairs shorthand shorthanded shorthands shorthorn shorthorns shortia shortias shortie shorties shorting shortish shortleaf shortlist shortlists shortly shortness shorts shortsighted shortsightedly shortsightedness shortstop shortstops shortwave shorty shoshone shoshonean shoshones shoshoni shoshonis shostakovich shot shote shotes shotgun shotgunner shotgunners shotguns shots shott shotted shotten shotting shotts should should've shoulder shouldered shouldering shoulders shouldest shouldn shouldn't shouldst shout shouted shouter shouters shouting shouts shove shoved shovel shoveled shoveler shovelers shovelful shovelfuls shovelhead shovelheads shoveling shovelled shoveller shovellers shovelling shovelnose shovelnoses shovels shovelsful shover shovers shoves shoving show showable showbiz showbizzy showboat showboated showboating showboats showbread showbreads showcase showcased showcases showcasing showdown showdowns showed shower showered showerer showerers showerhead showerheads showering showerless showers showery showgirl showgirls showier showiest showily showiness showing showings showman showmanship showmen shown showoff showoffs showpiece showpieces showplace showplaces showring showrings showroom showrooms shows showstopper showstoppers showstopping showtime showtimes showy shoyu shrank shrapnel shred shredded shredder shredders shredding shreds shrew shrewd shrewder shrewdest shrewdly shrewdness shrewish shrewishly shrewishness shrewlike shrewmice shrewmouse shrews shriek shrieked shrieker shriekers shrieking shrieks shrieval shrievalty shrift shrifts shrike shrikes shrill shrilled shriller shrillest shrilling shrillness shrills shrilly shrimp shrimped shrimper shrimpers shrimpfish shrimpfishes shrimping shrimplike shrimps shrimpy shrine shrined shriner shriners shrines shrining shrink shrinkable shrinkage shrinkages shrinker shrinkers shrinking shrinks shrive shrived shrivel shriveled shriveling shrivelled shrivelling shrivels shriven shriver shrivers shrives shriving shroff shroffs shropshire shroud shrouded shrouding shrouds shrove shrovetide shrub shrubberies shrubbery shrubbier shrubbiest shrubbiness shrubby shrubs shrug shrugged shrugging shrugs shrunk shrunken shtetel shtetels shtetl shtetlach shtetls shtick shticks shtik shtiks shuck shucked shucker shuckers shucking shucks shudder shuddered shuddering shudderingly shudders shuddery shuffle shuffleboard shuffled shuffler shufflers shuffles shuffling shui shul shuls shun shunned shunner shunners shunning shunpike shunpiked shunpiker shunpikers shunpikes shunpiking shuns shunt shunted shunter shunters shunting shunts shush shushed shushes shushing shut shutdown shutdowns shute shuteye shutoff shutoffs shutout shutouts shuts shutter shutterbug shutterbugs shuttered shuttering shutterless shutters shutting shuttle shuttlecock shuttlecocked shuttlecocking shuttlecocks shuttlecraft shuttlecrafts shuttled shuttleless shuttler shuttlers shuttles shuttling shy shyer shyers shyest shying shylock shylocked shylocking shylocks shyly shyness shyster shysterism shysters si siabon siabons sial sialadenitis sialadenitises sialagogic sialagogue sialagogues sialic sialomucin sialomucins sialorrhea sialorrheas sialorrhoea sialorrhoeas sials siam siamang siamangs siamese sib sibari sibelius siberia siberian siberians sibilance sibilancy sibilant sibilantly sibilants sibilate sibilated sibilates sibilating sibilation sibilations sibling siblings sibs sibuyan sibyl sibylic sibyllic sibylline sibyls sic siccative siccatives sicced siccing sichuan sicilian sicilians sicily sick sickbay sickbays sickbed sickbeds sicked sicken sickened sickener sickeners sickening sickeningly sickens sicker sickert sickest sickie sickies sicking sickish sickishly sickishness sickle sicklebill sicklebills sickled sicklemia sicklemias sickles sicklied sicklier sicklies sickliest sicklily sickliness sickling sickly sicklying sickness sicknesses sicko sickos sickout sickouts sickroom sickrooms sicks sics siddons siddur siddurim side sidearm sidearms sideband sidebands sidebar sidebars sideboard sideboards sideburn sideburned sideburns sidecar sidecars sided sidedly sidedness sidedress sidedresses sidehill sidehills sidekick sidekicks sidelight sidelights sideline sidelined sideliner sideliners sidelines sideling sidelining sidelong sideman sidemen sidepiece sidepieces sider sidereal siderite siderites sideritic siderochrome siderochromes siderocyte siderocytes siderolite siderolites siderosis sides sidesaddle sidesaddles sideshow sideshows sideslip sideslipped sideslipping sideslips sidespin sidespins sidesplitting sidesplittingly sidestep sidestepped sidestepper sidesteppers sidestepping sidesteps sidestream sidestroke sidestroked sidestroker sidestrokers sidestrokes sidestroking sideswipe sideswiped sideswiper sideswipers sideswipes sideswiping sidetrack sidetracked sidetracking sidetracks sidewalk sidewalks sidewall sidewalls sideward sidewards sideway sideways sidewinder sidewinders sidewise siding sidings sidle sidled sidles sidling sidlingly sidney sidon siege sieged sieges siegfried sieging siemens siena sienese sienna sierozem sierozems sierra sierran sierras siesta siestas sieva sieve sieved sievert sieverts sieves sieving sifaka sifakas sift sifted sifter sifters sifting siftings sifts sigh sighed sigher sighers sighing sighs sight sighted sightedly sightedness sighting sightings sightless sightlessly sightlessness sightlier sightliest sightline sightlines sightliness sightly sights sightsaw sightsee sightseeing sightseen sightseer sightseers sightsees sigil sigils sigismund sigma sigmas sigmate sigmoid sigmoidal sigmoidally sigmoidoscope sigmoidoscopes sigmoidoscopic sigmoidoscopy sign signage signal signaled signaler signalers signaling signalization signalizations signalize signalized signalizes signalizing signalled signaller signallers signalling signally signalman signalmen signalment signalments signals signatories signatory signature signatures signboard signboards signed signee signees signer signers signet signeted signeting signets signifiable significance significances significancy significant significantly signification significations significative significativeness significs signified signifier signifiers signifies signify signifying signing signings signior signiories signiors signiory signoff signoffs signor signora signoras signore signori signories signorina signorinas signorine signors signory signpost signposts signs sihasapa sihasapas sika sikas sikh sikhism sikhs sikkim sikkimese silage silane silanes silastic sild silds silence silenced silencer silencers silences silencing sileni silent silently silentness silents silenus silesia silesian silesians silesias silex silexes silhouette silhouetted silhouettes silhouetting silhouettist silhouettists silica silicate silicates siliceous silicic silicide silicides siliciferous silicification silicifications silicified silicifies silicify silicifying silicious silicle silicles silicon silicone silicones siliconized silicoses silicosis silicotic silique siliques siliquose siliquous silk silkaline silked silken silkier silkiest silkily silkiness silking silklike silkoline silks silkscreen silkscreened silkscreening silkscreens silkweed silkweeds silkworm silkworms silky sill sillabub sillabubs sillier sillies silliest sillily sillimanite silliness sills silly silo siloed siloing silos siloxane siloxanes silt siltation siltations silted silting silts siltstone siltstones silty silures silurian silurid silurids silva silvae silvan silvanus silvas silver silverback silverbacked silverbacks silverbell silverberries silverberry silvered silverer silverers silvereye silvereyes silverfish silverfishes silveriness silvering silverly silvern silverpoint silverpoints silverrod silverrods silvers silverside silversides silversmith silversmithing silversmiths silvertip silvertips silverware silverweed silverweeds silverwork silvery silvex silvexes silvichemical silvichemicals silvicolous silvicultural silviculturally silviculture silviculturist silviculturists sima simas simazine simchas simchat simeon simian simians similar similarities similarity similarly simile similes similitude simla simmental simmentals simmenthal simmenthals simmer simmered simmering simmers simnel simnels simoleon simoleons simon simoniac simoniacal simoniacally simoniacs simonist simonists simonize simonized simonizes simonizing simony simoom simooms simoon simoons simp simpatico simper simpered simperer simperers simpering simperingly simpers simple simpleminded simplemindedly simplemindedness simpleness simpler simples simplest simpleton simpletons simplex simplexes simplices simplicia simplicial simplicially simplicities simplicity simplification simplifications simplified simplifier simplifiers simplifies simplify simplifying simplism simplistic simplistically simplon simply simps simpson simulacra simulacre simulacres simulacrum simulacrums simular simulars simulate simulated simulates simulating simulation simulations simulative simulator simulators simulcast simulcasted simulcasting simulcasts simulium simuliums simultaneity simultaneous simultaneously simultaneousness sin sinai sinanthropus sinanthropuses sinapism sinapisms sinbad since sincere sincerely sincereness sincerer sincerest sincerity sincipita sincipital sinciput sinciputs sind sindbad sindhi sindhis sine sinecure sinecures sinecurism sinecurist sinecurists sines sinew sinewed sinewing sinews sinewy sinfonia sinfonias sinfonietta sinfoniettas sinful sinfully sinfulness sing singable singapore singaporean singaporeans singe singed singeing singer singers singes singh singhalese singing singings single singled singlehood singleness singles singlestick singlesticker singlestickers singlesticks singlet singleton singletons singletree singletrees singlets singlewide singlewides singling singly sings singsong singsongs singsongy singspiel singspiels singular singularities singularity singularize singularized singularizes singularizing singularly singularness singulars sinhala sinhalese sinicism sinicisms sinicization sinicizations sinicize sinicized sinicizes sinicizing sinification sinifications sinified sinifies sinify sinifying sinister sinisterly sinisterness sinistral sinistrally sinistrorse sinistrorsely sinistrous sinistrously sinitic sink sinkable sinkage sinkages sinker sinkerball sinkerballs sinkers sinkhole sinkholes sinkiang sinking sinks sinless sinlessly sinlessness sinn sinned sinner sinners sinning sino sinoatrial sinoauricular sinolog sinological sinologist sinologists sinologs sinologue sinologues sinology sinope sinophile sinophiles sinophilia sinophobe sinophobes sinophobia sinophobic sinopia sinopias sinopie sins sinsemilla sinsemillas sinter sinterability sintered sintering sinters sinuate sinuated sinuately sinuates sinuating sinuation sinuations sinuosities sinuosity sinuous sinuously sinuousness sinus sinuses sinusitis sinusoid sinusoidal sinusoidally sinusoids siouan siouans sioux sip siphon siphonal siphoned siphonic siphoning siphonophore siphonophores siphonostele siphonosteles siphonostelic siphons siphuncle siphuncles siphuncular siphunculate sipped sipper sippers sippet sippets sipping sips sir sirach sirdar sirdars sire sired siree siren sirenian sirenians sirens sires siriases siriasis siring sirius sirloin sirloins sirocco siroccos sirrah sirrahs sirree sirs sirup sirups sirupy sirvente sirventes sis sisal sisals siscowet siscowets siskin siskins sisseton sissetons sissies sissified sissify sissifying sissiness sissy sissyish sissyness sister sisterhood sisterhoods sisterliness sisterly sisters sistine sistra sistrum sistrums sisyphean sisyphian sisyphus sit sita sitar sitarist sitarists sitars sitatunga sitatungas sitcom sitcoms site sited sites sith siting sitka sitkas sitology sitomania sitomanias sitophobia sitophobias sitosterol sitosterols sits sitter sitters sitting sittings situ situate situated situates situating situation situational situationally situations situs situtunga situtungas sitz sitzkrieg sitzkriegs sitzmark sitzmarks siva sivaism sivaist sivaists sivan siwalik siwash six sixes sixfold sixmo sixmos sixpence sixpences sixpenny sixteen sixteenfold sixteenmo sixteenmos sixteenpenny sixteens sixteenth sixteenths sixth sixthly sixths sixties sixtieth sixtieths sixtine sixty sixtyfold sixtyish sizable sizableness sizably sizar sizars size sizeable sized sizer sizers sizes sizing sizings sizzle sizzled sizzler sizzlers sizzles sizzling sizzlingly siècle sjaelland sjambok sjamboked sjamboking sjamboks sjögren ska skag skagerak skagerrak skags skald skaldic skalds skamble skanda skaneateles skat skate skateboard skateboarded skateboarder skateboarders skateboarding skateboards skated skater skaters skates skating skatol skatole skatoles skatols skean skeane skeans skedaddle skedaddled skedaddler skedaddlers skedaddles skedaddling skeet skeeter skeeters skeg skegs skein skeins skeletal skeletally skeleton skeletonic skeletonize skeletonized skeletonizer skeletonizers skeletonizes skeletonizing skeletons skell skells skelter skeltered skeltering skelters skeltonics skene skenes skep skeps skepsis skeptic skeptical skeptically skepticism skeptics skerries skerry sketch sketchbook sketchbooks sketched sketcher sketchers sketches sketchier sketchiest sketchily sketchiness sketching sketchpad sketchpads sketchy skew skewback skewbacks skewbald skewbalds skewed skewer skewered skewering skewers skewing skewness skews ski skiable skiagram skiagrams skiagraph skiagraphs skiagraphy skiascope skiascopes skiascopies skiascopy skibob skibobber skibobbers skibobbing skibobs skid skidded skidder skidders skiddier skiddiest skidding skiddoo skiddy skidoo skidoos skidproof skids skied skier skiers skies skiey skiff skiffle skiffs skiing skijoring skilful skill skilled skilless skillessness skillet skillets skillful skillfully skillfulness skilling skillings skills skim skimble skimmed skimmer skimmers skimming skimobile skimobiles skimp skimped skimpier skimpiest skimpily skimpiness skimping skimps skimpy skims skin skinflint skinflints skinful skinfuls skinhead skinheads skink skinker skinkers skinks skinless skinned skinner skinnerian skinnerians skinnerism skinners skinnier skinniest skinniness skinning skinny skins skintight skip skipjack skipjacks skippable skipped skipper skippered skippering skippers skipping skips skirl skirled skirling skirls skirmish skirmished skirmisher skirmishers skirmishes skirmishing skirr skirred skirret skirrets skirring skirrs skirt skirted skirter skirters skirting skirts skis skit skits skitter skittered skittering skitters skittery skittish skittishly skittishness skittle skittles skive skived skiver skivers skives skiving skivvies skivvy skiwear skoal skoda skopje skosh skua skuas skulduggeries skulduggery skulk skulked skulker skulkers skulking skulks skull skullcap skullcaps skullduggeries skullduggery skulled skulls skunk skunked skunking skunks skunkweed skunkweeds skunkworks sky skyborne skybox skyboxes skycap skycaps skydive skydived skydiver skydivers skydives skydiving skye skyey skyhook skyhooks skying skyjack skyjacked skyjacker skyjackers skyjacking skyjacks skylark skylarked skylarker skylarkers skylarking skylarks skylight skylighted skylights skyline skylines skylit skyrocket skyrocketed skyrocketing skyrockets skyros skysail skysails skyscraper skyscrapers skyscraping skywalk skywalks skyward skywards skyway skyways skywrite skywriter skywriters skywrites skywriting skywritten skywrote skíros slab slabbed slabber slabbered slabbering slabbers slabbing slablike slabs slack slacked slacken slackened slackening slackens slacker slackers slackest slacking slackly slackness slacks slag slagged slagging slaggy slags slain slake slaked slakes slaking slalom slalomed slalomer slalomers slaloming slalomist slalomists slaloms slam slammed slammer slammers slamming slams slander slandered slanderer slanderers slandering slanderous slanderously slanderousness slanders slang slanged slangily slanginess slanging slangs slanguage slangy slant slanted slanting slantingly slants slantways slantwise slanty slap slapdash slaphappier slaphappiest slaphappy slapjack slapjacks slapped slapper slappers slapping slaps slapstick slapsticks slash slashed slasher slashers slashes slashing slashingly slat slate slated slatelike slater slaters slates slatey slather slathered slathering slathers slatier slatiest slating slats slatted slattern slatternliness slatternly slatterns slatting slaty slaughter slaughtered slaughterer slaughterers slaughterhouse slaughterhouses slaughtering slaughterous slaughterously slaughters slav slave slaved slaveholder slaveholders slaveholding slaveholdings slaver slavered slaveries slavering slavers slavery slaves slavey slaveys slavic slavicist slavicists slaving slavish slavishly slavishness slavism slavist slavists slavocracies slavocracy slavocrat slavocratic slavocrats slavonia slavonian slavonians slavonic slavophil slavophile slavophiles slavophilism slavophils slavs slaw slaws slay slayed slayer slayers slaying slays sle sleave sleaves sleaze sleazebag sleazebags sleazeball sleazeballs sleazier sleaziest sleazily sleaziness sleazo sleazy sled sledded sledder sledders sledding sledge sledged sledgehammer sledgehammered sledgehammering sledgehammers sledges sledging sleds sleek sleeked sleeken sleekened sleekening sleekens sleeker sleekest sleeking sleekly sleekness sleeks sleep sleeper sleepers sleepier sleepiest sleepily sleepiness sleeping sleepless sleeplessly sleeplessness sleeplike sleepover sleepovers sleeps sleepwalk sleepwalked sleepwalker sleepwalkers sleepwalking sleepwalks sleepwear sleepy sleepyhead sleepyheads sleet sleeted sleeting sleets sleety sleeve sleeved sleeveless sleevelet sleevelets sleeves sleeving sleigh sleighed sleigher sleighers sleighing sleighs sleight sleights slender slenderer slenderest slenderize slenderized slenderizes slenderizing slenderly slenderness slept sles sleuth sleuthed sleuthhound sleuthhounds sleuthing sleuths slew slewed slewing slews slice sliceable sliced slicer slicers slices slicing slick slicked slicken slickened slickener slickeners slickening slickens slickenside slickensides slicker slickers slickest slicking slickly slickness slickrock slicks slid slidden slide slider sliders slides slideway slideways sliding slier sliest slight slighted slighter slightest slighting slightingly slightly slightness slights slim slime slimeball slimeballs slimed slimes slimier slimiest slimily sliminess sliming slimly slimmed slimmer slimmers slimmest slimming slimnastics slimness slimpsy slims slimsier slimsiest slimsy slimy sling slinger slingers slinging slings slingshot slingshots slink slinked slinkier slinkiest slinkily slinkiness slinking slinkingly slinks slinky slip slipcase slipcased slipcases slipcover slipcovered slipcovering slipcovers slipform slipformed slipforming slipforms slipknot slipknots slipover slipovers slippage slipped slipper slippered slipperier slipperiest slipperiness slippers slipperwort slipperworts slippery slippier slippiest slipping slippy slips slipshod slipshoddiness slipshodness slipslop slipslops slipsole slipsoles slipstitch slipstitches slipstream slipstreamed slipstreaming slipstreams slipup slipups slipware slipway slipways slit slither slithered slithering slithers slithery slitless slits slitter slitters slitting slitty sliver slivered slivering slivers slivery slivovitz slob slobber slobbered slobberer slobberers slobbering slobbers slobbery slobbish slobby slobs sloe sloes slog slogan sloganeer sloganeered sloganeering sloganeers sloganize sloganized sloganizer sloganizers sloganizes sloganizing slogans slogged slogger sloggers slogging slogs sloop sloops slop slope sloped sloper slopers slopes sloping slopingly slopped sloppier sloppiest sloppily sloppiness slopping sloppy slops slopwork slosh sloshed sloshes sloshing sloshy slot slotback slotbacks sloth slothful slothfully slothfulness sloths slots slotted slotting slouch slouched sloucher slouchers slouches slouchier slouchiest slouchily slouchiness slouching slouchy slough sloughed sloughing sloughs sloughy slovak slovakia slovakian slovakians slovaks sloven slovene slovenes slovenia slovenian slovenians slovenlier slovenliest slovenliness slovenly slovens slow slowdown slowdowns slowed slower slowest slowing slowish slowly slowness slowpoke slowpokes slows slowwitted slowworm slowworms sloyd sloyds slub slubbed slubbing slubs sludge sludged sludges sludgiest sludging sludgy slue slued slues slug slugabed slugabeds slugfest slugfests sluggard sluggardly sluggardness sluggards slugged slugger sluggers slugging sluggish sluggishly sluggishness slugs sluice sluiced sluices sluiceway sluiceways sluicing sluicy sluing slum slumber slumbered slumberer slumberers slumbering slumberingly slumberous slumberously slumberousness slumbers slumbery slumbrous slumgullion slumgullions slumlord slumlords slummed slummer slummier slummiest slumming slummy slump slumped slumpflation slumping slumps slums slung slungshot slungshots slunk slur slurb slurbs slurp slurped slurping slurps slurred slurried slurries slurring slurry slurrying slurs slush slushed slushes slushier slushiest slushily slushiness slushing slushy slut sluts sluttish sluttishly sluttishness slutty sly slyboots slyer slyest slyly slyness slype slypes smack smacked smacker smackers smacking smacks small smallclothes smaller smallest smallholder smallholders smallholding smallholdings smallish smallmouth smallness smallpox smalls smallsword smallswords smalltime smalltimer smalltimers smalt smalti smaltine smaltines smaltite smaltites smalto smalts smaragd smaragdine smaragdite smaragdites smarm smarmier smarmiest smarmily smarminess smarmy smart smarted smarten smartened smartening smartens smarter smartest smartie smarties smarting smartly smartness smarts smartweed smartweeds smarty smash smashed smasher smashers smashes smashing smashingly smashup smashups smatter smattered smatterer smatterers smattering smatterings smatters smaze smazes smear smearcase smearcases smeared smearer smearers smearier smeariest smeariness smearing smears smeary smectic smectite smectites smectitic smegma smell smelled smeller smellers smellier smelliest smelling smells smelly smelt smelted smelter smelteries smelters smeltery smelting smelts smetana smew smews smidge smidgen smidgens smidgeon smidgeons smidgin smidgins smiercase smilax smilaxes smile smiled smileless smiler smilers smiles smiley smiling smilingly smilingness smilodons smilodonss smily smirch smirched smirches smirching smirk smirked smirker smirkers smirkily smirking smirkingly smirks smirky smite smiter smiters smites smith smithereens smitheries smithery smithfield smithies smiths smithsonian smithsonite smithsonites smithy smiting smitten smock smocked smocking smockings smocks smog smoggier smoggiest smoggy smogless smokable smoke smokeable smoked smokehouse smokehouses smokejack smokejacks smokejumper smokejumpers smokeless smokelike smoker smokers smokes smokescreen smokescreens smokestack smokestacks smokey smokier smokiest smokily smokiness smoking smoky smolder smoldered smoldering smolderingly smolders smolensk smollett smolt smolts smooch smooched smooches smooching smoochy smooth smoothbore smoothbores smoothed smoothen smoothened smoothening smoothens smoother smoothers smoothes smoothest smoothie smoothies smoothing smoothly smoothness smooths smoothy smorgasbord smorgasbords smote smother smothered smothering smothers smothery smoulder smouldered smouldering smoulders smudge smudged smudges smudgier smudgiest smudgily smudginess smudging smudgy smug smugger smuggest smuggle smuggled smuggler smugglers smuggles smuggling smugly smugness smut smutch smutched smutches smutching smutchy smuts smutted smuttier smuttiest smuttily smuttiness smutting smutty smyrna snack snacked snacker snackers snacking snacks snaffle snaffled snaffles snaffling snafu snafued snafuing snafus snag snagged snagging snaggleteeth snaggletooth snaggletoothed snaggy snags snail snaillike snails snake snake's snakebird snakebirds snakebit snakebite snakebites snakebitten snaked snakefish snakefishes snakehead snakeheads snakelike snakemouth snakemouths snakeroot snakeroots snakes snakeskin snakeskins snakestone snakestones snakeweed snakeweeds snakey snakier snakiest snakily snakiness snaking snaky snap snapback snapbacks snapdragon snapdragons snapped snapper snappers snappier snappiest snappily snappiness snapping snappish snappishly snappishness snappy snaps snapshoot snapshooter snapshooters snapshooting snapshoots snapshot snapshots snare snared snarer snarers snares snaring snarky snarl snarled snarler snarlers snarling snarlingly snarls snarly snatch snatched snatcher snatchers snatches snatchier snatchiest snatching snatchy snath snathe snathes snaths snazzier snazziest snazziness snazzy sneak sneaked sneaker sneakered sneakers sneakier sneakiest sneakily sneakiness sneaking sneakingly sneaks sneaky sneer sneered sneerer sneerers sneerful sneering sneeringly sneers sneery sneeze sneezed sneezer sneezers sneezes sneezeweed sneezeweeds sneezewort sneezeworts sneezing sneezy snell snellen snells snib snibbed snibbing snibs snick snicked snicker snickered snickerer snickerers snickering snickeringly snickers snickersnee snickersnees snickery snicking snicks snide snidely snideness snider snidest sniff sniffable sniffed sniffer sniffers sniffier sniffiest sniffily sniffiness sniffing sniffish sniffishly sniffishness sniffle sniffled sniffler snifflers sniffles sniffling sniffly sniffs sniffy snifter snifters snigger sniggered sniggerer sniggerers sniggering sniggers sniggle sniggled sniggles sniggling snip snipe sniped snipefish snipefishes sniper snipers sniperscope sniperscopes snipes sniping snipped snipper snippers snippersnapper snippersnappers snippet snippetier snippetiest snippets snippety snippier snippiest snippily snippiness snipping snippy snips snit snitch snitched snitcher snitchers snitches snitching snits snivel sniveled sniveler snivelers sniveling snivelled snivelling snivels snob snobberies snobbery snobbier snobbiest snobbish snobbishly snobbishness snobbism snobby snobs snoek snoeks snollygoster snollygosters snood snooded snooding snoods snook snooker snookered snookering snookers snooks snoop snooped snooper snoopers snoopier snoopiest snoopily snoopiness snooping snoops snoopy snoot snooted snootier snootiest snootily snootiness snooting snoots snooty snooze snoozed snoozer snoozers snoozes snoozing snoozle snoozled snoozles snoozling snore snored snorer snorers snores snoring snorkel snorkeled snorkeler snorkelers snorkeling snorkels snort snorted snorter snorters snorting snorts snot snots snottier snottiest snottily snottiness snotty snout snouted snoutish snouts snouty snow snowball snowballed snowballing snowballs snowbank snowbanks snowbell snowbells snowbelt snowbelts snowberries snowberry snowbird snowbirds snowblink snowblinks snowblower snowblowers snowboard snowboarded snowboarder snowboarders snowboarding snowboards snowbound snowbrush snowbrushes snowbush snowbushes snowcap snowcapped snowcaps snowdrift snowdrifts snowdrop snowdrops snowed snowfall snowfalls snowfield snowfields snowflake snowflakes snowier snowiest snowily snowiness snowing snowless snowmaker snowmakers snowmaking snowmakings snowman snowmelt snowmelts snowmen snowmobile snowmobiler snowmobilers snowmobiles snowmobiling snowmobilist snowmobilists snowpack snowpacks snowplough snowploughs snowplow snowplowed snowplowing snowplows snows snowscape snowscapes snowshed snowsheds snowshoe snowshoed snowshoeing snowshoer snowshoers snowshoes snowslide snowslides snowstorm snowstorms snowsuit snowsuits snowy snub snubbed snubber snubbers snubbiness snubbing snubby snubness snubs snuck snuff snuffbox snuffboxes snuffed snuffer snuffers snuffing snuffle snuffled snuffler snufflers snuffles snuffling snuffly snuffs snuffy snug snugged snugger snuggeries snuggery snuggest snugging snuggle snuggled snuggles snuggling snuggly snugly snugness snugs so soak soakage soaked soaker soakers soaking soaks soap soapbark soapbarks soapberries soapberry soapbox soapboxed soapboxes soapboxing soaped soaper soapers soapier soapiest soapily soapiness soaping soaps soapstone soapsuds soapwort soapworts soapy soar soared soarer soarers soaring soaringly soarings soars soave soaves sob sobbed sobbing sobbingly sober sobered soberer soberest sobering soberize soberized soberizes soberizing soberly soberness sobers sobersided sobersidedness sobersides sobriety sobriquet sobriquets sobs soca socage socager socagers socages socas soccage soccages soccer sociabilities sociability sociable sociableness sociables sociably social socialism socialist socialistic socialistically socialists socialite socialites socialities sociality socialization socializations socialize socialized socializer socializers socializes socializing socially socials societal societally societies society socinian socinianism socinians sociobiological sociobiologist sociobiologists sociobiology sociocultural socioculturally socioeconomic socioeconomically sociogram sociograms sociohistorical sociolinguist sociolinguistic sociolinguistics sociolinguists sociologese sociologic sociological sociologically sociologist sociologists sociology sociometric sociometry sociopath sociopathic sociopaths sociopolitical sociopsychological socioreligious sociosexual sock sockdolager sockdolagers sockdologer sockdologers socked socket socketed socketing sockets sockeye sockeyes socking sockless socko socks socle socles socotra socrates socratic socratically sod soda sodalist sodalists sodalite sodalites sodalities sodality sodas sodbuster sodbusters sodded sodden soddened soddening soddenly soddenness soddens sodding sodic sodium sodom sodomist sodomists sodomite sodomites sodomitic sodomitical sodomize sodomized sodomizes sodomizing sodomy sods soever sofa sofar sofars sofas soffit soffits sofia soft softback softbacks softball softballer softballers softballs softbound softcover soften softened softener softeners softening softens softer softest softhead softheaded softheadedly softheadedness softheads softhearted softheartedly softheartedness softie softies softish softly softness softnesses softshell softshells software softwood softwoods softy sogdian sogdians soggier soggiest soggily sogginess soggy sognafjord soho soigné soignée soil soilage soilborne soiled soiler soiling soilism soilless soils soilure soiree soirees soirée soirées soixante sojourn sojourned sojourner sojourners sojourning sojourns soke sokeman sokemen sokes sol sola solace solaced solacement solacer solacers solaces solacing solan solanaceous solanin solanine solanines solanins solans solanum solanums solar solaria solarimeter solarimeters solarium solariums solarization solarizations solarize solarized solarizes solarizing solatia solation solatium sold soldan soldans solder solderability soldered solderer solderers soldering solders soldi soldier soldiered soldieries soldiering soldierly soldiers soldiership soldiery soldo sole solecism solecisms solecist solecistic solecists soled solei solely solemn solemner solemnest solemnified solemnifies solemnify solemnifying solemnities solemnity solemnization solemnizations solemnize solemnized solemnizes solemnizing solemnly solemnness soleness solenodon solenodons solenoid solenoidal solenoidally solenoids soleplate soleplates soleprint soleprints soles soleus solfatara solfataras solfataric solfeggi solfeggio solfeggios solferino solferinos solfège solgel solicit solicitant solicitants solicitation solicitations solicited soliciting solicitor solicitors solicitorship solicitous solicitously solicitousness solicits solicitude solicitudes solid solidago solidagos solidarism solidarist solidaristic solidarists solidarity solider solidest solidi solidification solidifications solidified solidifier solidifiers solidifies solidify solidifying solidity solidly solidness solids solidus solifluction soliloquies soliloquist soliloquists soliloquize soliloquized soliloquizer soliloquizers soliloquizes soliloquizing soliloquy soliman soling solipsism solipsist solipsistic solipsistically solipsists solitaire solitaires solitarian solitarians solitaries solitarily solitariness solitary soliton solitons solitude solitudinarian solitudinarians solleret sollerets solmization solmizations solo soloed soloing soloist soloistic soloists solomon solomonic solomons solon solonchak solonchaks solonetz solonetzic solons solos sols solstice solstices solstitial solubilities solubility solubilization solubilizations solubilize solubilized solubilizes solubilizing soluble solubleness solubly solum solums solus solute solutes solution solutions solutrean solutrian solvability solvable solvableness solvate solvated solvates solvating solvation solvations solvay solve solved solvency solvent solventless solvently solvents solver solvers solves solving solvolysis solvolytic soma somali somalia somalian somalians somaliland somalis somas somata somatic somatically somatogenetic somatogenic somatologic somatological somatologist somatologists somatology somatomedin somatomedins somatoplasm somatoplasms somatoplastic somatopleural somatopleure somatopleures somatopleuric somatosensory somatostatin somatostatins somatotherapies somatotherapy somatotrophin somatotrophins somatotropic somatotropin somatotropins somatotype somatotypes somatotypic somber somberly somberness sombre sombrero sombreros sombrous some somebodies somebody somebody's someday somehow someone someone's someplace somersault somersaulted somersaulting somersaults somerset somersets somersetted somersetting somesthetic something sometime sometimes someway someways somewhat somewhen somewhere somewheres somewhither somite somites somitic somme sommelier sommeliers somnambulant somnambular somnambulate somnambulated somnambulates somnambulating somnambulation somnambulations somnambulism somnambulist somnambulistic somnambulistically somnambulists somnifacient somnifacients somniferous somniferously somnific somniloquies somniloquist somniloquists somniloquy somnolence somnolent somnolently son sonance sonances sonant sonants sonar sonata sonatas sonatina sonatinas sonde sondes sone sones song songbird songbirds songbook songbooks songfest songfests songful songfully songfulness songless songlessly songlike songs songsmith songsmiths songster songsters songstress songstresses songwriter songwriters songwriting sonhood sonic sonically sonicate sonicated sonicates sonicating sonication sonications sonless sonly sonnet sonneteer sonneteering sonneteers sonnets sonnies sonny sonobuoy sonobuoys sonogram sonograms sonograph sonographer sonographers sonographic sonographs sonography sonometer sonometers sonorant sonorants sonorities sonority sonorous sonorously sonorousness sons sonship soochong soochongs soon sooner sooners soonest soot sooted sooth soothe soothed soother soothers soothes soothfast soothing soothingly soothingness soothly sooths soothsaid soothsay soothsayer soothsayers soothsaying soothsayings soothsays sootier sootiest sootily sootiness sooting soots sooty sop sopaipilla sopapilla sophism sophisms sophist sophistic sophistical sophistically sophisticate sophisticated sophisticatedly sophisticates sophisticating sophistication sophistications sophisticator sophisticators sophistries sophistry sophists sophoclean sophocles sophomore sophomores sophomoric sophomorically sophonias sopor soporiferous soporiferously soporiferousness soporific soporifically soporifics sopors sopped soppier soppiest soppiness sopping soppy sopranino sopraninos soprano sopranos sops sora soras sorb sorbability sorbable sorbate sorbates sorbed sorbefacient sorbefacients sorbent sorbents sorbet sorbets sorbian sorbians sorbic sorbing sorbitol sorbonne sorbose sorboses sorbs sorcerer sorcerers sorceress sorceresses sorcerous sorcerously sorcery sordid sordidly sordidness sordini sordino sords sore sored soredia soredial soredium sorehead soreheaded soreheads sorely soreness sorer sores sorest sorgho sorghos sorghum sorghums sorgo sorgos sori soricine soring sorites soroptimist soroptimists sororal sororate sororates sororicidal sororicide sororicides sororities sorority sorption sorptive sorrel sorrels sorrento sorrier sorriest sorrily sorriness sorrow sorrowed sorrower sorrowers sorrowful sorrowfully sorrowfulness sorrowing sorrows sorry sort sortable sortation sortations sorted sorter sorters sortie sortied sortieing sorties sortilege sortileges sorting sortition sortitions sorts sorus sos sostenuti sostenuto sostenutos sot soteriologic soteriological soteriology sothic sotho sotol sotols sots sotted sottedly sottedness sottish sottishly sottishness sotto sou sou'wester sou'westers souari soubise soubises soubrette soubrettes soubriquet soubriquets souchong souchongs souci soudan soudans soufflé souffléd soufflés soufrière sough soughed soughing soughs sought souk souks soul souled soulful soulfully soulfulness soulless soullessly soullessness soulmate soulmates souls sound soundable soundalike soundboard soundboards sounded sounder sounders soundest sounding soundingly soundings soundless soundlessly soundlessness soundly soundman soundmen soundness soundproof soundproofed soundproofing soundproofs sounds soundstage soundstages soundtrack soundtracks soup souped soupier soupiest soups soupspoon soupspoons soupy soupçon soupçons sour sourball sourballs source sourcebook sourcebooks sourced sourceless sources sourcing sourdine sourdines sourdough sourdoughs soured sourer sourest souring sourish sourly sourness sourpuss sourpusses sours soursop soursops sourwood sourwoods sous sousa sousaphone sousaphones souse soused souses sousing souslik sousliks soutache soutaches soutane soutanes south southampton southbound southdown southeast southeaster southeasterly southeastern southeasterner southeasterners southeasternmost southeasters southeastward southeastwardly southeastwards souther southerlies southerly southern southerner southerners southernism southernisms southernmost southernness southernwood southernwoods southers southey southing southings southland southlander southlanders southlands southpaw southpaws southron southrons southward southwardly southwards southwest southwester southwesterly southwestern southwesterner southwesterners southwesternmost southwesters southwestward southwestwardly southwestwards souvenir souvenirs souvlaki souvlakia sovereign sovereignly sovereigns sovereignties sovereignty soviet sovietism sovietization sovietizations sovietize sovietized sovietizes sovietizing sovietologist sovietologists sovietology soviets sovkhoz sovkhozes sovkhozy sovran sovrans sovranties sovranty sow sowbellies sowbelly sowbread sowbreads sowed sowens sower sowers sowetan sowetans soweto sowing sowings sown sows sox soxer soxers soy soya soybean soybeans soymilk sozzled spa space spaceband spacebands spacebar spacebars spaceborne spacebridge spacebridges spacecraft spaced spacefarer spacefarers spacefaring spacefarings spaceflight spaceflights spaceless spaceman spacemen spaceport spaceports spacer spacers spaces spaceship spaceships spacesick spacesuit spacesuits spacewalk spacewalked spacewalker spacewalkers spacewalking spacewalks spaceward spacey spacial spacier spaciest spacing spacings spacious spaciously spaciousness spackle spackled spackles spackling spacy spade spaded spadefish spadefishes spadefoot spadeful spadefuls spader spaders spades spadework spadices spadille spading spadix spaetzle spaetzles spaghetti spaghettilike spaghettini spaghettis spagyric spagyrical spahi spahis spain spall spallable spallation spallations spalled spalling spalls spalpeen spalpeens spam spammed spamming spams span spanakopita spanakopitas spandau spandex spandrel spandrels spandril spandrils spang spangle spangled spangles spangling spanglish spangly spaniard spaniards spaniel spaniels spanish spanishness spank spanked spanker spankers spanking spankingly spankings spanks spanned spanner spanners spanning spanokopita spans spanworm spanworms spar spare spareable spared sparely spareness sparer sparerib spareribs sparers spares sparest sparge sparged sparger spargers sparges sparging sparid sparids sparing sparingly sparingness spark sparked sparker sparkers sparkier sparkiest sparkily sparking sparkish sparkle sparkleberries sparkleberry sparkled sparkler sparklers sparkles sparklier sparkliest sparkling sparklingly sparkly sparkplug sparkplugged sparkplugging sparkplugs sparks sparky sparling sparlings sparred sparring sparrow sparrowgrass sparrowlike sparrows spars sparse sparsely sparseness sparser sparsest sparsity sparta spartacist spartacists spartacus spartan spartanism spartanly spartans sparteine sparteines spas spasm spasmodic spasmodically spasmolytic spasmolytics spasms spastic spastically spasticity spastics spat spatchcock spatchcocked spatchcocking spatchcocks spate spates spathe spathes spathic spathulate spatial spatiality spatially spatiotemporal spatiotemporally spats spatted spatter spatterdock spatterdocks spattered spattering spatters spatting spatula spatular spatulas spatulate spatzle spatzles spavin spavined spawn spawned spawner spawners spawning spawns spay spayed spaying spays spaz spazzes speak speakable speakeasies speakeasy speaker speakerphone speakerphones speakers speakership speakerships speaking speaks spear speared spearer spearers spearfish spearfished spearfisher spearfishers spearfishes spearfishing speargun spearguns spearhead spearheaded spearheading spearheads spearing spearlike spearman spearmen spearmint spearmints spears spearwort spearworts spec spec'd spec'er spec'ers spec'ing specced speccing special specialism specialisms specialist specialistic specialists specialities speciality specialization specializations specialize specialized specializes specializing specially specialness specials specialties specialty speciate speciated speciates speciating speciation speciational speciations specie species speciesism speciesist speciesists specifiable specific specifically specification specifications specificity specificness specifics specified specifier specifiers specifies specify specifying specimen specimens speciosity specious speciously speciousness speck specked specking speckle speckled speckles speckling specks specs spectacle spectacled spectacles spectacular spectacularity spectacularly spectaculars spectate spectated spectates spectating spectator spectatorial spectators spectatorship spectatorships specter specters spectinomycin spectinomycins spectra spectral spectrality spectrally spectralness spectre spectres spectrin spectrins spectrofluorimeter spectrofluorimeters spectrofluorometer spectrofluorometers spectrofluorometric spectrofluorometry spectrogram spectrograms spectrograph spectrographic spectrographically spectrographs spectrography spectroheliogram spectroheliograms spectroheliograph spectroheliographic spectroheliographs spectroheliography spectrohelioscope spectrohelioscopes spectrohelioscopic spectrometer spectrometers spectrometric spectrometry spectrophotometer spectrophotometers spectrophotometric spectrophotometrical spectrophotometrically spectrophotometry spectroscope spectroscopes spectroscopic spectroscopical spectroscopically spectroscopies spectroscopist spectroscopists spectroscopy spectrum spectrums specula specular specularity specularly speculate speculated speculates speculating speculation speculations speculative speculatively speculativeness speculator speculators speculum speculums sped speech speeches speechified speechifier speechifiers speechifies speechify speechifying speechless speechlessly speechlessness speechmaker speechmakers speechmaking speechwriter speechwriters speechwriting speed speedball speedballs speedboat speedboater speedboaters speedboating speedboatings speedboats speeded speeder speeders speedier speediest speedily speediness speeding speedings speedo speedometer speedometers speedos speeds speedster speedsters speedup speedups speedway speedways speedwell speedwells speedwriter speedwriters speedwriting speedwritings speedy speiss speisses speleological speleologist speleologists speleology spell spellbind spellbinder spellbinders spellbinding spellbindingly spellbinds spellbound spellchecker spellcheckers spelldown spelldowns spelled speller spellers spelling spellings spells spelt spelter spelters spelunker spelunkers spelunking spencer spencerian spencerianism spencerians spencerism spencers spend spendable spender spenders spending spends spendthrift spendthrifts spenglerian spenglerians spenser spenserian spent sperm spermaceti spermacetis spermagonia spermagonium spermaries spermary spermatheca spermathecas spermatia spermatial spermatic spermatid spermatids spermatium spermatocyte spermatocytes spermatogenesis spermatogenetic spermatogenic spermatogonia spermatogonial spermatogonium spermatophore spermatophores spermatophyte spermatophytes spermatophytic spermatozoa spermatozoal spermatozoan spermatozoid spermatozoids spermatozoon spermicidal spermicide spermicides spermiogenesis spermogonia spermogonium spermophile spermophiles spermous sperms sperrylite sperrylites spessartine spessartines spessartite spessartites spew spewed spewer spewers spewing spews sphagnous sphagnum sphalerite sphalerites sphene sphenes sphenic sphenodon sphenodons sphenodont sphenogram sphenograms sphenoid sphenoidal sphenoids sphenopsid sphenopsids spheral sphere sphered spheres spheric spherical spherically sphericalness sphericity spherics spherier spheriest sphering spheroid spheroidal spheroidally spheroidic spheroidicity spheroids spherometer spherometers spheroplast spheroplasts spherular spherule spherules spherulite spherulites spherulitic sphery sphincter sphincteral sphincteric sphincters sphinges sphingid sphingids sphingosine sphingosines sphinx sphinxes sphinxlike sphragistics sphygmic sphygmogram sphygmograms sphygmograph sphygmographic sphygmographs sphygmography sphygmoid sphygmomanometer sphygmomanometers sphygmomanometric sphygmomanometrically sphygmomanometry sphygmometer sphygmometers spic spica spicae spicas spicate spiccato spiccatos spice spiceberries spiceberry spicebush spicebushes spiced spiceless spiceries spicery spices spicier spiciest spicily spiciness spicing spick spicks spics spicula spiculae spicular spiculate spiculation spiculations spicule spicules spiculum spicy spider spiderish spiderlike spiders spiderweb spiderwebs spiderwort spiderworts spidery spied spiegel spiegeleisen spiegeleisens spiegels spiel spieled spieler spielers spieling spiels spier spiers spies spiff spiffed spiffied spiffier spiffies spiffiest spiffily spiffiness spiffing spiffs spiffy spiffying spigot spigots spik spike spiked spikelet spikelets spikelike spikenard spikenards spiker spikers spikes spikey spikier spikiest spikily spikiness spiking spiks spiky spile spiled spiles spiling spill spillable spillage spillback spillbacks spilled spiller spillers spillikin spillikins spilling spillover spillovers spills spillway spillways spilt spilth spilths spin spina spinach spinachlike spinachy spinal spinally spinals spindle spindled spindler spindlers spindles spindlier spindliest spindling spindly spindrift spine spined spinel spineless spinelessly spinelessness spinelike spinelle spinelles spinels spines spinescence spinescent spinet spinets spinier spiniest spiniferous spinifex spinifexes spininess spinless spinnaker spinnakers spinner spinneret spinnerets spinnerette spinnerettes spinners spinney spinneys spinning spinnings spinocerebellar spinoff spinoffs spinor spinors spinose spinosely spinosity spinous spinout spinouts spinoza spinozism spinozist spinozistic spinozists spins spinster spinsterhood spinsterish spinsterly spinsters spinthariscope spinthariscopes spinthariscopic spinto spintos spinule spinules spinulose spinulous spiny spiracle spiracles spiracular spiraea spiraeas spiral spiraled spiraling spirality spiralled spiralling spirally spirals spirant spirants spire spirea spireas spired spirem spireme spiremes spirems spires spiriferous spirilla spirillum spiring spirit spirited spiritedly spiritedness spiriting spiritism spiritist spiritistic spiritists spiritless spiritlessly spiritlessness spiritoso spiritous spirits spiritual spiritualism spiritualist spiritualistic spiritualists spiritualities spirituality spiritualization spiritualizations spiritualize spiritualized spiritualizer spiritualizers spiritualizes spiritualizing spiritually spiritualness spirituals spiritualties spiritualty spirituel spirituelle spirituosity spirituous spirituousness spirochaete spirochaetes spirochetal spirochete spirochetes spirochetoses spirochetosis spirograph spirographic spirographically spirographs spirography spirogyra spirogyras spiroid spirometer spirometers spirometric spirometry spironolactone spironolactones spiroplasma spiroplasmas spirt spirted spirting spirts spirula spirulae spiry spit spital spitals spitball spitballs spite spited spiteful spitefully spitefulness spites spitfire spitfires spithead spiting spits spitsbergen spitted spitter spitters spitting spittle spittlebug spittlebugs spittoon spittoons spitz spitzes spiv spivs splanchnic splanchnology splanchnopleure splanchnopleures splanchnopleuric splash splashboard splashboards splashdown splashdowns splashed splasher splashers splashes splashguard splashguards splashier splashiest splashily splashiness splashing splashy splat splats splatter splattered splattering splatters splay splayed splayfeet splayfoot splayfooted splaying splays spleen spleenful spleens spleenwort spleenworts spleeny splendent splendid splendidly splendidness splendiferous splendiferously splendiferousness splendor splendorous splendors splendrous splenectomies splenectomize splenectomized splenectomizes splenectomizing splenectomy splenetic splenetical splenetically spleneticals splenetics splenial splenic splenii splenius splenomegalies splenomegaly splice spliced splicer splicers splices splicing spliff spline splines splint splinted splinter splintered splintering splinters splintery splinting splints split splits splitter splitters splitting splotch splotched splotches splotchiness splotching splotchy splurge splurged splurges splurging splurgy splutter spluttered splutterer spluttering splutters spluttery spock spode spodumene spodumenes spoil spoilable spoilage spoiled spoiler spoilers spoiling spoils spoilsman spoilsmen spoilsport spoilsports spoilt spokane spoke spoked spoken spokes spokeshave spokeshaves spokesman spokesmanship spokesmen spokespeople spokesperson spokespersons spokeswoman spokeswomen spoking spoleto spoliate spoliated spoliates spoliating spoliation spoliator spoliators spondaic spondee spondees spondylitis spondylitises spondyloses spondylosis sponge sponged sponger spongers sponges spongeware spongier spongiest spongiform spongin sponginess sponging spongins spongioblast spongioblasts spongiocyte spongiocytes spongocoel spongocoels spongy sponson sponsons sponsor sponsored sponsorial sponsoring sponsors sponsorship sponsorships spontaneities spontaneity spontaneous spontaneously spontaneousness spontoon spontoons spoof spoofed spoofery spoofing spoofs spoofy spook spooked spookeries spookery spookier spookiest spookily spookiness spooking spookish spooks spooky spool spooled spooling spoolings spools spoon spoonable spoonbill spoonbills spoondrift spoondrifts spooned spoonerism spoonerisms spooney spoonful spoonfuls spoonier spooniest spooning spoons spoonsful spoony spoor spoored spooring spoors sporaceous sporades sporadic sporadical sporadically sporadicalness sporangia sporangial sporangiophore sporangiophores sporangium spore spored sporeling sporelings spores sporicidal sporicide sporicides sporiferous sporing sporocarp sporocarps sporocyst sporocysts sporocyte sporocytes sporogenesis sporogenic sporogenous sporogonia sporogonic sporogonium sporogonous sporogony sporont sporonts sporophore sporophores sporophyll sporophylls sporophyte sporophytes sporophytic sporoplasm sporoplasms sporopollenin sporopollenins sporotrichoses sporotrichosis sporozoan sporozoans sporozoite sporozoites sporran sporrans sport sported sportfisherman sportfishermen sportfishing sportful sportfully sportfulness sportier sportiest sportif sportily sportiness sporting sportingly sportive sportively sportiveness sports sportscast sportscaster sportscasters sportscasts sportsman sportsmanlike sportsmanly sportsmanship sportsmen sportswear sportswoman sportswomen sportswriter sportswriters sportswriting sporty sporular sporulate sporulated sporulates sporulating sporulation sporulations sporulative spot spotless spotlessly spotlessness spotlight spotlighted spotlighting spotlights spotlit spots spottable spotted spotter spotters spottier spottiest spottily spottiness spotting spotty spousal spousals spouse spoused spouseless spouses spousing spout spouted spouter spouters spouting spoutings spouts sprachgefühl spraddle spraddled spraddles spraddling sprag sprags sprain sprained spraining sprains sprang sprat sprats sprawl sprawled sprawler sprawlers sprawling sprawls spray sprayed sprayer sprayers spraying sprays spread spreadability spreadable spreadably spreader spreaders spreading spreads spreadsheet spreadsheets sprechstimme sprechstimmes spree sprees sprier spriest sprig sprigged sprigger spriggers sprigging spright sprightful sprightfully sprightfulness sprightlier sprightliest sprightliness sprightly sprights sprigs sprigtail sprigtails spring springal springald springalds springals springboard springboards springbok springboks springbuck springbucks springe springer springers springes springfield springform springhalt springhalts springhare springhares springhead springheads springhouse springhouses springier springiest springily springiness springing springlet springlets springlike springs springtail springtails springtide springtides springtime springwater springwood springwoods springy sprinkle sprinkled sprinkler sprinklered sprinklering sprinklers sprinkles sprinkling sprinklings sprint sprinted sprinter sprinters sprinting sprints sprit sprite sprites sprits spritsail spritsails spritz spritzed spritzer spritzers spritzes spritzing sprocket sprockets sprout sprouted sprouting sprouts spruce spruced sprucely spruceness sprucer spruces sprucest sprucier spruciest sprucing sprucy sprue sprues sprung spry spryer spryest spryly spryness spud spudded spudding spuds spumante spume spumed spumes spuming spumone spumones spumoni spumonis spumous spumy spun spunbonded spunk spunkier spunkiest spunkily spunkiness spunky spur spurge spurges spurious spuriously spuriousness spurn spurned spurner spurners spurning spurns spurred spurrey spurreys spurries spurring spurry spurs spurt spurted spurting spurts sputa sputnik sputniks sputter sputtered sputterer sputterers sputtering sputters sputtery sputum spy spyglass spyglasses spying spymaster spymasters squab squabble squabbled squabbler squabblers squabbles squabbling squabs squad squadded squadding squadron squadrons squads squalamine squalene squalenes squalid squalidity squalidly squalidness squall squalled squaller squallers squallier squalliest squalling squalls squally squalor squalors squama squamae squamate squamation squamations squamiform squamosal squamosals squamose squamous squamously squamousness squamule squamules squamulose squander squandered squanderer squanderers squandering squanderingly squanders square squared squarely squareness squarer squarers squares squarest squaretail squaretails squaring squarish squarishly squarishness squarrose squash squashed squasher squashers squashes squashier squashiest squashily squashiness squashing squashy squat squatly squatness squats squatted squatter squatters squattest squattier squattiest squatting squatty squaw squawfish squawfishes squawk squawked squawker squawkers squawkier squawkiest squawkily squawking squawks squawky squawroot squawroots squaws squeak squeaked squeaker squeakers squeakier squeakiest squeakily squeakiness squeaking squeaks squeaky squeal squealed squealer squealers squealing squeals squeamish squeamishly squeamishness squeegee squeegeed squeegeeing squeegees squeezability squeezable squeeze squeezebox squeezeboxes squeezed squeezer squeezers squeezes squeezing squelch squelched squelcher squelchers squelches squelching squelchy squeteague squib squibbed squibbing squibs squid squidded squidding squids squiffed squiffier squiffiest squiffy squiggle squiggled squiggles squiggling squiggly squill squilla squillae squillas squills squinch squinched squinches squinching squinnied squinnies squinny squinnying squint squinted squinter squinting squintingly squints squinty squirarchies squirarchy squire squirearchies squirearchy squired squires squiring squirish squirm squirmed squirmer squirmers squirmier squirmiest squirminess squirming squirms squirmy squirrel squirreled squirrelfish squirrelfishes squirreling squirrelled squirrelling squirrelly squirrels squirt squirted squirter squirters squirting squirts squish squished squishes squishier squishiest squishiness squishing squishy squoosh squooshed squooshes squooshing squush squushed squushes squushing sranan sranantongo srebrenica sri srinagar st stab stabat stabbed stabber stabbers stabbing stabile stabiles stabilities stability stabilization stabilizations stabilize stabilized stabilizer stabilizers stabilizes stabilizing stable stabled stableman stablemate stablemates stablemen stableness stabler stables stablest stabling stablish stablished stablishes stablishing stably stabs staccati staccato staccatos stack stackable stacked stacker stackers stacking stacks stackup stackups stacte stactes staddle staddles stade stades stadholder stadholders stadia stadium stadiums stadtholder stadtholderate stadtholders stadtholdership staff staffed staffer staffers staffing staffordshire staffs stag stage stageable stagecoach stagecoaches stagecraft stagecrafts staged stageful stagefuls stagehand stagehands stagelike stager stagers stages stagestruck stagey stagflation stagflationary staggard staggards stagged stagger staggerbush staggerbushes staggered staggerer staggerers staggering staggeringly staggers staggery stagging staggy staghorn staghound staghounds stagier stagiest stagily staginess staging stagings stagirite stagirites stagnancy stagnant stagnantly stagnate stagnated stagnates stagnating stagnation stagnations stags stagy staid staidly staidness stain stainability stainable stained stainer stainers staining stainless stainlessly stainproof stains stair staircase staircases stairs stairway stairways stairwell stairwells stake staked stakeholder stakeholders stakeout stakeouts stakes stakhanovism stakhanovite stakhanovites staking stalactiform stalactite stalactites stalactitic stalag stalagmite stalagmites stalagmitic stalags stale staled stalely stalemate stalemated stalemates stalemating staleness staler stales stalest stalin staling stalingrad stalinism stalinist stalinists stalinization stalinize stalinized stalinizes stalinizing stalinoid stalk stalked stalker stalkers stalking stalkless stalks stalky stall stalled stallholder stallholders stalling stallion stallions stalls stalwart stalwartly stalwartness stalwarts stamen stamens stamina staminal staminate staminode staminodes staminodia staminodies staminodium staminody stammel stammels stammer stammered stammerer stammerers stammering stammeringly stammers stamp stamped stampede stampeded stampeder stampeders stampedes stampeding stamper stampers stamping stampless stamps stance stances stanch stanched stancher stanchers stanches stanching stanchion stanchioned stanchioning stanchions stanchly stanchness stand standalone standard standardbred standardbreds standardizable standardization standardizations standardize standardized standardizer standardizers standardizes standardizing standardless standardly standards standaway standby standbys standdown standdowns standee standees stander standers standing standings standish standishes standoff standoffish standoffishly standoffishness standoffs standout standouts standpat standpatter standpatters standpattism standpipe standpipes standpoint standpoints stands standstill standstills standup stanford stanhope stanhopes stanine stanines stanislavski stanislavskian stanislavsky stank stanley stannaries stannary stannic stannite stannites stannous stanovoi stanovoy stanza stanzaic stanzas stapedectomies stapedectomy stapedes stapedial stapelia stapelias stapes staph staphs staphylinid staphylinids staphylococcal staphylococci staphylococcic staphylococcus staphyloplastic staphyloplasties staphyloplasty staphyloraphies staphyloraphy staphylorrhaphies staphylorrhaphy staple stapled stapler staplers staples stapling star starboard starboards starburst starbursts starch starched starches starchier starchiest starchily starchiness starching starchy stardom stardoms stardust stare stared starer starers stares starets starfish starfishes starflower starflowers stargaze stargazed stargazer stargazers stargazes stargazing staring stark starker starkers starkest starkly starkness starless starlet starlets starlight starlike starling starlings starlit starred starrier starriest starriness starring starry stars starship starships starstruck start started starter starters starting startle startled startlement startles startling startlingly startlingness starts startsy startup startups starvation starve starved starveling starvelings starves starving starwort starworts stases stash stashed stashes stashing stasis stat statable statant state statecraft stated statedly statehood statehooder statehooders statehouse statehouses stateless statelessness statelet statelets statelier stateliest stateliness stately statement statements staten stater stateroom staterooms staters states stateside statesman statesmanlike statesmanly statesmanship statesmen stateswoman stateswomen statewide static statical statically statice statices staticky statics stating station stational stationaries stationary stationed stationer stationers stationery stationhouse stationhouses stationing stationmaster stationmasters stations statism statist statistic statistical statistically statistician statisticians statistics statists stative statives statoblast statoblasts statocyst statocysts statolith statoliths stator stators statoscope statoscopes stats statuaries statuary statue statues statuesque statuesquely statuette statuettes stature statures status statuses statusy statutable statute statutes statutorily statutory staunch staunched stauncher staunchers staunches staunching staunchly staunchness staurolite staurolites staurolitic stavanger stave staved staves stavesacre stavesacres staving stay stayed stayer stayers staying stays staysail staysails staël stead steaded steadfast steadfastly steadfastness steadied steadier steadiers steadies steadiest steadily steadiness steading steadings steads steady steadying steak steakhouse steakhouses steaks steal stealable stealer stealers stealing steals stealth stealthier stealthiest stealthily stealthiness stealthy steam steamboat steamboats steamed steamer steamers steamfitter steamfitters steamfitting steamier steamiest steamily steaminess steaming steamroll steamrolled steamroller steamrollered steamrollering steamrollers steamrolling steamrolls steams steamship steamships steamy steapsin steapsins stearate stearates stearic stearin stearine stearines stearins stearoptene stearoptenes steatite steatites steatitic steatolysis steatopygia steatopygias steatopygic steatopygous steatorrhea steatorrheas steatorrhoea steatorrhoeas steatoses steatosis stedfast steed steeds steel steele steeled steelhead steelheads steelie steelier steelies steeliest steeliness steeling steelmaker steelmakers steelmaking steels steelwork steelworker steelworkers steelworks steely steelyard steelyards steenbok steenboks steep steeped steepen steepened steepening steepens steeper steepers steepest steeping steepish steeple steeplebush steeplebushes steeplechase steeplechaser steeplechasers steeplechases steeplechasing steepled steeplejack steeplejacks steeples steeply steepness steeps steer steerable steerage steerageway steerageways steered steerer steerers steering steers steersman steersmen steeve steeved steeves steeving steganographic steganography stegodon stegodons stegosaur stegosaurs stegosaurus stegosauruses stein steinbeck steinbok steinboks steins steinway stela stelae stelar stele steles stella stellar stellas stellate stellated stellately stellenbosch steller stelliform stellular stem stemless stemma stemmas stemmata stemmatic stemmed stemmer stemmers stemmier stemmiest stemming stemmy stems stemson stemsons stemware sten stench stenches stenchful stenchy stencil stenciled stenciler stencilers stenciling stencilled stenciller stencillers stencilling stencils stendhal steno stenobath stenobathic stenobaths stenograph stenographer stenographers stenographic stenographical stenographically stenographs stenography stenohaline stenophagous stenos stenosed stenoses stenosis stenotherm stenothermal stenothermic stenothermous stenotherms stenotic stenotopic stenotype stenotyped stenotypes stenotypies stenotyping stenotypist stenotypists stenotypy stentor stentorian stentors step stepbrother stepbrothers stepchild stepchildren stepdaughter stepdaughters stepfamilies stepfamily stepfather stepfathers stephanotis stephanotises stephen stephenson stepladder stepladders steplike stepmother stepmothers stepparent stepparenting stepparents steppe stepped stepper steppers steppes stepping steppingstone steppingstones steps stepsibling stepsiblings stepsister stepsisters stepson stepsons stepwise steradian steradians stercoraceous stercorous sterculia stere stereo stereobate stereobates stereochemical stereochemistry stereochrome stereochromes stereochromic stereochromically stereochromies stereochromy stereogram stereograms stereograph stereographed stereographic stereographical stereographically stereographing stereographs stereography stereoisomer stereoisomeric stereoisomerism stereoisomerisms stereoisomers stereologic stereological stereologically stereologist stereologists stereology stereomicroscope stereomicroscopes stereomicroscopic stereomicroscopically stereomicroscopy stereophonic stereophonically stereophony stereophotographic stereophotography stereopsis stereopticon stereopticons stereoregular stereoregularity stereos stereoscope stereoscopes stereoscopic stereoscopically stereoscopist stereoscopists stereoscopy stereospecific stereospecifically stereospecificity stereotactic stereotactical stereotactically stereotaxic stereotaxical stereotaxically stereotaxies stereotaxis stereotaxises stereotaxy stereotropic stereotropism stereotropisms stereotype stereotyped stereotyper stereotypers stereotypes stereotypic stereotypical stereotypically stereotypies stereotyping stereotypy stereovision stereovisions steres steric sterical sterically sterigma sterigmata sterigmatic sterilant sterilants sterile sterilely sterileness sterility sterilization sterilizations sterilize sterilized sterilizer sterilizers sterilizes sterilizing sterlet sterlets sterling sterlingly sterlingness stern sterna sternal sterner sternest sternforemost sternite sternites sternly sternmost sternness sternoclavicular sternocleidomastoid sternocleidomastoids sternocostal sternpost sternposts sterns sternson sternsons sternum sternums sternutation sternutations sternutator sternutatories sternutators sternutatory sternward sternwards sternway sternways sternwheeler sternwheelers steroid steroidal steroidogenesis steroidogenic steroids sterol sterols sterope steropes stertor stertorous stertorously stertors stet stethoscope stethoscopes stethoscopic stethoscopical stethoscopically stethoscopy stets stetson stetsons stetted stetting stevedore stevedored stevedores stevedoring stevengraph stevengraphs stevensgraph stevensgraphs stew steward stewarded stewardess stewardesses stewarding stewards stewardship stewardships stewartia stewartias stewed stewing stewpan stewpans stewpot stewpots stews stewy sthenia sthenias sthenic stibine stibines stibnite stibnites stich stiches stichic stichometric stichometry stichomythia stichomythias stichomythic stichomythies stichomythy stick stickball stickballer stickballers sticked sticker stickers stickful stickfuls stickhandle stickhandled stickhandler stickhandlers stickhandles stickhandling stickier stickiest stickily stickiness sticking stickle stickleback sticklebacks stickled stickler sticklers stickles sticklike stickling stickman stickmen stickpin stickpins sticks stickseed stickseeds sticktail sticktails sticktight sticktights stickum stickums stickup stickups stickweed stickweeds stickwork sticky stiction stied sties stiff stiffed stiffen stiffened stiffener stiffeners stiffening stiffens stiffer stiffest stiffing stiffish stiffly stiffness stiffs stifle stifled stifler stiflers stifles stifling stiflingly stigma stigmal stigmas stigmasterol stigmasterols stigmata stigmatic stigmatically stigmatics stigmatism stigmatist stigmatists stigmatization stigmatizations stigmatize stigmatized stigmatizer stigmatizers stigmatizes stigmatizing stilbene stilbenes stilbestrol stilbestrols stilbite stilbites stile stiles stiletto stilettoes stilettos still stillbirth stillbirths stillborn stilled stiller stillest stillier stilliest stilliform stilling stillman stillmen stillness stillroom stillrooms stills stillson stillsons stilly stilt stilted stiltedly stiltedness stilting stilton stilts stimulant stimulants stimulate stimulated stimulater stimulaters stimulates stimulating stimulatingly stimulation stimulations stimulative stimulator stimulators stimulatory stimuli stimulus sting stingaree stingarees stinger stingers stingier stingiest stingily stinginess stinging stingingly stingless stingray stingrays stings stingy stink stinkard stinkards stinkaroo stinkaroos stinkball stinkballs stinkbug stinkbugs stinker stinkeroo stinkeroos stinkers stinkhorn stinkhorns stinking stinkingly stinkingness stinko stinkpot stinkpots stinks stinkstone stinkstones stinkweed stinkweeds stinkwood stinkwoods stinky stint stinted stinter stinters stinting stintingly stints stipe stiped stipel stipellate stipels stipend stipendiaries stipendiary stipends stipes stipiform stipitate stipites stipitiform stipple stippled stippler stipplers stipples stippling stipular stipulate stipulated stipulates stipulating stipulation stipulations stipulator stipulators stipulatory stipule stipuled stipules stir stirabout stirabouts stirk stirks stirling stirp stirpes stirps stirred stirrer stirrers stirring stirringly stirrings stirrup stirrups stirs stishovite stishovites stitch stitched stitcher stitchers stitchery stitches stitching stitchwort stitchworts stithies stithy stiver stivers stoa stoae stoas stoat stoats stoccado stoccados stochastic stochastically stock stockade stockaded stockades stockading stockage stockbreeder stockbreeders stockbreeding stockbreedings stockbroker stockbrokerage stockbrokers stockbroking stockcar stockcars stocked stocker stockers stockfish stockfishes stockholder stockholders stockholding stockholdings stockholm stockier stockiest stockily stockiness stockinet stockinets stockinette stockinettes stocking stockinged stockings stockish stockist stockists stockjobber stockjobbers stockjobbery stockjobbing stockkeeper stockkeepers stockless stockman stockmar stockmen stockowner stockowners stockownership stockpile stockpiled stockpiler stockpilers stockpiles stockpiling stockpot stockpots stockroom stockrooms stocks stocktaking stocktakings stocky stockyard stockyards stodgier stodgiest stodgily stodginess stodgy stogie stogies stogy stoic stoical stoically stoicalness stoichiometric stoichiometrically stoichiometry stoicism stoics stoke stoked stokehold stokeholds stokehole stokeholes stoker stokers stokes stoking stole stolen stoles stolid stolider stolidest stolidity stolidly stolidness stollen stollens stolon stolonate stoloniferous stoloniferously stoma stomach stomachache stomachaches stomached stomacher stomachers stomachic stomachically stomachics stomaching stomachs stomachy stomal stomas stomata stomatal stomate stomates stomatic stomatitis stomatitises stomatologic stomatological stomatologist stomatologists stomatology stomatopod stomatopods stomatous stomodaea stomodaeal stomodaeum stomodea stomodeal stomodeum stomp stomped stomper stompers stomping stompingly stomps stone stoneboat stoneboats stonecat stonecats stonechat stonechats stonecrop stonecrops stonecutter stonecutters stonecutting stoned stonefish stonefishes stoneflies stonefly stonehearted stonehenge stonemason stonemasonry stonemasons stoner stoneroller stonerollers stoners stones stonewall stonewalled stonewaller stonewallers stonewalling stonewalls stoneware stonewash stonewashed stonewashes stonewashing stonework stoneworker stoneworkers stonewort stoneworts stoney stonier stoniest stonily stoniness stoning stony stonyhearted stonyheartedly stonyheartedness stood stooge stooged stooges stooging stool stooled stoolie stoolies stooling stools stoop stoopball stoopballs stooped stooper stoopers stooping stoops stop stopcock stopcocks stope stoped stoper stopers stopes stopgap stopgaps stoping stoplight stoplights stopover stopovers stoppable stoppage stoppages stopped stopper stoppered stoppering stoppers stopping stopple stoppled stopples stoppling stops stopwatch stopwatches storable storage storax storaxes store stored storefront storefronts storehouse storehouses storekeeper storekeepers storekeeping storeowner storeowners storer storeroom storerooms storers stores storeship storeships storewide storey storeyed storeys storied stories storing stork storks storksbill storksbills storm stormbound stormed stormier stormiest stormily storminess storming storms stormy story storyboard storyboarded storyboarding storyboards storybook storybooks storying storyteller storytellers storytelling storywriter storywriters stoss stotinka stotinki stound stounds stoup stoups stout stouten stoutened stoutening stoutens stouter stoutest stouthearted stoutheartedly stoutheartedness stoutish stoutly stoutness stouts stove stovepipe stovepipes stover stovers stoves stovetop stovetops stow stowage stowaway stowaways stowed stowing stows strabismal strabismic strabismus strabo strabotomies strabotomy strachey strad straddle straddled straddler straddlers straddles straddling stradivari stradivarius strads strafe strafed strafer strafers strafes strafing straggle straggled straggler stragglers straggles stragglier straggliest straggling straggly straight straightarrow straightaway straightaways straightbred straightedge straightedged straightedges straighten straightened straightener straighteners straightening straightens straighter straightest straightforward straightforwardly straightforwardness straightforwards straightish straightjacket straightjacketed straightjacketing straightjackets straightlaced straightly straightness straights straightway strain strained strainer strainers straining strainometer strainometers strains strait straiten straitened straitening straitens straitjacket straitjacketed straitjacketing straitjackets straitlaced straitlacedly straitlacedness straitly straitness straits strake strakes stramonium stramoniums strand stranded strandedness stranding strandline strandlines strands strange strangely strangeness stranger strangers strangest strangle strangled stranglehold strangleholds strangler stranglers strangles strangling strangulate strangulated strangulates strangulating strangulation strangulations stranguries strangury strap straphang straphanger straphangers straphanging straphangs straphung strapless straplesses strappado strappadoes strapped strapper strappers strapping straps strasbourg strass strasses strata stratagem stratagems stratal strategic strategical strategically strategics strategies strategist strategists strategize strategized strategizes strategizing strategy stratford strath strathclyde straths strathspey strathspeys strati straticulate straticulation straticulations stratification stratificational stratified stratifies stratiform stratify stratifying stratigraphic stratigraphical stratigraphically stratigraphy stratocracies stratocracy stratocratic stratocumuli stratocumulus stratopause stratopauses stratosphere stratospheres stratospheric stratospherically stratovolcano stratovolcanos stratum stratums stratus strauss stravinsky straw strawberries strawberry strawboard strawboards strawflower strawflowers strawhat straws strawworm strawworms strawy stray strayed strayer strayers straying strays streak streaked streaker streakers streakier streakiest streakily streakiness streaking streaks streaky stream streambed streambeds streamed streamer streamers streaming streamlet streamlets streamline streamlined streamliner streamliners streamlines streamlining streams streamside streamsides streamy street streetcar streetcars streeter streeters streetlight streetlights streets streetscape streetscapes streetwalker streetwalkers streetwalking streetwise strength strengthen strengthened strengthener strengtheners strengthening strengthens strengths strenuosity strenuous strenuously strenuousness strep streps streptobacilli streptobacillus streptocarpus streptocarpuses streptococcal streptococci streptococcic streptococcus streptodornase streptodornases streptokinase streptokinases streptolysin streptolysins streptomyces streptomycete streptomycetes streptomycin streptomycins streptonigrin streptonigrins streptothricin streptothricins streptovaricin streptovaricins streptozotocin streptozotocins stresa stress stressed stresses stressful stressfully stressfulness stressing stressless stresslessness stressor stressors stretch stretchability stretchable stretched stretcher stretchers stretches stretchier stretchiest stretchiness stretching stretchy stretta strettas strette stretti stretto strettos streusel streusels strew strewed strewing strewn strews stria striae striata striate striated striates striating striation striations striatum strick stricken strickle strickled strickles strickling stricks strict stricter strictest strictly strictness stricture strictures stridden stride stridence stridency strident stridently strider striders strides striding stridor stridors stridulate stridulated stridulates stridulating stridulation stridulations stridulatory stridulous stridulously strife strifeless strigil strigils strigose strike strikebound strikebreaker strikebreakers strikebreaking strikeout strikeouts strikeover strikeovers striker strikers strikes striking strikingly strikingness strindberg string stringboard stringboards stringcourse stringcourses stringed stringencies stringency stringendo stringent stringently stringer stringers stringhalt stringhalted stringhalts stringier stringiest stringily stringiness stringing stringless stringpiece stringpieces strings stringy stringybark stringybarks strip stripe striped stripeless striper stripers stripes stripfilm stripfilms stripier stripiest striping stripings stripling striplings strippable stripped stripper strippers stripping strips stript striptease stripteaser stripteasers stripteases stripy strive strived striven striver strivers strives striving strivingly strivings strobe strobes strobila strobilaceous strobilae strobilar strobilation strobilations strobile strobiles strobili strobilus stroboscope stroboscopes stroboscopic stroboscopically strobotron strobotrons strode stroganoff stroke stroked stroker strokers strokes stroking stroll strolled stroller strollers strolling strolls stroma stromal stromata stromatic stromatolite stromatolites stromatolitic stromboli strong strongbox strongboxes stronger strongest stronghold strongholds strongish strongly strongman strongmen strongpoint strongpoints strongyl strongyle strongyles strongyloidiasis strongyloidosis strongylosis strongyls strontianite strontianites strontium strop strophanthin strophanthins strophe strophes strophic strophoid strophoids strophuli strophulus stropped stroppier stroppiest stropping stroppy strops stroud strouding strouds strove struck structural structuralism structuralist structuralists structuralization structuralizations structuralize structuralized structuralizes structuralizing structurally structurals structuration structure structured structureless structurelessness structures structuring strudel strudels struggle struggled struggler strugglers struggles struggling strugglingly strum struma strumae strumas strumatic strummed strummer strummers strumming strumose strumous strumpet strumpets strums strung strut struthious struts strutted strutter strutters strutting struttingly strychnine strychninism strychninisms stuart stuarts stub stubbed stubbier stubbiest stubbily stubbiness stubbing stubble stubbled stubbly stubborn stubborner stubbornest stubbornly stubbornness stubbs stubby stubs stucco stuccoed stuccoes stuccoing stuccos stuccowork stuccoworker stuccoworkers stuck stud studbook studbooks studded studding studdingsail studdingsails student students studentship studentships studfish studfishes studhorse studhorses studied studiedly studiedness studier studiers studies studio studios studious studiously studiousness studly studs studwork study studying stuff stuffed stuffer stuffers stuffier stuffiest stuffily stuffiness stuffing stuffless stuffs stuffy stukeley stull stulls stultification stultifications stultified stultifier stultifiers stultifies stultify stultifying stum stumble stumblebum stumblebums stumbled stumbler stumblers stumbles stumbling stumblingly stummed stumming stump stumpage stumped stumper stumpers stumpiness stumping stumps stumpy stums stun stung stunk stunned stunner stunners stunning stunningly stuns stunt stunted stuntedness stunting stuntman stuntmen stunts stuntwoman stuntwomen stupa stupas stupe stupefacient stupefacients stupefaction stupefactions stupefactive stupefactives stupefied stupefier stupefiers stupefies stupefy stupefying stupefyingly stupendous stupendously stupendousness stupes stupid stupider stupidest stupidities stupidity stupidly stupidness stupids stupor stuporous stupors sturdier sturdiest sturdily sturdiness sturdy sturgeon sturgeons sturm stutter stuttered stutterer stutterers stuttering stutteringly stutters stuttgart sty stye styes stygian stying stylar stylate style stylebook stylebooks styled styler stylers styles stylet stylets styli styliform styling stylings stylish stylishly stylishness stylist stylistic stylistically stylistics stylists stylite stylites stylitic stylitism stylization stylizations stylize stylized stylizer stylizers stylizes stylizing stylobate stylobates stylography styloid stylolite stylolites stylopodia stylopodium stylus styluses stymie stymied stymieing stymies stymy stymying stypsis styptic stypticity styptics styrax styraxes styrene styria styrofoam styx suability suable suably suasion suasions suasive suasively suasiveness suave suavely suaveness suaver suavest suavity sub subabdominal subacid subacidly subacidness subacute subacutely subadar subadars subaddress subaddresses subadolescent subadult subadults subaerial subaerially subagencies subagency subagent subagents subahdar subahdars suballocation suballocations subalpine subaltern subalternate subalternation subalternations subalterns subantarctic subapical subapically subaquatic subaqueous subarachnoid subarachnoidal subarctic subarea subareas subarid subassemblies subassembly subatmospheric subatomic subaudible subaudition subauditions subaverage subaxillary subbase subbasement subbasements subbases subbasin subbasins subbass subbasses subbed subbing subbituminous subblock subblocks subbranch subbranches subcabinet subcaliber subcapsular subcarrier subcarriers subcartilaginous subcaste subcastes subcategories subcategorization subcategorizations subcategorize subcategorized subcategorizes subcategorizing subcategory subceiling subceilings subcelestial subcellar subcellars subcellular subcenter subcenters subcentral subcentrally subchannel subchannels subchapter subchapters subchaser subchasers subchief subchiefs subclan subclans subclass subclasses subclassification subclassifications subclassified subclassifies subclassify subclassifying subclavian subclavians subclimactic subclimax subclimaxes subclinical subclinically subcluster subclusters subcode subcodes subcollection subcollections subcollege subcolleges subcollegiate subcolonies subcolony subcommand subcommands subcommission subcommissions subcommittee subcommittees subcommunities subcommunity subcompact subcompacts subcomponent subcomponents subconference subconferences subconscious subconsciously subconsciousness subcontinent subcontinental subcontinents subcontract subcontracted subcontracting subcontractor subcontractors subcontracts subcontraoctave subcontraoctaves subcontraries subcontrary subcool subcooled subcooling subcools subcordate subcoriaceous subcortex subcortical subcortically subcortices subcounties subcounty subcritical subcrustal subcult subcults subcultural subculturally subculture subcultures subcurative subcutaneous subcutaneously subcutis subcutises subdeacon subdeacons subdean subdeans subdeb subdebs subdebutante subdebutantes subdecision subdecisions subdepartment subdepartments subdermal subdermally subdevelopment subdevelopments subdiaconal subdiaconate subdiaconates subdialect subdialects subdirector subdirectories subdirectors subdirectory subdiscipline subdisciplines subdistrict subdistricts subdividable subdivide subdivided subdivider subdividers subdivides subdividing subdivision subdivisional subdivisions subdominant subdominants subduable subduct subducted subducting subduction subductions subducts subdue subdued subduedly subduer subduers subdues subduing subdural subeconomies subeconomy subedit subedited subediting subeditor subeditorial subeditors subedits subemployed subemployment subentries subentry subepidermal subequatorial suberect suberin suberins suberization suberizations suberize suberized suberizes suberizing suberose suberous subexpression subexpressions subfamilies subfamily subfield subfields subfigure subfigures subfile subfiles subfloor subflooring subfloorings subfloors subfolder subfolders subfossil subfossils subframe subframes subfreezing subfusc subfuscs subgenera subgeneration subgenerations subgeneric subgenre subgenres subgenus subglacial subglacially subgoal subgoals subgovernment subgovernments subgrade subgrades subgraph subgraphs subgroup subgroups subgum subgums subharmonic subhead subheading subheadings subheads subhuman subhumans subhumid subindex subindexes subindices subindustries subindustry subinfeud subinfeudate subinfeudated subinfeudates subinfeudating subinfeudation subinfeudations subinfeudatory subinfeuded subinfeuding subinfeuds subinhibitory subinterval subintervals subirrigate subirrigated subirrigates subirrigating subirrigation subirrigations subito subjacency subjacent subjacently subject subjected subjecting subjection subjections subjective subjectively subjectiveness subjectivism subjectivist subjectivistic subjectivists subjectivity subjectivization subjectivizations subjectivize subjectivized subjectivizes subjectivizing subjectless subjects subjoin subjoinder subjoinders subjoined subjoining subjoins subjugate subjugated subjugates subjugating subjugation subjugations subjugator subjugators subjunction subjunctions subjunctive subjunctives subkingdom subkingdoms sublanguage sublanguages sublate sublated sublates sublating sublation sublations sublease subleased subleases subleasing sublet sublethal sublethally sublets subletting sublevel sublevels sublibrarian sublibrarians sublicense sublicensed sublicensee sublicensees sublicenses sublicensing sublieutenant sublieutenants sublimable sublimate sublimated sublimates sublimating sublimation sublimations sublime sublimed sublimely sublimeness sublimer sublimers sublimes subliminal subliminally subliming sublimit sublimities sublimits sublimity subline sublines sublingual sublingually sublinguals subliteracy subliterary subliterate subliterature sublittoral sublot sublots sublunar sublunary subluxation subluxations submachine submanager submanagers submandibular submarginal submarine submarined submariner submariners submarines submarining submarket submarkets submaxilla submaxillae submaxillaries submaxillary submaximal submediant submediants submenu submenus submerge submerged submergence submerges submergibility submergible submerging submerse submersed submerses submersible submersibles submersing submersion submersions submetacentric submetacentrics submicrogram submicron submicroscopic submicroscopically submillimeter subminiature subminiaturization subminiaturizations subminiaturize subminiaturized subminiaturizes subminiaturizing subminimal subminimum subminister subministered subministering subministers submiss submission submissions submissive submissively submissiveness submit submitochondrial submits submittal submittals submitted submitter submitters submitting submontane submucosa submucosal submucosally submucosas submultiple submultiples submunition submunitions subnational subnet subnets subnetwork subnetworks subniche subniches subnormal subnormality subnormally subnormals subnuclear suboceanic suboptimal suboptimization suboptimizations suboptimize suboptimized suboptimizes suboptimizing suboptimum suboptimums suborbicular suborbital suborbitals suborder suborders subordinate subordinated subordinately subordinateness subordinates subordinating subordination subordinations subordinative subordinator subordinators suborganization suborganizations suborn subornation subornations suborned suborner suborners suborning suborns suboxide suboxides subpanel subpanels subpar subparagraph subparagraphs subparallel subpart subparts subperiod subperiods subperiosteal subphase subphases subphyla subphylum subplot subplots subpoena subpoenaed subpoenaing subpoenas subpolar subpopulation subpopulations subpotency subpotent subprimate subprimates subprincipal subprincipals subproblem subproblems subprocess subprocesses subproduct subproducts subprofessional subprofessionals subprogram subprograms subproject subprojects subproletariat subproletariats subrational subregion subregional subregions subreption subreptions subreptitious subreptitiously subring subrings subrogate subrogated subrogates subrogating subrogation subrogations subroutine subroutines subs subsample subsampled subsamples subsampling subsatellite subsatellites subsaturated subsaturation subscale subscales subscapular subscapulars subscience subsciences subscribe subscribed subscriber subscribers subscribes subscribing subscript subscripted subscripting subscription subscriptions subscriptive subscriptively subscripts subsea subsecretaries subsecretary subsection subsections subsector subsectors subsegment subsegments subseizure subsense subsenses subsentence subsentences subsequence subsequences subsequent subsequently subsequentness subsere subseres subseries subserve subserved subserves subservience subserviency subservient subserviently subserving subset subsets subshell subshells subshrub subshrubs subside subsided subsidence subsides subsidiaries subsidiarily subsidiarity subsidiary subsidies subsiding subsidization subsidizations subsidize subsidized subsidizer subsidizers subsidizes subsidizing subsidy subsist subsisted subsistence subsistent subsister subsisters subsisting subsists subsite subsites subskill subskills subsocial subsocieties subsociety subsoil subsoiled subsoiler subsoilers subsoiling subsoils subsolar subsonic subsonically subspace subspaces subspecialist subspecialists subspecialization subspecializations subspecialize subspecialized subspecializes subspecializing subspecialties subspecialty subspecies subspecific substage substages substance substanceless substances substandard substantia substantiae substantial substantiality substantially substantialness substantials substantiate substantiated substantiates substantiating substantiation substantiations substantiative substantival substantivally substantive substantively substantiveness substantives substantivize substantivized substantivizes substantivizing substate substates substation substations substituent substituents substitutability substitutable substitute substituted substitutes substituting substitution substitutional substitutionally substitutionary substitutions substitutive substitutively substrata substrate substrates substrative substratosphere substratospheres substratospheric substratum substratums substructural substructure substructures subsumable subsume subsumed subsumes subsuming subsumption subsumptions subsumptive subsurface subsystem subsystems subtask subtasks subtaxa subtaxon subtaxons subteen subteens subtemperate subtenancy subtenant subtenants subtend subtended subtending subtends subterfuge subterfuges subterminal subterranean subterraneanly subterraneous subterraneously subterrestrial subtest subtests subtext subtexts subtextual subtheme subthemes subtherapeutic subtherapeutically subthreshold subtile subtilely subtileness subtiler subtilest subtilin subtilins subtilisin subtilisins subtility subtilization subtilizations subtilize subtilized subtilizes subtilizing subtilty subtitle subtitled subtitles subtitling subtle subtleness subtler subtlest subtleties subtlety subtly subtonic subtonics subtopic subtopics subtorrid subtotal subtotaled subtotaling subtotalled subtotalling subtotally subtotals subtract subtracted subtracter subtracters subtracting subtraction subtractions subtractive subtracts subtrahend subtrahends subtreasuries subtreasury subtrend subtrends subtribe subtribes subtropic subtropical subtropics subtype subtypes subulate subumbrella subumbrellas subunit subunits suburb suburban suburbanite suburbanites suburbanization suburbanizations suburbanize suburbanized suburbanizes suburbanizing suburbans suburbia suburbs subvarieties subvariety subvassal subvassals subvention subventionary subventions subversion subversionary subversions subversive subversively subversiveness subversives subvert subverted subverter subverters subverting subverts subviral subvirus subviruses subvisible subvisual subvocal subvocalization subvocalizations subvocalize subvocalized subvocalizer subvocalizers subvocalizes subvocalizing subvocally subway subways subworld subworlds subwriter subwriters subzero subzone subzones succedanea succedaneous succedaneum succedaneums succedent succeed succeeded succeeder succeeders succeeding succeeds success successes successful successfully successfulness succession successional successionally successions successive successively successiveness successor successors succi succinate succinates succinct succincter succinctest succinctly succinctness succinic succinyl succinylcholine succinylcholines succinyls succinylsulfathiazole succinylsulfathiazoles succor succorable succored succorer succorers succories succoring succors succory succotash succoth succuba succubae succubi succubus succubuses succulence succulency succulent succulently succulents succumb succumbed succumbing succumbs succus succussatory succussion succussions succès such suchlike suck sucked sucker suckered suckerfish suckerfishes suckering suckers suckfish suckfishes sucking suckle suckled suckler sucklers suckles suckling sucklings sucks sucrase sucrases sucre sucres sucrose suction suctional suctioned suctioning suctions suctorial suctorian suctorians sudan sudanese sudanic sudatoria sudatories sudatorium sudatory sudd sudden suddenly suddenness sudds sudeten sudetenland sudetes sudoriferous sudorific sudorifics sudra sudras suds sudser sudsers sudsier sudsiest sudsless sudsy sue sued suede sueded suedes sueding suer suers sues suet suety suey sueys suez suffer sufferable sufferableness sufferably sufferance suffered sufferer sufferers suffering sufferingly sufferings suffers suffice sufficed sufficer sufficers suffices sufficiencies sufficiency sufficient sufficiently sufficing sufficingly sufficingness suffix suffixal suffixation suffixations suffixed suffixes suffixing suffixion suffixions suffocate suffocated suffocates suffocating suffocatingly suffocation suffocations suffocative suffolk suffragan suffragans suffraganship suffraganships suffrage suffrages suffragette suffragettes suffragettism suffragism suffragist suffragists suffrutescent suffruticose suffuse suffused suffuses suffusing suffusion suffusions suffusive sufi sufic sufis sufism sufistic sugar sugarberries sugarberry sugarbird sugarbirds sugarcane sugarcanes sugarcoat sugarcoated sugarcoating sugarcoats sugared sugarer sugarers sugarhouse sugarhouses sugarier sugariest sugariness sugaring sugarless sugarloaf sugarloaves sugarplum sugarplums sugars sugary suggest suggested suggester suggesters suggestibility suggestible suggesting suggestion suggestions suggestive suggestively suggestiveness suggests sui suicidal suicidally suicide suicided suicides suiciding suicidologist suicidologists suicidology suing suint suints suit suitability suitable suitableness suitably suitcase suitcases suite suited suiter suiters suites suiting suitings suitor suitors suits sukiyaki sukiyakis sukkah sukkot sukkoth sulawesi sulcal sulcate sulci sulcus suleiman sulfa sulfadiazine sulfadiazines sulfanilamide sulfanilamides sulfanilic sulfatase sulfatases sulfate sulfated sulfates sulfathiazole sulfathiazoles sulfating sulfhydryl sulfhydryls sulfide sulfides sulfinpyrazone sulfinpyrazones sulfinyl sulfinyls sulfite sulfites sulfitic sulfonamide sulfonamides sulfonate sulfonated sulfonates sulfonating sulfonation sulfonations sulfone sulfones sulfonic sulfonium sulfoniums sulfonmethane sulfonmethanes sulfonyl sulfonyls sulfonylurea sulfonylureas sulfoxide sulfoxides sulfur sulfurate sulfurated sulfurates sulfurating sulfuration sulfurations sulfured sulfureous sulfuret sulfureted sulfureting sulfurets sulfuretted sulfuretting sulfuric sulfuring sulfurization sulfurizations sulfurize sulfurized sulfurizes sulfurizing sulfurous sulfurously sulfurousness sulfurs sulfury sulfuryl sulfuryls sulk sulked sulkers sulkier sulkies sulkiest sulkily sulkiness sulking sulks sulky sulla sullage sullen sullener sullenest sullenly sullenness sullied sullies sullivan sully sullying sulphur sulphured sulphureous sulphuric sulphuring sulphurous sulphurs sulphury sulpician sulpicians sultan sultana sultanas sultanate sultanates sultaness sultanesses sultanic sultans sultrier sultriest sultrily sultriness sultry sulu sulus sum sumac sumach sumacs sumatra sumatran sumatrans sumba sumbawa sumer sumerian sumerians sumerologist sumerologists sumerology summa summability summable summae summand summands summaries summarily summariness summarizable summarization summarizations summarize summarized summarizer summarizers summarizes summarizing summary summate summated summates summating summation summational summations summative summed summer summercater summercaters summered summerhouse summerhouses summering summerlike summerlong summerly summers summersault summersaulted summersaulting summersaults summerset summersets summersetted summersetting summertime summerwood summery summing summings summit summiteer summiteers summitries summitry summits summon summonable summoned summoner summoners summoning summons summonsed summonses summonsing summum sumo sump sumps sumpter sumpters sumptuary sumptuous sumptuously sumptuousness sums sun sunbaked sunbath sunbathe sunbathed sunbather sunbathers sunbathes sunbathing sunbaths sunbeam sunbeams sunbelt sunbelts sunbird sunbirds sunblind sunblock sunbonnet sunbonnets sunbow sunbows sunburn sunburned sunburning sunburns sunburnt sunburst sunbursts sunchoke sunchokes sundae sundaes sunday sundays sundeck sundecks sunder sunderance sundered sundering sunders sundew sundews sundial sundials sundog sundogs sundown sundowner sundowners sundress sundresses sundries sundrops sundry sunfish sunfishes sunflower sunflowers sung sunglass sunglasses sunglow sunglows sunk sunken sunlamp sunlamps sunless sunlessness sunlight sunlike sunlit sunn sunna sunnah sunned sunni sunnier sunniest sunnily sunniness sunning sunnis sunnism sunnite sunnites sunns sunny sunporch sunporches sunray sunrays sunrise sunrises sunroof sunroofs sunroom sunrooms suns sunscald sunscalds sunscreen sunscreening sunscreens sunseeker sunseekers sunset sunsets sunshade sunshades sunshine sunshiny sunspace sunspaces sunspot sunspots sunstone sunstones sunstroke sunstrokes sunstruck sunsuit sunsuits suntan suntanned suntans sunup sunward sunwards sunwise sup super superable superableness superably superabound superabounded superabounding superabounds superabsorbent superabsorbents superabundance superabundant superabundantly superachiever superachievers superactivities superactivity superadd superadded superadding superaddition superadditions superadds superadministrator superadministrators superagencies superagency superagent superagents superalloy superalloys superaltern superalterns superambitious superannuate superannuated superannuates superannuating superannuation superannuations superathlete superb superbad superball superbank superbillionaire superbitch superblock superblocks superbly superbness superboard superbomb superbomber superbright superbureaucrat supercabinet supercalender supercalendered supercalendering supercalenders supercar supercargo supercargoes supercargos supercarrier supercautious supercenter supercharge supercharged supercharger superchargers supercharges supercharging superchic superchurch superciliary supercilious superciliously superciliousness supercities supercity supercivilization supercivilized superclass superclasses superclean superclub supercluster superclusters supercoil supercoiled supercoiling supercoils supercollider supercolliders supercolossal supercolumnar supercomfortable supercompetitive supercomputer supercomputers supercomputing superconduct superconducted superconducting superconductive superconductivity superconductor superconductors superconducts superconfident superconglomerate superconservative supercontinent supercontinents superconvenient supercool supercooled supercooling supercools supercop supercorporation supercriminal supercritical supercurrent supercurrents supercute superdelegate superdelegates superdeluxe superdiplomat superdominant superdominants superduper supered supereffective superefficiency superefficient superego superegoist superegoists superegos superelevate superelevated superelevates superelevating superelevation superelevations superelite supereminence supereminent supereminently supererogate supererogated supererogates supererogating supererogation supererogations supererogative supererogatory superexcellent superexpensive superexpress superfamilies superfamily superfan superfarm superfast superfatted superfecta superfectas superfecundation superfecundations superfetate superfetated superfetates superfetating superfetation superfetations superficial superficialities superficiality superficially superficialness superficies superfine superfineness superfirm superfix superfixes superflack superfluid superfluidity superfluids superfluities superfluity superfluous superfluously superfluousness superfund supergalactic supergalaxies supergalaxy supergene supergenes supergiant supergiants superglue superglues supergood supergovernment supergraphics supergravity supergroup supergroups supergrowth superharden superheat superheated superheater superheaters superheating superheats superheavy superheavyweight superheavyweights superhelical superhelically superhelices superhelix superhelixes superhero superheroes superheroine superheterodyne superheterodynes superhigh superhighway superhighways superhit superhot superhuman superhumanity superhumanly superhumanness superhype superimposable superimpose superimposed superimposes superimposing superimposition superimpositions superincumbence superincumbency superincumbent superincumbently superindividual superinduce superinduced superinduces superinducing superinduction superinductions superinfect superinfected superinfecting superinfection superinfections superinfects supering superinsulated superintellectual superintelligence superintelligent superintend superintended superintendence superintendences superintendencies superintendency superintendent superintendents superintending superintends superintensity superior superiority superiorly superiors superjacent superjet superjets superjock superjumbo superlarge superlative superlatively superlativeness superlatives superlawyer superlight superlinear superliner superliners superlobbyist superlobbyists superloyalist superloyalists superlunar superlunary superluxurious superluxury supermacho supermagnetic supermajorities supermajority supermale superman supermarket supermarketer supermarketers supermarkets supermasculine supermassive supermen supermicro supermicros supermilitant supermillionaire supermind superminicomputer superminicomputers superminister supermodel supermodels supermodern supermolecule supermolecules supermom supermoms supernal supernally supernatant supernatants supernation supernational supernatural supernaturalism supernaturalist supernaturalistic supernaturalists supernaturally supernaturalness supernaturals supernature supernormal supernormality supernormally supernova supernovae supernovas supernumeraries supernumerary supernutrition superorder superorders superordinate superordinated superordinates superordinating superordination superordinations superorganic superorganism superorganisms superorgasm superovulate superovulated superovulates superovulating superovulation superovulations superoxide superoxides superparasitic superparasitism superparasitisms superpatriot superpatriotic superpatriotism superperson superpersonal superphenomenon superphosphate superphosphates superphysical superpimp superplane superplastic superplasticity superplayer superpolite superport superposable superpose superposed superposes superposing superposition superpower superpowered superpowerful superpowers superpremium superpro superprofit superquality superrace superreal superrealism superrealist superrealistic superrealists superregional superrich superroad superromantic superromanticism supers supersafe supersale supersalesman supersaturate supersaturated supersaturates supersaturating supersaturation supersaturations supersaver supersavers superscale superschool superscout superscribe superscribed superscribes superscribing superscript superscripted superscripting superscription superscripts supersecrecy supersecret supersede supersedeas supersedeases superseded superseder superseders supersedes superseding supersedure supersedures supersell superseller supersensible supersensibly supersensitive supersensitively supersensitivity supersensory superserviceable supersession supersessions superset supersets supersexuality supersharp supershow supersinger supersize supersized supersleuth superslick supersmart supersmooth supersoft supersonic supersonically supersonics supersophisticated superspecial superspecialist superspecialists superspecialization superspecialized superspectacle superspectacular superspeculation superspy superstar superstardom superstars superstate superstates superstation superstations superstimulate superstition superstitions superstitious superstitiously superstitiousness superstock superstore superstores superstrata superstratum superstrength superstrike superstring superstrings superstrong superstructural superstructure superstructures superstud supersubstantial supersubtle supersubtlety supersurgeon supersweet supersymmetric supersymmetry supersystem supersystems supertanker supertankers supertax supertaxes superterrific superthick superthin superthriller supertight supertitle supertitled supertitles supertonic supertonics supervene supervened supervenes supervenient supervening supervention superventions supervirile supervirtuoso supervise supervised supervises supervising supervision supervisions supervisor supervisors supervisory superwave superweapon superwide superwife superwoman superwomen supinate supinated supinates supinating supination supinations supinator supinators supine supinely supineness supped supper suppers suppertime suppertimes supping supplant supplantation supplantations supplanted supplanter supplanters supplanting supplants supple suppled supplejack supplejacks supplely supplement supplemental supplementarity supplementary supplementation supplementations supplemented supplementer supplementers supplementing supplements suppleness suppler supples supplest suppletion suppletions suppletive suppletory suppliance suppliant suppliantly suppliants supplicant supplicants supplicate supplicated supplicates supplicating supplication supplications supplicatory supplied supplier suppliers supplies suppling supply supplying support supportability supportable supportably supported supporter supporters supporting supportive supportively supportiveness supports supposable supposably supposal supposals suppose supposed supposedly supposes supposing supposition suppositional suppositionally suppositions suppositious supposititious supposititiously supposititiousness suppositive suppositively suppositives suppositories suppository suppress suppressant suppressants suppressed suppresser suppressers suppresses suppressibility suppressible suppressing suppression suppressions suppressive suppressiveness suppressor suppressors suppurate suppurated suppurates suppurating suppuration suppurations suppurative supra supracellular supragenic supraglottal supraliminal supramaxilla supramaxillae supramaxillary supramolecular supranational supranationalism supranationalist supranationalists supranationality supraoptic supraorbital suprarational suprarenal suprarenals suprascapular suprasegmental supraventricular supravital supravitally supremacies supremacist supremacists supremacy suprematism suprematist suprematists supreme supremely supremeness supremer supremest supremo supremos suprême sups suquamish suquamishes sura surah surahs sural suras surat surbase surbased surbases surcease surceased surceases surceasing surcharge surcharged surcharges surcharging surcingle surcingled surcingles surcingling surcoat surcoats surculose surd surds sure surefire surefooted surefootedly surefootedness surely sureness surer surest sureties surety suretyship surf surface surfaced surfacer surfacers surfaces surfacing surfactant surfactants surfbird surfbirds surfboard surfboarder surfboarders surfboarding surfboardings surfboards surfboat surfboats surfcaster surfcasters surfcasting surfcastings surfed surfeit surfeited surfeiter surfeiters surfeiting surfeits surfer surfers surficial surfing surfperch surfperches surfs surfside surfy surge surged surgeon surgeonfish surgeonfishes surgeons surgeries surgery surges surgical surgically surgicenter surgicenters surging suribachi suricate suricates surimi surimis surinam suriname surinamer surinamers surinamese surjection surjections surjective surlier surliest surlily surliness surly surmise surmised surmises surmising surmount surmountable surmounted surmounter surmounters surmounting surmounts surmullet surmullets surname surnamed surnames surnaming surpass surpassable surpassed surpasses surpassing surpassingly surplice surplices surplus surplusage surplusages surpluses surprint surprinted surprinting surprints surprisal surprisals surprise surprised surpriser surprisers surprises surprising surprisingly surprize surprized surprizes surprizing surra surreal surrealism surrealist surrealistic surrealistically surrealists surreally surrebuttal surrebuttals surrebutter surrebutters surrejoinder surrejoinders surrender surrendered surrendering surrenders surreptitious surreptitiously surreptitiousness surrey surreys surrogacies surrogacy surrogate surrogated surrogates surrogating surround surrounded surrounding surroundings surrounds surroyal surroyals surtax surtaxed surtaxes surtaxing surtitle surtitles surtout surtouts surveil surveillance surveillant surveillants surveilled surveilling surveils survey surveyed surveying surveyor surveyors surveys survivability survivable survival survivalist survivalists survivals survivance survive survived survives surviving survivor survivors survivorship susan susanna susceptance susceptances susceptibilities susceptibility susceptible susceptibleness susceptibly susceptive susceptiveness susceptivity sushi susiana suslik susliks suspect suspected suspecting suspects suspend suspended suspender suspendered suspenders suspending suspends suspense suspenseful suspensefully suspensefulness suspenseless suspenser suspensers suspension suspensions suspensive suspensively suspensiveness suspensor suspensories suspensors suspensory suspicion suspicional suspicioned suspicioning suspicions suspicious suspiciously suspiciousness suspiration suspirations suspire suspired suspires suspiring susquehanna susquehannas susquehannock susquehannocks suss sussed susses sussex sussing sustain sustainability sustainable sustainably sustained sustainedly sustainer sustainers sustaining sustainment sustainments sustains sustenance sustentacular sustentation sustentations sustentative susu susurrant susurration susurrations susurrous susurrus susurruses susus sutler sutlers sutra sutras suttee suttees sutural suturally suture sutured sutures suturing suzerain suzerains suzerainties suzerainty suzette suzettes suède svalbard svedberg svedbergs svelte sveltely svelteness svelter sveltest svengali svengalis sverdlovsk sverdrup sw swab swabbed swabber swabbers swabbie swabbies swabbing swabby swabia swabian swabians swabs swaddle swaddled swaddles swaddling swag swage swaged swages swagged swagger swaggered swaggerer swaggerers swaggering swaggeringly swaggers swagging swaging swagman swagmen swags swahili swahilian swahilis swain swainish swainishness swains swainson swale swales swallow swallowable swallowed swallower swallowers swallowing swallows swallowtail swallowtails swallowwort swallowworts swam swami swamis swamp swamped swamper swampers swampier swampiest swampiness swamping swampland swamplands swamps swampy swan swank swanked swanker swankest swankier swankiest swankily swankiness swanking swanks swanky swanlike swanned swanneries swannery swanning swans swansdown swanskin swanskins swap swappable swapped swapper swappers swapping swaps swaraj swarajist swarajists sward swarded swards swarf swarfs swarm swarmed swarmer swarmers swarming swarms swart swarth swarthier swarthiest swarthily swarthiness swarths swarthy swartness swash swashbuckle swashbuckled swashbuckler swashbucklers swashbuckles swashbuckling swashed swasher swashers swashes swashing swastika swastikas swat swatch swatches swath swathe swathed swather swathers swathes swathing swaths swats swatted swatter swatters swatting sway swayback swaybacked swaybacks swayed swayer swayers swaying swayingly sways swazi swaziland swazis swear swearer swearers swearing swears swearword swearwords sweat sweatband sweatbands sweatbox sweatboxes sweated sweater sweaterdress sweaterdresses sweaters sweathouse sweathouses sweatier sweatiest sweatily sweatiness sweating sweatpants sweats sweatshirt sweatshirts sweatshop sweatshops sweaty swede sweden swedenborg swedenborgian swedenborgianism swedenborgians swedes swedish sweep sweepback sweepbacks sweeper sweepers sweepier sweepiest sweeping sweepingly sweepingness sweepings sweeps sweepstake sweepstakes sweepy sweet sweetbread sweetbreads sweetbriar sweetbriars sweetbrier sweetbriers sweeten sweetened sweetener sweeteners sweetening sweetenings sweetens sweeter sweetest sweetheart sweethearts sweetie sweeties sweeting sweetings sweetish sweetishly sweetly sweetmeat sweetmeats sweetness sweets sweetshop sweetshops sweetsop sweetsops swell swelled sweller swellest swellfish swellfishes swellhead swellheaded swellheadedness swellheads swelling swellings swells swelter sweltered sweltering swelteringly swelters sweltrier sweltriest sweltry swept sweptback sweptwing sweptwings swerve swerved swerves swerving swidden swiddens swift swifter swiftest swiftlet swiftlets swiftly swiftness swifts swig swigged swigger swiggers swigging swigs swill swilled swiller swillers swilling swills swim swimmable swimmer swimmeret swimmerets swimmers swimmier swimmiest swimmily swimming swimmingly swimmy swims swimsuit swimsuits swimwear swindle swindled swindler swindlers swindles swindling swine swineherd swineherds swinepox swinepoxes swing swinge swinged swingeing swinger swingers swinges swingier swingiest swinging swingingly swingletree swingletrees swingman swingmen swings swingy swinish swinishly swinishness swipe swiped swipes swiping swirl swirled swirlier swirliest swirling swirlingly swirls swirly swish swished swisher swishers swishes swishier swishiest swishing swishingly swishy swiss swissair switch switchable switchback switchbacks switchblade switchblades switchboard switchboards switched switcher switcheroo switcheroos switchers switches switchgrass switching switchman switchmen switchover switchovers switchyard switchyards switzer switzerland switzers swivel swiveled swiveling swivelled swivelling swivels swivet swivets swizzle swizzled swizzler swizzlers swizzles swizzling swob swobbed swobbing swobs swollen swoon swooned swooner swooners swooning swooningly swoons swoop swooped swooper swoopers swooping swoops swoosh swooshed swooshes swooshing swop swopped swopping swops sword swordbill swordbills swordfish swordfishes swordlike swordplay swordplayer swordplayers swords swordsman swordsmanship swordsmen swordtail swordtails swore sworn swum swung sybarite sybarites sybaritic sybaritically sybaritism sycamine sycamines sycamore sycamores syce sycee sycees syces sycomore sycomores syconia syconium sycophancies sycophancy sycophant sycophantic sycophantical sycophantically sycophantish sycophantishly sycophantism sycophantly sycophants sycosis sydenham sydney syenite syenites syenitic syli sylis syllabaries syllabary syllabi syllabic syllabically syllabicate syllabicated syllabicates syllabicating syllabication syllabications syllabicity syllabics syllabification syllabifications syllabified syllabifies syllabify syllabifying syllabism syllabisms syllabize syllabized syllabizes syllabizing syllable syllabled syllables syllabling syllabub syllabubs syllabus syllabuses syllepses syllepsis sylleptic syllogism syllogisms syllogist syllogistic syllogistical syllogistically syllogistics syllogists syllogization syllogizations syllogize syllogized syllogizer syllogizers syllogizes syllogizing sylph sylphid sylphids sylphlike sylphs sylva sylvan sylvanite sylvanites sylvanus sylvatic sylviculture sylvine sylvines sylvinite sylvinites sylvite sylvites symbiont symbiontic symbionts symbioses symbiosis symbiote symbiotes symbiotic symbiotical symbiotically symbol symboled symbolic symbolical symbolically symbolicalness symboling symbolism symbolist symbolistic symbolistically symbolists symbolization symbolizations symbolize symbolized symbolizer symbolizers symbolizes symbolizing symbology symbols symmetallism symmetric symmetrical symmetrically symmetricalness symmetries symmetrization symmetrizations symmetrize symmetrized symmetrizes symmetrizing symmetry sympathectomies sympathectomized sympathectomy sympathetic sympathetically sympathies sympathin sympathins sympathize sympathized sympathizer sympathizers sympathizes sympathizing sympathizingly sympatholytic sympathomimetic sympathomimetics sympathy sympatric sympatrically sympatries sympatry sympetalous sympetaly symphonic symphonically symphonies symphonious symphoniously symphonist symphonists symphony symphyseal symphyses symphysial symphysis sympodia sympodial sympodially sympodium symposia symposiac symposiacs symposiarch symposiarchs symposiast symposiasts symposium symposiums symptom symptomatic symptomatically symptomatize symptomatized symptomatizes symptomatizing symptomatologic symptomatological symptomatologically symptomatology symptomize symptomized symptomizes symptomizing symptomless symptoms synaeresis synaesthesia synaesthesias synaesthesis synagog synagogal synagogical synagogs synagogue synagogues synalepha synalephas synaloepha synaloephas synapse synapsed synapses synapsid synapsing synapsis synaptic synaptically synaptinemal synaptonemal synaptosomal synaptosome synaptosomes synarthrodia synarthrodiae synarthrodial synarthrodially synarthroses synarthrosis sync syncarp syncarpous syncarps syncarpy syncategorematic syncategorematically synced synch synched synching synchondroses synchondrosis synchro synchrocyclotron synchrocyclotrons synchroflash synchroflashes synchromesh synchromeshes synchronal synchroneity synchronic synchronical synchronically synchronicities synchronicity synchronies synchronism synchronistic synchronistical synchronistically synchronization synchronizations synchronize synchronized synchronizer synchronizers synchronizes synchronizing synchronous synchronously synchronousness synchrony synchros synchroscope synchroscopes synchrotron synchrotrons synchs syncing synclinal syncline synclines syncopal syncopate syncopated syncopates syncopating syncopation syncopations syncopative syncopator syncopators syncope syncopes syncopic syncretic syncretism syncretist syncretistic syncretists syncretize syncretized syncretizes syncretizing syncs syncytia syncytial syncytium syndactyl syndactylism syndactylous syndactyls syndactyly syndesmoses syndesmosis syndesmotic syndetic syndetically syndic syndical syndicalism syndicalist syndicalistic syndicalists syndicate syndicated syndicates syndicating syndication syndications syndicator syndicators syndics syndrome syndromes syndromic syne synecdoche synecdoches synecdochic synecdochical synecdochically synecologic synecological synecology synereses syneresis synergetic synergic synergically synergid synergids synergies synergism synergist synergistic synergistically synergists synergy synesis synesthesia synesthesias synesthete synesthetes synesthetic synfuel synfuels syngamic syngamies syngamous syngamy syngas syngases syngeneic syngeneically syngenesis syngenetic synizeses synizesis synkaryon synkaryonic synkaryons synkineses synkinesis synkinetic synod synodal synodic synodical synodically synods synonym synonymic synonymical synonymies synonymist synonymists synonymity synonymize synonymized synonymizes synonymizing synonymous synonymously synonyms synonymy synopses synopsis synopsize synopsized synopsizes synopsizing synoptic synoptical synoptically synostoses synostosis synostotic synovia synovial synovias synovitis synovitises synsepalous syntactic syntactical syntactically syntactics syntagma syntagmas syntagmata syntagmatic syntax syntaxes syntenic syntenies synteny synth syntheses synthesis synthesist synthesists synthesize synthesized synthesizer synthesizers synthesizes synthesizing synthetase synthetases synthetic synthetically synthetics synths syntonic syntrophies syntrophism syntrophisms syntrophy sypher syphered syphering syphers syphilis syphilitic syphilitics syphiloid syphon syphoned syphoning syphons syracusan syracuse syrette syria syriac syrian syrians syringa syringas syringe syringeal syringed syringes syringing syringomyelia syringomyelias syringomyelic syrinx syrinxes syros syrphid syrphids syrphus syrup syrups syrupy sysop sysops syssarcoses syssarcosis systaltic system systematic systematical systematically systematicness systematics systematism systematist systematists systematization systematizations systematize systematized systematizer systematizers systematizes systematizing systemic systemically systemization systemizations systemize systemized systemizer systemizers systemizes systemizing systemless systems systole systoles systolic syzygial syzygies syzygy szechuan szechwan sào são séance séances sémillon sémillons sérac sèvres síros sûreté süleyman t t'other taal tab tabanid tabanids tabard tabards tabaret tabarets tabasco tabbed tabbies tabbing tabbouleh tabby tabernacle tabernacled tabernacles tabernacling tabernacular tabes tabescence tabescent tabetic tabi tabis tabla tablas tablature tablatures table tableau tableaus tableaux tablecloth tablecloths tabled tableful tablefuls tableland tablelands tablemat tablemate tablemates tablemats tables tableside tablesides tablespoon tablespoonful tablespoonfuls tablespoons tablespoonsful tablet tableted tableting tabletop tabletops tablets tableware tabling tabloid tabloids taboo tabooed tabooing tabooli taboos tabor taborer taborers taboret taborets tabors tabouli tabour tabourer tabourers tabouret tabourets tabours tabriz tabs tabu tabued tabuing tabula tabulae tabular tabularization tabularizations tabularize tabularized tabularizes tabularizing tabularly tabulate tabulated tabulates tabulating tabulation tabulations tabulator tabulators tabun tabuns tabus tac tacamahac tacamahacs tacan tacet tach tachina tachinid tachinids tachism tachisme tachist tachiste tachistes tachistoscope tachistoscopes tachistoscopic tachistoscopically tachists tachograph tachographs tachometer tachometers tachometric tachometry tachyarrhythmia tachyarrhythmias tachycardia tachycardiac tachycardiacs tachycardias tachygraphy tachylite tachylites tachylyte tachylytes tachylytic tachymeter tachymeters tachymetry tachyon tachyonic tachyons tachyphylaxes tachyphylaxis tachypnea tachypneas tachysterol tachysterols tacit tacitly tacitness taciturn taciturnity taciturnly tacitus tack tackboard tackboards tacked tacker tackers tackier tackies tackiest tackified tackifier tackifiers tackifies tackify tackifying tackily tackiness tacking tackle tackled tackler tacklers tackles tackless tackling tacks tacky taco tacoma taconite taconites tacos tact tactful tactfully tactfulness tactic tactical tactically tactician tacticians tactics tactile tactilely tactility taction tactions tactless tactlessly tactlessness tactoreceptor tactoreceptors tactual tactually tad tadema tadjik tadjiks tadpole tadpoles tads tadzhik tadzhiki tadzhikistan tadzhiks tael taels taenia taeniacide taeniacides taeniae taeniafuge taeniafuges taenias taeniasis taeniasises taffeta taffetas taffetized taffia taffias taffies taffrail taffrails taffy tafia tafias tag tagalog tagalogs tagalong tagalongs tagboard tagboards tagged tagger taggers tagging taggle tagliatelle tagline taglines tagma tagmata tagore tagrag tags tagus tahini tahiti tahitian tahitians tahoe tahr tahrs tahseeldar tahseeldars tahsil tahsildar tahsildars tai taiga taigas tail tailback tailbacks tailboard tailboards tailbone tailbones tailcoat tailcoated tailcoats tailed tailender tailenders tailer tailers tailfin tailfins tailgate tailgated tailgater tailgaters tailgates tailgating tailing tailings taille tailles tailless taillight taillights taillike tailor tailorbird tailorbirds tailored tailoring tailors tailpiece tailpieces tailpipe tailpipes tailplane tailplanes tailrace tailraces tails tailskid tailskids tailslide tailslides tailspin tailspins tailstock tailstocks tailwater tailwind tailwinds tain taino tainos tains taint tainted tainting taintless taintlessly taintlessness taints taipan taipans taipeh taipei tais taiwan taiwanese taj tajik tajiki tajikistan tajiks tajs taka takable takahe takahes takas take takeaway takeaways takedown takedowns taken takeoff takeoffs takeout takeouts takeover takeovers taker takers takes takin taking takings takins takkakaw taklamakan taklimakan tala talapoin talapoins talaria talas talaud talaur talbot talc talced talcing talcked talcking talcky talcose talcous talcs talcum tale talebearer talebearers talebearing talent talented talentless talentlessness talents taler talers tales talesman talesmen taleteller taletellers taletelling tali talion talions taliped talipeds talipes talipot talipots talisman talismanic talismanical talismanically talismans talk talkathon talkathons talkative talkatively talkativeness talkback talkbacks talked talker talkers talkfest talkfests talkie talkier talkies talkiest talkiness talking talks talky tall tallage tallaged tallages tallaging tallahassee tallboy tallboys taller tallest talleyrand tallgrass tallied tallies tallis tallish tallisim tallith tallithim talliths tallness tallow tallowed tallowing tallows tallowy tally tallyho tallyhoed tallyhoing tallyhos tallying tallyman tallymen talmi talmud talmudic talmudical talmudism talmudist talmudists talon taloned talons talus taluses tam tamable tamale tamales tamandua tamanduas tamarack tamaracks tamarao tamaraos tamarau tamaraus tamari tamarillo tamarillos tamarin tamarind tamarinds tamarins tamarisk tamarisks tambac tambacs tambak tambaks tambala tambalas tambour tamboura tambouras tamboured tambourer tambourers tambourin tambourine tambourines tambouring tambourins tambours tambura tamburas tamburitza tamburitzas tamburlaine tame tameable tamed tameless tamely tameness tamer tamerlane tamers tames tamest tamil tamils taming tammany tammanyism tammuz tammy tamora tamoxifen tamp tampa tamped tamper tampered tamperer tamperers tampering tamperproof tampers tamping tampion tampions tampon tamponed tamponing tampons tamps tams tamworth tan tanager tanagers tanagrine tanbark tanbarks tanbur tanburs tancred tandem tandems tandoor tandoori tandoors tang tanganyika tanganyikan tanganyikans tanged tangelo tangelos tangence tangency tangent tangental tangential tangentiality tangentially tangents tangerine tangerines tangibility tangible tangibleness tangibles tangibly tangier tangiest tanginess tanging tangle tangled tanglement tangles tangling tangly tango tangoed tangoing tangolike tangoreceptor tangoreceptors tangos tangram tangrams tangs tangy tanimbar tanist tanistry tanists tank tanka tankage tankages tankard tankards tankas tanked tanker tankers tankful tankfuls tanking tankless tanklike tanks tannage tannate tannates tanned tanner tanneries tanners tannery tannest tannhäuser tannic tanniferous tannin tanning tannings tannins tannish tanoak tanoaks tanoan tanrec tanrecs tans tansies tansy tantalate tantalic tantalite tantalites tantalization tantalizations tantalize tantalized tantalizer tantalizers tantalizes tantalizing tantalizingly tantalum tantalums tantalus tantaluses tantamount tantara tantaras tantivies tantivy tantra tantras tantric tantrism tantrist tantrists tantrum tantrums tanuki tanyard tanyards tanzania tanzanian tanzanians tanzanite tanzanites tao taoiseach taoism taoist taoistic taoists taormina taos tap tapa tapas tape tapeable taped tapeless tapeline tapelines taper tapered taperer taperers tapering taperingly tapers taperstick tapersticks tapes tapestried tapestries tapestry tapestrying tapeta tapetal tapetum tapeworm tapeworms taphole tapholes taphonomic taphonomist taphonomists taphonomy taping tapings tapioca tapiocas tapir tapirs tapis tapped tapper tappers tappet tappets tapping tappings taproom taprooms taproot taproots taps tapster tapsters tapénade tar taradiddle taradiddles tarahumara tarahumaras taramasalata taramasalatas taramosalata taramosalatas tarantella tarantellas tarantism tarantisms taranto tarantula tarantulae tarantulas tarascan tarascans tarawa tarboosh tarbooshes tarbush tarbushes tardenois tardenoisean tardier tardiest tardigrade tardigrades tardily tardiness tardive tardo tardy tare tared tarentum tares targe targes target targetable targeted targeting targets targum targums tarheel tarheels tariff tariffed tariffing tariffs taring tarlatan tarlatans tarletan tarletans tarmac tarmacadam tarmacadams tarmacked tarmacking tarmacs tarn tarnal tarnally tarnation tarnations tarnish tarnishable tarnished tarnishes tarnishing tarns taro taroc tarocs tarok taroks taros tarot tarots tarp tarpaper tarpapered tarpapers tarpaulin tarpaulins tarpon tarpons tarps tarquin tarquins tarradiddle tarradiddles tarragon tarragona tarre tarred tarres tarriance tarriances tarried tarrier tarriers tarries tarriest tarring tarry tarrying tars tarsal tarsi tarsier tarsiers tarsometatarsal tarsometatarsi tarsometatarsus tarsus tart tartan tartans tartar tartare tartarean tartareous tartarian tartaric tartarization tartarizations tartarize tartarized tartarizes tartarizing tartarous tartars tartarus tartary tarter tartest tartier tartiest tartily tartine tartines tartiness tartish tartlet tartlets tartly tartness tartrate tartrated tartrates tarts tartufe tartufes tartuffe tartuffery tartuffes tarty tarvia tarweed tarweeds tarzan tarzans tashkent task tasked tasking taskmaster taskmasters taskmistress taskmistresses tasks tasman tasmania tasmanian tasmanians tass tasse tassel tasseled tasseling tasselled tasselling tassels tasses tasset tassets tasso tastable taste tasted tasteful tastefully tastefulness tasteless tastelessly tastelessness tastemaker tastemakers taster tasters tastes tastier tastiest tastily tastiness tasting tastings tasty tat tatami tatamis tatar tatars tatary tater taters tats tatted tatter tatterdemalion tatterdemalions tattered tattering tatters tattersall tattersalls tattier tattiest tattiness tatting tattle tattled tattler tattlers tattles tattletale tattletales tattling tattlingly tattoo tattooed tattooer tattooers tattooing tattooist tattooists tattoos tatty tau taught taunt taunted taunter taunters taunting tauntingly taunts taupe taurean taureans taurine taurines taurocholic taurus tausug taut tautaug tautaugs tauten tautened tautening tautens tauter tautest tautly tautness tautog tautogs tautologic tautological tautologically tautologies tautologist tautologists tautologize tautologized tautologizes tautologizing tautologous tautologously tautology tautomer tautomeric tautomerism tautomerisms tautomers tautonym tautonymic tautonymous tautonyms tautonymy tav tavern taverna tavernas taverner taverners taverns taw tawdrier tawdriest tawdrily tawdriness tawdry tawed tawer tawers tawing tawnier tawnies tawniest tawniness tawny taws tawse tax taxa taxability taxable taxableness taxables taxably taxation taxed taxeme taxemes taxemic taxer taxers taxes taxi taxicab taxicabs taxidermal taxidermic taxidermist taxidermists taxidermy taxied taxies taxiing taximan taximen taximeter taximeters taximetrics taxing taxingly taxis taxiway taxiways taxman taxmen taxon taxonomic taxonomical taxonomically taxonomies taxonomist taxonomists taxonomy taxons taxpayer taxpayers taxpaying taxus taxying taygeta taylor tayra tayras tayside tazza tazzas tbilisi tchaikovskian tchaikovsky tchaikovskyan tchotchke tchotchkes te tea teabag teabags teaberry teacake teacakes teacart teacarts teach teachability teachable teachableness teachably teacher teacherly teachers teaches teaching teachings teacup teacupful teacupfuls teacups teahouse teahouses teak teakettle teakettles teaks teakwood teal tealike teals team teamed teaming teammate teammates teams teamster teamsters teamwork teapot teapots teapoy teapoys tear tearable tearaway tearaways teardown teardowns teardrop teardrops teared tearer tearers tearful tearfully tearfulness teargas teargases teargassed teargasses teargassing tearier teariest tearily teariness tearing tearjerker tearjerkers tearless tearlessly tearoom tearooms tears tearstain tearstained tearstains teary teas tease teased teasel teaseled teaseling teaselled teaselling teasels teaser teasers teases teashop teashops teasing teasingly teaspoon teaspoonful teaspoonfuls teaspoons teaspoonsful teat teated teatime teatimes teats tebet tebeth tech teched techie techies technetium technetronic technic technical technicalities technicality technicalization technicalizations technicalize technicalized technicalizes technicalizing technically technicalness technicals technician technicians technicolor technics technique techniques technobabble technocracies technocracy technocrat technocratic technocrats technologic technological technologically technologies technologist technologists technologize technologized technologizes technologizing technology technophile technophiles technophobe technophobes technophobia technophobic technostructure technostructures techy tecta tectal tectonic tectonically tectonics tectonism tectonisms tectrices tectrix tectum ted tedded tedder tedders teddies tedding teddy tedious tediously tediousness tedium teds tee teed teeing teem teemed teemer teemers teeming teemingly teemingness teems teen teenage teenaged teenager teenagers teener teeners teenier teeniest teens teensier teensiest teensy teeny teenybop teenybopper teenyboppers teeoff teeoffs teepee teepees tees teeter teeterboard teeterboards teetered teetering teeters teeth teethe teethed teether teethers teethes teething teethridge teethridges teetotal teetotaler teetotalers teetotalism teetotalist teetotalists teetotaller teetotallers teetotally teetotum teetotums teff tefillin teflon teg tegg teggs tegmen tegmental tegmentum tegmentums tegmina tegs tegu tegua teguas tegucigalpa tegular tegularly tegulated tegument tegumental tegumentary teguments tegus tehachapi teheran tehran tehuantepec tehuelche tehuelchean tehuelches teiglach teiid teiids tekkie tekkies tektite tektites tektitic tektronix tel telaesthesia telaesthesias telamon telamones telangiectases telangiectasia telangiectasias telangiectasis telangiectatic telecamera telecameras telecast telecasted telecaster telecasters telecasting telecasts telecom telecommunicate telecommunicated telecommunicates telecommunicating telecommunication telecommunications telecommunicator telecommunicators telecommute telecommuted telecommuter telecommuters telecommutes telecommuting telecoms teleconference teleconferenced teleconferences teleconferencing telecopier telecourse telecourses teledrama teledramas teledu teledus telefacsimile telefacsimiles telefilm telefilms telegenic telegenically telegonic telegonous telegony telegram telegrammed telegramming telegrams telegraph telegraphed telegrapher telegraphers telegraphese telegraphic telegraphical telegraphically telegraphing telegraphist telegraphists telegraphs telegraphy telegu telegus telekinesis telekinetic telekinetically telemachus telemark telemarked telemarker telemarkers telemarketer telemarketers telemarketing telemarking telemarks telemedicine telemeter telemetered telemetering telemeters telemetric telemetrical telemetrically telemetry telencephalic telencephalon telencephalons teleologic teleological teleologically teleologies teleologist teleologists teleology teleonomic teleonomy teleost teleostean teleosteans teleosts telepath telepathic telepathically telepathist telepathists telepaths telepathy telephone telephoned telephoner telephoners telephones telephonic telephonically telephoning telephonist telephonists telephony telephoto telephotograph telephotographed telephotographic telephotographing telephotographs telephotography telephotos teleplay teleplays teleport teleportation teleported teleporting teleports teleprinter teleprinters teleprocessing teleprompter teleprompters teleran telerans telescope telescoped telescopes telescopic telescopically telescoping telescopist telescopists telescopium telescopy teleses teleshopping teleshoppings telesis telestereoscope telestereoscopes telesthesia telesthesias telesthetic telesto teletext teletexts teletheater teletheaters telethermoscope telethermoscopes telethon telethons teletranscription teletranscriptions teletype teletyped teletypes teletypesetter teletypewriter teletypewriters teletyping teleutospore teleutospores teleutosporic televangelism televangelist televangelists teleview televiewed televiewer televiewers televiewing televiews televise televised televises televising television televisions televisor televisors televisual telex telexed telexes telexing telford telia telial telic telically teliospore teliospores teliosporic telium tell tellable teller tellers tellership tellies telling tellingly tells telltale telltales tellurian tellurians telluric telluride tellurion tellurions tellurium tellurometer tellurometers tellurous telly tellys telnet telocentric telolecithal telome telomere telomeres telophase telophases telophasic telos telotaxis telotaxises telpher telphered telphering telphers telson telsons telugu telugus tem temblor temblors temerarious temerariously temerariousness temerity temne temnes temp tempeh tempehs temper tempera temperability temperable temperament temperamental temperamentally temperaments temperance temperas temperate temperately temperateness temperature temperatures tempered temperedly temperedness temperer temperers tempering tempers tempest tempested tempesting tempests tempestuous tempestuously tempestuousness tempi templar templars template templates temple templed temples templet templets tempo temporal temporalities temporality temporalize temporalized temporalizes temporalizing temporally temporaries temporarily temporariness temporary tempore temporization temporizations temporize temporized temporizer temporizers temporizes temporizing temporomandibular tempos temps tempt temptable temptation temptations tempted tempter tempters tempting temptingly temptingness temptress temptresses tempts tempura tempuras ten tenability tenable tenableness tenably tenace tenaces tenacious tenaciously tenaciousness tenacity tenacula tenaculum tenancies tenancy tenant tenantable tenanted tenanting tenantless tenantry tenants tench tenches tend tendance tended tendencies tendencious tendency tendentious tendentiously tendentiousness tender tendered tenderer tenderers tenderest tenderfeet tenderfoot tenderfoots tenderhearted tenderheartedly tenderheartedness tendering tenderization tenderizations tenderize tenderized tenderizer tenderizers tenderizes tenderizing tenderloin tenderloins tenderly tenderness tendernesses tenderometer tenderometers tenders tending tendinitis tendinous tendon tendonitis tendons tendresse tendril tendriled tendrilled tendrilous tendrils tends tenebrae tenebrific tenebrionid tenebrionids tenebrious tenebrism tenebrist tenebrists tenebrosity tenebrous tenebrously tenement tenemental tenementary tenements tenens tenerife tenesmus tenesmuses tenet tenets tenfold tenia teniacide teniacides teniae teniafuge teniafuges tenias teniasis teniasises tenner tenners tennessean tennesseans tennessee tenniel tennies tennis tennist tennists tennyson tennysonian tenochtitlán tenon tenoned tenoning tenonitis tenons tenor tenorist tenorists tenorrhaphies tenorrhaphy tenors tenos tenosynovitis tenosynovitises tenotomies tenotomy tenpenny tenpin tenpins tenpounder tenpounders tenrec tenrecs tens tense tensed tensely tenseness tenser tenses tensest tensile tensility tensimeter tensimeters tensing tensiometer tensiometers tensiometric tensiometry tension tensional tensioned tensioner tensioners tensioning tensionless tensions tensities tensity tensive tensor tensorial tensors tent tentacle tentacled tentacles tentacular tentage tentages tentative tentatively tentativeness tented tenter tentered tenterhook tenterhooks tentering tenters tenth tenthly tenths tenting tentless tentlike tentmaker tentmakers tents tenues tenuis tenuity tenuous tenuously tenuousness tenurable tenure tenured tenures tenurial tenurially tenuto teocalli teocallis teosinte teosintes teotihuacán tepa tepal tepals tepary tepas tepee tepees tephra tephras tepid tepidity tepidly tepidness tequila tequilas teraampere teraamperes terabecquerel terabecquerels terabit terabits terabyte terabytes teracandela teracandelas teracoulomb teracoulombs terafarad terafarads teraflop teraflops teragram teragrams terahenries terahenry terahenrys terahertz terai terais terajoule terajoules terakelvin terakelvins teralumen teralumens teralux terameter terameters teramole teramoles teranewton teranewtons teraohm teraohms terapascal terapascals teraph teraphim teraradian teraradians terasecond teraseconds terasiemens terasievert terasieverts terasteradian terasteradians teratesla terateslas teratism teratisms teratocarcinoma teratocarcinomas teratocarcinomata teratogen teratogenesis teratogenic teratogenicity teratogens teratoid teratologic teratological teratologist teratologists teratology teratoma teratomas teratomata teratomatous teravolt teravolts terawatt terawatts teraweber terawebers terbium terce terceira tercel tercels tercentenaries tercentenary tercentennial tercentennials tercet tercets terebene terebenes terebic terebinth terebinthic terebinthine terebinths teredines teredo teredos terence terephthalate terephthalates terephthalic teresa terete tereus terga tergal tergite tergites tergiversate tergiversated tergiversates tergiversating tergiversation tergiversations tergiversator tergiversators tergum teriyaki teriyakis term termagant termagants termed termer termers terminability terminable terminableness terminably terminal terminally terminals terminate terminated terminates terminating termination terminational terminations terminative terminatively terminator terminators terminer terming termini terminological terminologically terminologies terminologist terminologists terminology terminus terminuses termitaria termitaries termitarium termitary termite termites termitic termless terms tern ternaries ternary ternate ternately terne terneplate terneplates ternes terns terpene terpeneless terpenes terpenic terpenoid terpenoids terpin terpineol terpineols terpolymer terpolymers terpsichore terpsichorean terpsichoreans terpsichores terr terra terrace terraced terraces terracing terracotta terrae terrain terrains terramycin terran terrane terranes terrapin terrapins terraqueous terraria terrarium terrariums terrazzo terrene terrenes terreplein terrepleins terrestrial terrestrially terrestrialness terrestrials terret terrets terrible terribleness terribles terribly terricolous terrier terriers terries terrific terrifically terrified terrifier terrifiers terrifies terrify terrifying terrifyingly terrigenous terrine terrines territorial territorialism territorialist territorialists territorialities territoriality territorialization territorializations territorialize territorialized territorializes territorializing territorially territorials territories territory terror terrorism terrorist terroristic terrorists terrorization terrorizations terrorize terrorized terrorizer terrorizers terrorizes terrorizing terrorless terrors terrs terry terse tersely terseness terser tersest tertial tertials tertian tertians tertiaries tertiary tertium tertullian tervalent tervuren terza terze tesla teslas tessellate tessellated tessellates tessellating tessellation tessellations tessera tesseract tesseracts tesserae tessitura tessituras test testa testability testable testacean testaceans testaceous testacy testae testament testamentary testaments testate testator testators testatrices testatrix testatrixes testcross testcrossed testcrosses testcrossing tested testee testees tester testers testes testicle testicles testicular testiculate testier testiest testificandum testification testifications testified testifier testifiers testifies testify testifying testily testimonial testimonials testimonies testimony testiness testing testis teston testons testoon testoons testosterone tests testudinal testudinate testudinates testudo testudos testy tetanal tetanic tetanically tetanies tetanization tetanizations tetanize tetanized tetanizes tetanizing tetanus tetany tetartohedral tetched tetchier tetchiest tetchily tetchiness tetchy teth tether tetherball tetherballs tethered tethering tethers tethys teton tetons tetra tetrabasic tetrabasicity tetrabranchiate tetrabranchiates tetracaine tetracaines tetrachloride tetrachlorides tetrachloroethylene tetrachord tetrachordal tetrachords tetracid tetracids tetracyclic tetracycline tetracyclines tetrad tetradactylous tetradic tetradrachm tetradrachms tetrads tetradymite tetradymites tetradynamous tetraethyl tetraethyllead tetraethylleads tetrafluoride tetrafluorides tetragon tetragonal tetragonally tetragons tetragrammaton tetragynous tetrahedra tetrahedral tetrahedrally tetrahedrite tetrahedrites tetrahedron tetrahedrons tetrahydrocannabinol tetrahydrocannabinols tetrahydrofuran tetrahydrofurans tetrahydroxy tetrahymena tetrahymenas tetralogies tetralogy tetramer tetrameric tetramerism tetramerous tetramers tetrameter tetrameters tetramethyllead tetramethylleads tetrandrous tetraplegic tetraploid tetraploids tetraploidy tetrapod tetrapodous tetrapods tetrapterous tetrapyrrole tetrapyrroles tetrarch tetrarchate tetrarchates tetrarchic tetrarchical tetrarchies tetrarchs tetrarchy tetras tetrasporangia tetrasporangium tetraspore tetraspores tetrasporic tetrastyle tetrasyllabic tetratomic tetravalent tetrazolium tetrazoliums tetrazzini tetrode tetrodes tetrodotoxin tetrodotoxins tetroxide tetroxides tetryl tetryls tetter tetterbush tetterbushes tetters teuton teutonic teutonically teutonicism teutonicisms teutonism teutonisms teutonist teutonists teutonization teutonizations teutonize teutonized teutonizes teutonizing teutons tevet tewa tewas tex texaco texan texans texas texel text textbook textbookish textbooks textile textiles texts textual textualism textualisms textualist textualists textually textuaries textuary textural texturally texture textured textureless textures texturing texturize texturized texturizer texturizers texturizes texturizing thackeray thai thailand thais thalamencephalic thalamencephalon thalamencephalons thalami thalamic thalamically thalamus thalassemia thalassemias thalassemic thalassic thalassocracies thalassocracy thalassocrat thalassocrats thaler thalers thales thalesian thalia thalidomide thalli thallic thallium thalloid thalloidal thallophyte thallophytes thallophytic thallous thallus thalluses thammuz than thanage thanages thanatological thanatologist thanatologists thanatology thanatopsis thanatos thanatotic thane thanes thaneship thanet thank thanked thanker thankers thankful thankfully thankfulness thanking thankless thanklessly thanklessness thanks thanksgiving thanksgivings thankworthier thankworthiest thankworthy that that'd that'll that's thataway thatch thatched thatcher thatchers thatches thatching thatchy thaumatologies thaumatology thaumaturge thaumaturges thaumaturgic thaumaturgical thaumaturgist thaumaturgists thaumaturgy thaw thawed thawing thaws the theanthropic theanthropical theanthropism theanthropisms theanthropist theanthropists thearchies thearchy theater theatergoer theatergoers theatergoing theaters theatine theatines theatre theatres theatric theatrical theatricalism theatricalisms theatricality theatricalization theatricalizations theatricalize theatricalized theatricalizer theatricalizers theatricalizes theatricalizing theatrically theatricalness theatricals theatrics thebaine thebaines theban thebans thebe thebes theca thecae thecal thecate thecodont thecodonts thee theelin theelins theelol theelols theft thefts thegn thegnly their theirs theirselves theism theist theistic theistical theistically theists them thematic thematically theme themed themeless themes themistocles themselves then thenar thenars thence thenceforth thenceforward thenceforwards theobald theobromine theobromines theocentric theocentricity theocentrism theocracies theocracy theocrat theocratic theocratical theocratically theocrats theocritus theodicies theodicy theodolite theodolites theodolitic theodora theodore theodoric theodosius theogonic theogonies theogony theolog theologian theologians theologic theological theologically theologies theologize theologized theologizer theologizers theologizes theologizing theologs theologue theologues theology theomachies theomachy theomorphic theomorphism theomorphisms theonomous theonomy theophanic theophanies theophany theophrastus theophylline theophyllines theorbo theorbos theorem theorematic theorems theoretic theoretical theoretically theoretician theoreticians theoretics theories theorist theorists theorization theorizations theorize theorized theorizer theorizers theorizes theorizing theory theosophic theosophical theosophically theosophies theosophist theosophists theosophy theotokos therapeusis therapeutic therapeutical therapeutically therapeutics therapeutist therapeutists therapies therapist therapists therapsid therapsids therapy theravada there there'd there'll there's thereabout thereabouts thereafter thereagainst thereat thereby therefor therefore therefrom therein thereinafter thereinto theremin theremins thereof thereon theresa thereto theretofore thereunder thereunto thereupon therewith therewithal theriac theriaca theriacal theriacs theriomorphic theriomorphous therm thermal thermalization thermalizations thermalize thermalized thermalizes thermalizing thermally thermals thermanesthesia thermanesthesias thermesthesia thermesthesias thermic thermically thermidor thermion thermionic thermionics thermions thermistor thermistors thermit thermite thermocauteries thermocautery thermochemical thermochemist thermochemistry thermochemists thermocline thermoclines thermocoagulation thermocoagulations thermocouple thermocouples thermoduric thermodynamic thermodynamical thermodynamically thermodynamicist thermodynamicists thermodynamics thermoelectric thermoelectrical thermoelectrically thermoelectricity thermoelectron thermoelectrons thermoelement thermoelements thermoform thermoformable thermoformed thermoforming thermoforms thermogenesis thermogenetic thermogenic thermogram thermograms thermograph thermographic thermographically thermographies thermographs thermography thermohaline thermojunction thermojunctions thermolabile thermolability thermoluminescence thermoluminescences thermoluminescent thermolyses thermolysis thermolytic thermomagnetic thermometer thermometers thermometric thermometrically thermometry thermomotor thermomotors thermonuclear thermoperiodicities thermoperiodicity thermoperiodism thermoperiodisms thermophile thermophiles thermophilic thermophilous thermopile thermopiles thermoplastic thermoplasticity thermoplastics thermoreceptor thermoreceptors thermoregulate thermoregulated thermoregulates thermoregulating thermoregulation thermoregulations thermoregulator thermoregulators thermoregulatory thermoremanence thermoremanent thermos thermoscope thermoscopes thermoses thermoset thermosets thermosetting thermosphere thermospheric thermostabile thermostability thermostable thermostat thermostatic thermostatically thermostats thermotactic thermotaxes thermotaxic thermotaxis thermotherapies thermotherapy thermotropic thermotropism therms theropod theropodan theropodans theropods thersites thesaural thesauri thesaurus thesauruses these these'd these'll theses theseus thesis thespian thespians thespis thessalian thessalians thessalonian thessalonians thessalonica thessaloniki thessaloníki thessaly theta thetas thetic thetical thetically thetis theurgic theurgical theurgically theurgies theurgist theurgists theurgy thew thews thewy they they'd they'll they're they've thiabendazole thiabendazoles thiamin thiaminase thiaminases thiamine thiamines thiamins thiazide thiazides thiazine thiazines thiazole thiazoles thick thicken thickened thickener thickeners thickening thickenings thickens thicker thickest thicket thicketed thickets thickety thickhead thickheaded thickheads thickish thickly thickness thicknesses thickset thickskulled thief thieve thieved thieveries thievery thieves thieving thievish thievishly thievishness thigh thighbone thighbones thighed thighs thigmotactic thigmotactically thigmotaxis thigmotaxises thigmotropic thigmotropism thigmotropisms thill thills thimble thimbleberries thimbleberry thimbleful thimblefuls thimblerig thimblerigged thimblerigger thimbleriggers thimblerigging thimblerigs thimbles thimbleweed thimbleweeds thimbu thimerosal thimerosals thimphu thin thine thing thingamabob thingamabobs thingamajig thingamajigs thingness things thingumabob thingumabobs thingumajig thingumajigs thingumbob thingumbobs thingummies thingummy think thinkable thinkableness thinkably thinker thinkers thinking thinkingly thinkingness thinkings thinks thinly thinned thinner thinners thinness thinnest thinning thinnish thins thio thiocarbamide thiocarbamides thiocyanate thiocyanates thiocyanic thiokol thiol thiolic thiols thionic thionyl thionyls thiopental thiophene thiophenes thioridazine thioridazines thiosulfate thiosulfates thiosulfuric thiotepa thiotepas thiouracil thiouracils thiourea thioureas thiram thirams third thirdhand thirdly thirds thirst thirsted thirster thirsters thirstier thirstiest thirstily thirstiness thirsting thirsts thirsty thirteen thirteenfold thirteens thirteenth thirteenths thirties thirtieth thirtieths thirty thirtyfold thirtyish this this'd this'll thisaway thisbe thistle thistledown thistles thistly thither thitherto thitherward thitherwards thixotropic thixotropy tho thohoyandou thole tholeiite tholeiitic tholepin tholepins tholes thomas thomism thomist thomistic thomists thompson thomson thong thonged thongs thor thoraces thoracic thoracically thoracolumbar thoracoplasties thoracoplasty thoracotomies thoracotomy thorax thoraxes thorazine thoreau thoreauvian thoria thorianite thorias thoric thorite thorites thorium thorn thornback thornbacks thornbush thornbushes thorndike thorned thornier thorniest thornily thorniness thornless thornlike thorns thorny thoron thorons thorough thoroughbass thoroughbasses thoroughbrace thoroughbraces thoroughbred thoroughbreds thoroughfare thoroughfares thoroughgoing thoroughly thoroughness thoroughpaced thoroughpin thoroughpins thoroughwort thoroughworts thorp thorps those those'd those'll thou though thought thoughtful thoughtfully thoughtfulness thoughtless thoughtlessly thoughtlessness thoughts thoughtway thoughtways thousand thousandfold thousands thousandth thousandths thrace thracian thracians thraldom thrall thralldom thralled thralling thralls thrash thrashed thrasher thrashers thrashes thrashing thrashings thrasonical thrasonically thread threadbare threadbareness threaded threader threaders threadfin threadfins threadier threadiest threadiness threading threadless threadlike threads threadworm threadworms thready threat threated threaten threatened threatener threateners threatening threateningly threatens threating threats three threefold threepence threepences threepenny threes threescore threesome threesomes thremmatology threnode threnodes threnodial threnodic threnodies threnodist threnodists threnody threonine threonines thresh threshed thresher threshers threshes threshing threshold thresholds threw thrice thrift thriftier thriftiest thriftily thriftiness thriftless thriftlessly thriftlessness thrifts thrifty thrill thrilled thriller thrillers thrilling thrillingly thrills thrips thrive thrived thriven thriver thrivers thrives thriving thrivingly throat throated throatier throatiest throatily throatiness throating throatlatch throatlatches throats throaty throb throbbed throbber throbbers throbbing throbbingly throbs throe throes thrombi thrombin thrombocyte thrombocytes thrombocytic thrombocytopenia thrombocytopenias thrombocytopenic thromboembolic thromboembolism thromboembolisms thrombokinase thrombokinases thrombolyses thrombolysis thrombolytic thrombophlebitis thrombophlebitises thromboplastic thromboplastically thromboplastin thromboplastins thromboses thrombosis thrombosthenin thrombosthenins thrombotic thromboxane thromboxanes thrombus throne throned thrones throng thronged thronging throngs throning throstle throstles throttle throttleable throttled throttlehold throttleholds throttler throttlers throttles throttling through throughly throughout throughput throughway throughways throve throw throwaway throwaways throwback throwbacks thrower throwers throwing thrown throws throwster throwsters thru thrum thrummed thrumming thrums thrush thrushes thrust thruster thrusters thrustful thrusting thrustor thrustors thrusts thruway thruways thucydides thud thudded thudding thuds thug thuggery thuggish thugs thuja thujas thule thulium thumb thumbed thumbhole thumbholes thumbing thumbnail thumbnails thumbnut thumbnuts thumbprint thumbprints thumbs thumbscrew thumbscrews thumbtack thumbtacked thumbtacking thumbtacks thumbwheel thumbwheels thummim thump thumped thumper thumpers thumping thumpingly thumps thunder thunderbird thunderbirds thunderbolt thunderbolts thunderclap thunderclaps thundercloud thunderclouds thundered thunderer thunderers thunderhead thunderheads thundering thunderingly thunderous thunderously thunders thundershower thundershowers thunderstone thunderstones thunderstorm thunderstorms thunderstricken thunderstrike thunderstrikes thunderstriking thunderstroke thunderstrokes thunderstruck thunk thunked thunking thunks thurber thurible thuribles thurifer thurifers thuringer thuringia thuringian thuringians thurl thurls thursday thursdays thus thusly thwack thwacked thwacking thwacks thwart thwarted thwarter thwarters thwarting thwartly thwarts thwartwise thy thyestean thyestes thylacine thylacines thylakoid thylakoids thyme thymectomies thymectomize thymectomized thymectomizes thymectomizing thymectomy thymey thymic thymidine thymidines thymine thymines thymocyte thymocytes thymol thymols thymoma thymomas thymosin thymosins thymus thymuses thymy thyratron thyratrons thyristor thyristors thyroactive thyrocalcitonin thyrocalcitonins thyroglobulin thyroglobulins thyroid thyroidal thyroidectomies thyroidectomize thyroidectomized thyroidectomizes thyroidectomizing thyroidectomy thyroiditis thyroiditises thyroids thyrotoxicosis thyrotrophic thyrotrophin thyrotrophins thyrotropic thyrotropin thyrotropins thyroxin thyroxine thyroxines thyroxins thyrse thyrses thyrsi thyrsoid thyrsoidal thyrsus thysanuran thysanurans thyself thásos théatre thíra ti tiahuanaco tiara tiaras tiber tiberian tiberius tibet tibetan tibetans tibeto tibia tibiae tibial tibias tibiofibula tibiofibular tibiofibulas tibiotarsus tibiotarsuses tic tical ticals ticced ticcing tick tickbird tickbirds ticked ticker tickers ticket ticketed ticketing ticketless tickets ticking tickle tickled tickler ticklers tickles tickling ticklish ticklishly ticklishness ticks tickseed tickseeds ticktack ticktacks ticktacktoe ticktacktoes ticktock ticktocks ticky ticqueur ticqueurs tics tictac tidal tidally tidbit tidbits tiddledywinks tiddler tiddlers tiddly tiddlywinks tide tided tideland tidelands tideless tidemark tidemarks tiderip tiderips tides tidewaiter tidewaiters tidewater tidewaters tideway tideways tidied tidier tidies tidiest tidily tidiness tiding tidings tidy tidying tidytips tie tieback tiebacks tiebreaker tiebreakers tiebreaking tied tieing tieless tiemannite tiemannites tientsin tiepin tiepins tiepolo tier tierce tiercel tiercels tierces tiered tiering tierra tiers ties tietze tiff tiffanies tiffany tiffed tiffin tiffing tiffins tiffs tiger tigereye tigereyes tigerish tigerishly tigerishness tigerlike tigers tight tighten tightened tightener tighteners tightening tightens tighter tightest tightfisted tightfistedness tightlipped tightlippedness tightly tightness tightrope tightropes tights tightwad tightwads tightwire tightwires tiglic tiglon tiglons tigon tigons tigre tigress tigresses tigrinya tigris tigré tike tikes tiki tikis til tilapia tilapias tilburies tilbury tilde tildes tile tiled tilefish tilefishes tiler tilers tiles tiling till tillable tillage tillamook tillandsia tillandsias tilled tiller tillered tillering tillerman tillermen tillers tilling tills tils tilsit tilsiter tilt tiltable tilted tilter tilters tilth tilting tiltmeter tiltmeters tilts tiltyard tiltyards tim timbal timbale timbales timbals timber timberdoodle timberdoodles timbered timberhead timberheads timbering timberings timberland timberlands timberline timberlines timberman timbermen timbers timberwork timberworks timbral timbre timbrel timbrelled timbrels timbres timbuktu time timecard timecards timed timekeeper timekeepers timekeeping timeless timelessly timelessness timelier timeliest timeline timelines timeliness timely timeous timeously timeout timeouts timepiece timepieces timepleaser timepleasers timer timers times timesaver timesavers timesaving timescale timescales timeserver timeservers timeserving timeshare timeshared timeshares timesharing timetable timetables timework timeworker timeworkers timeworn timid timider timidest timidity timidly timidness timing timings timocracies timocracy timocratic timocratical timolol timolols timon timor timorese timorous timorously timorousness timothies timothy timpani timpanist timpanists timpanogos timpanum timucua timucuas tin tinamou tinamous tinbergen tincal tincals tinct tinctorial tinctorially tincts tincture tinctured tinctures tincturing tinder tinderbox tinderboxes tine tinea tineal tineas tined tines tinfoil tinful tinfuls ting tinge tinged tingeing tinges tinging tingle tingled tingler tinglers tingles tingling tinglingly tingly tings tinhorn tinhorns tinian tinier tiniest tinily tininess tinker tinkered tinkerer tinkerers tinkering tinkers tinkertoy tinkle tinkled tinkles tinkling tinkly tinned tinner tinners tinnier tinniest tinnily tinniness tinning tinnitus tinnituses tinny tinplate tinplates tins tinsel tinseled tinseling tinselled tinselling tinselly tinsels tinsmith tinsmithing tinsmiths tinstone tinstones tint tinted tinter tinters tinting tintinnabula tintinnabular tintinnabulary tintinnabulation tintinnabulations tintinnabulous tintinnabulum tintless tintoretto tints tintype tintypes tinware tinwork tinworks tiny tip tipcart tipcarts tipcat tipi tipis tippecanoe tipped tipper tippers tippet tippets tippier tippiest tipping tipple tippled tippler tipplers tipples tippling tippy tips tipsier tipsiest tipsily tipsiness tipstaff tipstaffs tipstaves tipster tipsters tipsy tiptoe tiptoed tiptoeing tiptoes tiptop tiptops tirade tirades tiramisu tirana tiranë tire tired tiredly tiredness tireless tirelessly tirelessness tires tiresias tiresome tiresomely tiresomeness tiring tiro tirol tiros tirpitz tiryns tis tisane tisanes tishri tisiphone tissot tissue tissues tissuey tissular tit titan titanate titanates titaness titanesses titania titanic titanically titaniferous titanism titanisms titanite titanites titanium titanosaur titanosaurs titanothere titanotheres titanous titans titbit titbits titer titers titfer titfers tithable tithe tithed tither tithers tithes tithing tithings tithonia tithonias titi titian titianesque titicaca titillate titillated titillater titillaters titillates titillating titillatingly titillation titillations titillative titis titivate titivated titivates titivating titivation titivations titlark titlarks title titled titleholder titleholders titles titling titlist titlists titmice titmouse tito titoism titoist titoists titrant titrants titratable titrate titrated titrates titrating titration titrations titrator titrators titre titres titrimetric titrimetrically tits titter tittered titterer titterers tittering titteringly titters tittivate tittivated tittivates tittivating tittle tittles tittup tittuped tittuping tittupped tittupping tittups titubation titubations titular titularies titularly titulars titulary titus tivoli tiwa tiwas tizzies tizzy tko tlingit tlingits tmeses tmesis tnt to toad toadeater toadeaters toadfish toadfishes toadflax toadflaxes toadied toadies toads toadstone toadstones toadstool toadstools toady toadying toadyish toadyism toast toasted toaster toasters toastier toastiest toasting toastmaster toastmasters toastmistress toastmistresses toasts toasty tobacco tobaccoes tobacconist tobacconists tobaccos tobagan tobagans tobago tobagonian tobagonians tobias tobies tobit toboggan tobogganed tobogganer tobogganers tobogganing tobogganist tobogganists toboggans tobruk toby toccata toccatas tocharian tocharians tocology tocopherol tocopherols tocqueville tocsin tocsins today todays toddies toddle toddled toddler toddlerhood toddlers toddles toddling toddy todies tody toe toea toecap toecaps toed toehold toeholds toeing toeless toenail toenailed toenailing toenails toepiece toepieces toeplate toeplates toes toffee toffees toffies toffy tofu tog toga togaed togas together togetherness togged toggenburg toggeries toggery togging toggle toggled toggles toggling togo togolese togs togue togues toheroa toheroas toil toile toiled toiler toilers toilet toiletries toiletry toilets toilette toilettes toilful toilfully toiling toils toilsome toilsomely toilsomeness toilworn toity tokamak tokamaks tokara tokay tokays toke toked tokelau token tokened tokening tokenism tokenize tokenized tokenizes tokenizing tokens tokes tokharian tokharians toking tokology tokomak tokomaks tokonoma tokonomas tokyo tola tolas tolbutamide tolbutamides told tole toled toledo toledos tolerability tolerable tolerableness tolerably tolerance tolerances tolerant tolerantly tolerate tolerated tolerates tolerating toleration tolerative tolerator tolerators toles tolidine tolidines toling toll tollbooth tollbooths tolled tollgate tollgates tollhouse tollhouses tolling tolls tollway tollways tolstoian tolstoy tolstoyan toltec toltecan toltecs tolu toluate toluates toluene toluenes toluic toluidine toluidines toluol toluols tolus tolyl tolyls tom tomahawk tomahawked tomahawking tomahawks tomalley tomalleys tomatillo tomatillos tomato tomatoes tomatoey tomb tombac tombacs tombless tomblike tombolo tombolos tomboy tomboyish tomboyishness tomboys tombs tombstone tombstones tomcat tomcats tomcatted tomcatting tomcod tomcods tome tomenta tomentose tomentum tomes tomfool tomfooleries tomfoolery tomfools tomism tommed tommies tomming tommy tommyrot tomogram tomograms tomograph tomographic tomographs tomography tomorrow tomorrows tompion tompions toms tomsk tomtit tomtits tomé ton tonal tonalities tonality tonally tondi tondo tondos tone tonearm tonearms toned toneless tonelessly tonelessness toneme tonemes tonemic toner toners tones tonetic tonetically tonetics tonette tonettes toney tong tonga tongan tongans tonged tonger tongers tonging tongs tongue tongued tonguefish tonguefishes tongueless tonguelike tongues tonguing tonguings tonic tonically tonicities tonicity tonics tonier toniest tonight tonights toning tonk tonka tonkin tonkinese tonks tonnage tonnages tonne tonneau tonneaus tonner tonners tonnes tonometer tonometers tonometric tonometry tonoplast tonoplasts tons tonsil tonsillar tonsillectomies tonsillectomy tonsillitic tonsillitis tonsillotomies tonsillotomy tonsils tonsorial tonsure tonsured tonsures tonsuring tontine tontines tonus tonuses tony tonys too tooer tooers tooism took tool toolbox toolboxes tooled toolholder toolholders toolhouse toolhouses tooling toolings toolkit toolkits toolmaker toolmakers toolmaking toolroom toolrooms tools toolshed toolsheds toon toons toot tooted tooter tooters tooth toothache toothaches toothbrush toothbrushes toothbrushing toothed toothier toothiest toothily toothing toothless toothlessly toothlessness toothlike toothpaste toothpick toothpicks toothpowder toothpowders tooths toothsome toothsomely toothsomeness toothwort toothworts toothy tooting tootle tootled tootler tootlers tootles tootling toots tootsie tootsies tootsy top topaz topazes topcoat topcoats topcross topcrosses topdressing topdressings tope topectomies topectomy toped topee topees topeka toper topers topes topflight topful topfull topgallant topgallants tophet tophets tophi tophus topi topiaries topiary topic topical topicality topically topics toping topis topkick topkicks topknot topknots topless toplessness topline toplines toploftical toploftier toploftiest toploftily toploftiness toplofty topmast topmasts topminnow topminnows topmost topnotch topnotcher topnotchers topocentric topograph topographer topographers topographic topographical topographically topographies topographs topography topoi topologic topological topologically topologies topologist topologists topology toponym toponymic toponymical toponymies toponymist toponymists toponyms toponymy topos topotype topotypes topped topper toppers topping toppings topple toppled topples toppling tops topsail topsails topside topsider topsiders topsides topsoil topsoiled topsoiling topsoils topspin topstitch topstitched topstitches topstitching topsy topwork topworked topworking topworks toque toques tor torah torahs torbernite torbernites torch torchbearer torchbearers torched torches torchier torchiere torchieres torchiers torchiest torching torchlight torchlights torchon torchwood torchwoods torchy torchère torchères tore toreador toreadors torero toreros toreutic toreutics tori toric tories torii torino torment tormented tormenter tormenters tormentil tormentils tormenting tormentingly tormentor tormentors torments torn tornadic tornado tornadoes tornados tornillo tornillos toroid toroidal toroidally toroids toronto torose torpedo torpedoed torpedoes torpedoing torpid torpidity torpidly torpor torporific torquate torque torqued torquemada torquer torquers torques torqueses torquey torquing torr torrefaction torrefied torrefies torrefy torrefying torremolinos torrens torrent torrential torrentially torrents torres torrid torrider torridest torridity torridly torridness tors torsade torsades torsi torsion torsional torsionally torso torsos tort torte tortellini torten tortes torticollar torticollis torticollises tortilla tortillas tortious tortiously tortoise tortoises tortoiseshell tortoiseshells tortola tortoni tortricid tortricids tortrix torts tortuga tortuosities tortuosity tortuous tortuously tortuousness torture tortured torturer torturers tortures torturing torturous torturously torula torulae torulas torus tory toryism tosca toscanini tosh toss tossed tosser tossers tosses tossing tosspot tosspots tossup tossups tostada tostadas tostado tostados tot totable total totaled totaling totalism totalistic totalitarian totalitarianism totalitarianize totalitarianized totalitarianizes totalitarianizing totalitarians totalities totality totalization totalizations totalizator totalizators totalize totalized totalizer totalizers totalizes totalizing totalled totalling totally totals tote toted totem totemic totemism totemisms totemist totemistic totemists totems toter toters totes tother toting totipalmate totipalmation totipalmations totipotence totipotences totipotencies totipotency totipotent toto tots totted totter tottered totterer totterers tottering totteringly totters tottery totting touareg toucan toucanet toucanets toucans touch touchable touchableness touchback touchbacks touchdown touchdowns touched toucher touchers touches touchhole touchholes touchier touchiest touchily touchiness touching touchingly touchingness touchline touchlines touchmark touchmarks touchstone touchstones touchtone touchup touchups touchwood touchwoods touchy touché tough toughen toughened toughener tougheners toughening toughens tougher toughest toughie toughies toughly toughness toughs toughy toulon toulouse toupee toupees touquet tour touraco touracos touraine tourbillion tourbillions tourbillon tourbillons toured tourer tourers tourette tourette's touring tourings tourism tourist touristic touristically tourists touristy tourmaline tourmalines tournament tournaments tournedos tourney tourneyed tourneying tourneys tourniquet tourniquets tours touse toused touses tousing tousle tousled tousles tousling toussaint tout touted touter touters touting touts tovarich tovariches tovarish tovarishes tow towable towage toward towardliness towardly towards towboat towboats towed towel toweled towelette towelettes toweling towelings towelled towelling towellings towels tower towered towering toweringly towerish towerlike towers towhead towheaded towheads towhee towhees towing towline towlines town townhouse townhouses townie townies townlet townlets towns townscape townscapes townsend townsfolk townshend township townships townsman townsmen townspeople townswoman townswomen towny towpath towpaths towrope towropes tows toxalbumin toxalbumins toxaphene toxaphenes toxemia toxemic toxic toxically toxicant toxicants toxicities toxicity toxicogenic toxicologic toxicological toxicologically toxicologist toxicologists toxicology toxicoses toxicosis toxics toxigenic toxigenicity toxin toxins toxoid toxoids toxophilite toxophilites toxophily toxoplasma toxoplasmas toxoplasmic toxoplasmoses toxoplasmosis toy toyed toyer toyers toying toylike toynbee toyon toyons toyota toyotas toys toyshop toyshops trabeate trabeated trabeation trabeations trabecula trabeculae trabecular trabeculas trabeculate trace traceability traceable traceableness traceably traced traceless tracer traceried traceries tracers tracery traces trachea tracheae tracheal tracheary tracheas tracheate tracheated tracheates tracheid tracheidal tracheids tracheitis tracheitises tracheobronchial tracheoesophageal tracheolar tracheole tracheoles tracheophyte tracheophytes tracheoscopic tracheoscopies tracheoscopy tracheostomies tracheostomy tracheotomies tracheotomy trachoma trachomatous trachyte trachytic tracing tracings track trackable trackage trackages trackball trackballs tracked tracker trackers tracking tracklayer tracklayers tracklaying trackless trackman trackmen tracks trackside tracksides tracksuit tracksuits trackwalker trackwalkers trackway trackways tract tractability tractable tractableness tractably tractarian tractarianism tractarians tractate tractates tractile tractility traction tractional tractive tractor tractors tracts tracy tradable trade tradeable tradecraft tradecrafts traded trademark trademarked trademarking trademarks tradeoff tradeoffs trader traders trades tradescantia tradescantias tradesman tradesmen tradespeople trading tradition traditional traditionalism traditionalist traditionalistic traditionalists traditionalize traditionalized traditionalizes traditionalizing traditionally traditionary traditionless traditions traditor traditores traduce traduced traducement traducements traducer traducers traduces traducianism traducianist traducianistic traducianists traducing traducingly trafalgar traffic trafficability trafficable trafficked trafficker traffickers trafficking traffics tragacanth tragacanths tragedian tragedians tragedienne tragediennes tragedies tragedy tragi tragic tragical tragically tragicalness tragicomedies tragicomedy tragicomic tragicomical tragicomically tragopan tragopans tragus trail trailblazer trailblazers trailblazing trailbreaker trailbreakers trailed trailer trailerable trailered trailering trailerist trailerists trailerite trailerites trailers trailhead trailheads trailing trailless trails trailside trailsides train trainability trainable trainband trainbands trainbearer trainbearers trained trainee trainees traineeship trainer trainers trainful trainfuls training trainload trainloads trainman trainmaster trainmasters trainmen trains traipse traipsed traipses traipsing trait traitor traitoress traitoresses traitorous traitorously traitorousness traitors traitress traitresses traits trajan traject trajected trajecting trajection trajections trajectories trajectory trajects trakehner trakehners tram tramcar tramcars tramline tramlines trammed trammel trammeled trammeler trammelers trammeling trammelled trammelling trammels tramming tramontane tramontanes tramp tramped tramper trampers tramping trampish trample trampled trampler tramplers tramples trampling trampoline trampoliner trampoliners trampolines trampolining trampolinist trampolinists tramps trampy trams tramway tramways trance tranced trancelike trances tranche trancing tranquil tranquility tranquilization tranquilizations tranquilize tranquilized tranquilizer tranquilizers tranquilizes tranquilizing tranquillity tranquillize tranquillized tranquillizer tranquillizers tranquillizes tranquillizing tranquilly tranquilness trans transact transacted transacting transactinide transaction transactional transactions transactivate transactivated transactivates transactivating transactivation transactivations transactivator transactivators transactor transactors transacts transalpine transaminase transaminases transamination transaminations transatlantic transaxle transaxles transcaucasia transcaucasian transcaucasians transceiver transceivers transcend transcended transcendence transcendency transcendent transcendental transcendentalism transcendentalist transcendentalists transcendentally transcendently transcending transcends transconductance transcontinental transcribable transcribe transcribed transcriber transcribers transcribes transcribing transcript transcriptase transcriptases transcription transcriptional transcriptionally transcriptionist transcriptionists transcriptions transcripts transcultural transculturation transculturations transcurrent transcutaneous transdermal transdermals transdisciplinary transduce transduced transducer transducers transduces transducing transductant transductants transduction transductional transductions transect transected transecting transection transections transects transept transeptal transepts transeunt transfect transfected transfecting transfection transfections transfects transfer transferability transferable transferal transferals transferase transferases transferee transferees transference transferential transferor transferors transferrable transferred transferrer transferrers transferrin transferring transferrins transfers transfiguration transfigurations transfigure transfigured transfigurement transfigures transfiguring transfinite transfix transfixed transfixes transfixing transfixion transfixions transform transformable transformation transformational transformationalist transformationalists transformationally transformations transformative transformed transformer transformers transforming transforms transfusable transfuse transfused transfuser transfusers transfuses transfusible transfusing transfusion transfusional transfusions transfusive transgenic transgress transgressed transgresses transgressible transgressing transgression transgressions transgressive transgressively transgressor transgressors tranship transhipped transhipping tranships transhistorical transhumance transhumant transhumants transience transiency transient transiently transients transilluminate transilluminated transilluminates transilluminating transillumination transilluminations transilluminator transilluminators transistor transistorization transistorizations transistorize transistorized transistorizes transistorizing transistors transit transited transiting transition transitional transitionally transitionary transitions transitive transitively transitiveness transitives transitivity transitorily transitoriness transitory transits transjordan transjordanian transjordanians transkei transkeian transkeians translatability translatable translatableness translate translated translates translating translation translational translations translative translator translatorial translators translatory transliterate transliterated transliterates transliterating transliteration transliterations translocate translocated translocates translocating translocation translocations translucence translucency translucent translucently translunar transmarine transmembrane transmigrant transmigrants transmigrate transmigrated transmigrates transmigrating transmigration transmigrationism transmigrations transmigrator transmigrators transmigratory transmissibility transmissible transmission transmissions transmissive transmissivity transmissometer transmissometers transmissometry transmit transmits transmittable transmittal transmittals transmittance transmittances transmitted transmitter transmitters transmitting transmogrification transmogrifications transmogrified transmogrifies transmogrify transmogrifying transmontane transmountain transmundane transmutability transmutable transmutableness transmutably transmutation transmutational transmutations transmutative transmute transmuted transmuter transmuters transmutes transmuting transnational transnationalism transnatural transoceanic transom transoms transonic transpacific transparence transparencies transparency transparent transparentize transparentized transparentizes transparentizing transparently transparentness transpersonal transpicuous transpierce transpierced transpierces transpiercing transpiration transpirational transpire transpired transpires transpiring transplacental transplacentally transplant transplantability transplantable transplantation transplantations transplanted transplanter transplanters transplanting transplants transpolar transponder transponders transpontine transport transportability transportable transportation transportational transported transporter transporters transporting transportive transports transposable transpose transposed transposes transposing transposition transpositional transpositions transposon transposons transsexual transsexualism transsexuality transsexuals transshape transshaped transshapes transshaping transship transshipment transshipments transshipped transshipping transships transsonic transthoracic transthoracically transubstantial transubstantiate transubstantiated transubstantiates transubstantiating transubstantiation transubstantiationalist transubstantiationalists transubstantiations transudate transudates transudation transudations transudatory transude transuded transudes transuding transuranic transuranium transurethral transvaal transvaluate transvaluated transvaluates transvaluating transvaluation transvaluations transvalue transvalued transvalues transvaluing transversal transversally transversals transverse transversely transverseness transverses transvestism transvestite transvestites transvestitism transylvania transylvanian transylvanians trap trapdoor trapdoors trapeze trapezes trapezia trapeziform trapezist trapezists trapezium trapeziums trapezius trapeziuses trapezohedra trapezohedron trapezohedrons trapezoid trapezoidal trapezoids traplight traplights trapline traplines trapped trapper trappers trapping trappings trappist trappists traprock traprocks traps trapshooter trapshooters trapshooting trapunto trapuntos trash trashed trashes trashier trashiest trashily trashiness trashing trashman trashmen trashy trass trasses trattoria trattorias trattorie trauma traumas traumata traumatic traumatically traumatism traumatisms traumatization traumatizations traumatize traumatized traumatizes traumatizing traumatological traumatologist traumatologists traumatology travail travailed travailing travails trave travel traveled traveler traveler's travelers traveling travelled traveller travellers travelling travelog travelogs travelogue travelogues travels traversable traversal traversals traverse traversed traverser traversers traverses traversing travertine travertines traves travestied travesties travesty travestying traviata travois travoise travoises trawl trawled trawler trawlerman trawlermen trawlers trawling trawls tray trayful trayfuls trays trazodone trazodones treacheries treacherous treacherously treacherousness treachery treacle treacly tread treaded treader treaders treading treadle treadled treadler treadlers treadles treadless treadling treadmill treadmills treads treason treasonable treasonableness treasonably treasonous treasonously treasurable treasure treasured treasurer treasurers treasurership treasures treasuries treasuring treasury treat treatability treatable treated treater treaters treaties treating treatise treatises treatment treatments treats treaty trebizond treble trebled trebleness trebles trebling trebly trebuchet trebuchets trebucket trebuckets trecento tredecillion tredecillions tree treed treehopper treehoppers treeing treeless treelike treen treenail treenails treens trees treetop treetops tref trefoil trefoils trehala trehalas trehalase trehalases trehalose trehaloses treillage treillages trek trekked trekker trekkers trekking treks trellis trellised trellises trellising trelliswork trematode trematodes trematodiasis tremble trembled trembler tremblers trembles trembling tremblingly trembly tremendous tremendously tremendousness tremens tremolite tremolites tremolitic tremolo tremolos tremor tremors tremulant tremulous tremulously tremulousness trenail trenails trench trenchancy trenchant trenchantly trenched trencher trencherman trenchermen trenchers trenches trenching trend trended trendier trendies trendiest trendily trendiness trending trends trendsetter trendsetters trendsetting trendy trentino trenton trepan trepanation trepanations trepang trepangs trepanned trepanning trepans trephination trephinations trephine trephined trephines trephining trepid trepidant trepidation treponema treponemal treponemas treponemata treponematoses treponematosis treponematous treponeme treponemes trespass trespassed trespasser trespassers trespasses trespassing tress tressed tressel tressels tresses trestle trestles trestletree trestletrees trestlework tretinoin tretinoins trevallies trevally trevelyan trevithick trews trey treys triable triableness triacetate triacetates triacid triacids triad triadelphous triadic triadically triads triage triages trial trialogue trialogues trials triamcinolone triamcinolones triandrous triangle triangles triangular triangularity triangularly triangulate triangulated triangulates triangulating triangulation triangulations triangulum triarchies triarchy triassic triathlete triathletes triathlon triathlons triatomic triaxial triaxiality triazine triazines triazole triazoles tribade tribades tribadism tribal tribalism tribalisms tribalist tribalistic tribalists tribally tribasic tribe tribes tribesman tribesmen tribespeople tribeswoman tribeswomen triboelectric triboelectricities triboelectricity tribological tribologist tribologists tribology triboluminescence triboluminescent tribrach tribrachic tribrachs tribromoethanol tribromoethanols tribulate tribulated tribulates tribulating tribulation tribulations tribunal tribunals tribunary tribunate tribunates tribune tribunes tribuneship tributaries tributary tribute tributes tricameral tricarboxylic trice triced tricentennial tricentennials triceps tricepses triceratops triceratopses trices trichiasis trichina trichinae trichinal trichinas trichinization trichinizations trichinize trichinized trichinizes trichinizing trichinoses trichinosis trichinous trichite trichites trichitic trichlorethylene trichlorethylenes trichlorfon trichlorfons trichlorid trichloride trichlorides trichlorids trichloroacetic trichloroethane trichloroethylene trichloroethylenes trichlorphon trichlorphons trichocyst trichocystic trichocysts trichogyne trichogynes trichoid trichologist trichologists trichology trichome trichomes trichomic trichomonacidal trichomonacide trichomonacides trichomonad trichomonadal trichomonads trichomonal trichomoniases trichomoniasis trichopteran trichopterans trichoses trichosis trichothecene trichothecenes trichotomic trichotomies trichotomous trichotomously trichotomy trichroic trichroism trichroisms trichromat trichromatic trichromatism trichromats trichrome trichromic trichuriases trichuriasis tricing trick tricked tricker trickeries trickers trickery trickier trickiest trickily trickiness tricking trickish trickishly trickishness trickle trickled trickles trickling tricks tricksier tricksiest tricksiness trickster tricksters tricksy tricky triclad triclads triclinia triclinic triclinium tricolette tricolettes tricolor tricolored tricolors tricorn tricorne tricornered tricornes tricorns tricostate tricot tricotine tricotines tricots tricrotic tricrotism trictrac tricuspid tricuspidal tricuspidate tricuspids tricycle tricycles tricyclic tricyclics tridactyl tridactylous trident tridentate tridentine tridentines tridents tridimensional tridimensionality triduum tried triene trienes triennia triennial triennially triennials triennium trienniums trier trierarch trierarchies trierarchs trierarchy triers tries trieste triethiodide triethyl trifacial trifecta trifectas trifid trifle trifled trifler triflers trifles trifling triflingly trifluoperazine trifluoperazines trifluralin trifluralins trifocal trifocals trifoliate trifoliated trifoliolate trifolium triforia triforium triform triformed trifurcate trifurcated trifurcates trifurcating trifurcation trifurcations trig trigamous trigeminal trigemini trigeminus trigged trigger triggered triggerfish triggerfishes triggering triggerman triggermen triggers trigging trigly triglyceride triglycerides triglyph triglyphic triglyphical triglyphs trigness trigon trigonal trigonally trigonometric trigonometrical trigonometrically trigonometry trigons trigram trigrammatic trigrammatically trigrams trigraph trigraphic trigraphically trigraphs trigs trigynous trihalomethane trihalomethanes trihedra trihedral trihedrals trihedron trihedrons trihybrid trihybrids trihydric trihydroxy triiodothyronine triiodothyronines trijet trijets trike trikes trilabiate trilateral trilateralism trilateralisms trilateralist trilateralists trilaterally trilbies trilby trilinear trilingual trilingualism trilingually trilinguals triliteral triliteralism triliterals trilith trilithic trilithon trilithons triliths trill trilled triller trillers trilling trillion trillions trillionth trillionths trillium trilliums trills trilobate trilobated trilobed trilobite trilobites trilobitic trilocular trilogies trilogy trim trimaran trimarans trimer trimeric trimerism trimerous trimers trimester trimesters trimestral trimestrial trimeter trimeters trimethadione trimethadiones trimethoprim trimethoprims trimetric trimetrical trimetrogon trimetrogons trimly trimmed trimmer trimmers trimmest trimming trimmings trimness trimolecular trimonthly trimorph trimorphic trimorphically trimorphism trimorphous trimorphs trimotor trimotors trims trimurti trinal trinary trincomalee trine trines trinidad trinidadian trinidadians trinitarian trinitarianism trinitarians trinities trinitrobenzene trinitrobenzenes trinitrocresol trinitrocresols trinitrophenol trinitrophenols trinitrotoluene trinitrotoluenes trinitrotoluol trinitrotoluols trinity trinitytide trinket trinketer trinketers trinketry trinkets trinocular trinomial trinomialism trinomials trinucleotide trinucleotides trio triode triodes triol triolet triolets triols trios triose trioses trioxid trioxide trioxides trioxids trip tripack tripacks tripalmitin tripalmitins tripartite tripartitely tripartition tripartitions tripe tripedal tripeptide tripeptides tripetalous triphammer triphammers triphenylmethane triphenylmethanes triphibian triphibians triphibious triphosphatase triphosphate triphosphates triphosphopyridine triphthong triphthongal triphthongs tripinnate tripinnately triplane triplanes triple tripled tripleheader tripleheaders triples triplet tripletail tripletails triplets triplex triplexes triplicate triplicated triplicately triplicates triplicating triplication triplications triplicities triplicity tripling triploblastic triploid triploids triploidy triply tripod tripodal tripods tripoli tripolis tripolitan tripolitania tripolitanian tripolitanians tripolitans tripolyphosphate tripos triposes tripped tripper trippers trippet trippets tripping trippingly trippy trips triptane triptanes triptych triptychs tripura tripwire tripwires triquetra triquetral triquetrous triquetrum triradiate trireme triremes trisaccharide trisaccharides trisagion trisect trisected trisecting trisection trisections trisector trisectors trisects trisepalous trishaw trishaws triskaidekaphobia triskaidekaphobias triskele triskeles triskelia triskelion trismic trismus trisoctahedra trisoctahedral trisoctahedron trisoctahedrons trisodium trisome trisomes trisomic trisomies trisomy tristan tristate triste tristearin tristearins tristeza tristful tristfully tristfulness tristich tristichs tristimulus tristram trisubstituted trisulfide trisulfides trisyllabic trisyllabical trisyllabically trisyllable trisyllables tritanopia tritanopias trite tritely triteness triter tritest tritheism tritheist tritheistic tritheistical tritheists tritiate tritiated tritiates tritiating tritiation triticale triticales tritium tritoma tritomas triton tritone tritones tritons triturable triturate triturated triturates triturating trituration triturations triturator triturators triumph triumphal triumphalism triumphalisms triumphalist triumphalists triumphant triumphantly triumphed triumphing triumphs triumvir triumviral triumvirate triumvirates triumviri triumvirs triune triunes triunities triunity trivalence trivalency trivalent trivalve trivet trivets trivia trivial trivialist trivialists trivialities triviality trivialization trivializations trivialize trivialized trivializes trivializing trivially trivialness trivium triweeklies triweekly trobriand trocar trocars trochaic trochaics trochal trochanter trochanteral trochanteric trochanters trochar trochars troche trochee trochees troches trochlea trochleae trochlear trochoid trochoidal trochoidally trochoids trochophore trochophores trod trodden troffer troffers troglodyte troglodytes troglodytic troglodytical trogon trogons troika troikas troilite troilites troilus trois trojan trojans troll trolled troller trollers trolley trolleybus trolleybuses trolleyed trolleying trolleys trollied trollies trolling trollop trollope trollops trolls trolly trollying trombe trombiculiasis trombiculoses trombiculosis trombone trombones trombonist trombonists trommel trommels tromp trompe tromped trompes tromping tromps tromsö trona tronas trondheim troop trooped trooper troopers trooping troops troopship troopships troostite troostites trop trope tropes tropez trophallaxes trophallaxis trophic trophically trophies trophoblast trophoblastic trophoblasts trophoderm trophoderms trophozoite trophozoites trophy tropic tropical tropicalize tropicalized tropicalizes tropicalizing tropically tropicals tropicbird tropicbirds tropics tropin tropine tropines tropins tropism tropistic tropistically tropocollagen tropocollagens tropologic tropological tropologically tropologies tropology tropomyosin tropomyosins troponin troponins tropopause tropopauses tropophyte tropophytes tropophytic troposphere tropospheric tropotactic tropotactically tropotaxis tropotaxises troppo trot troth trothed trothing trothplight trothplighted trothplighting trothplights troths trotline trotlines trots trotsky trotskyism trotskyist trotskyists trotskyite trotskyites trotted trotter trotters trotting troubadour troubadours trouble troubled troublemaker troublemakers troublemaking troubler troublers troubles troubleshoot troubleshooter troubleshooters troubleshooting troubleshoots troubleshot troublesome troublesomely troublesomeness troubling troublingly troublous troublously troublousness trough troughs trounce trounced trounces trouncing troupe trouped trouper troupers troupes troupial troupials trouping trouser trousers trousseau trousseaus trousseaux trout troutier troutiest troutperch troutperches trouts trouty trouvere trouveres trouveur trouveurs trouville trouvère trouvères trove trover trovers troves trow trowed trowel troweled troweler trowelers troweling trowelled troweller trowellers trowelling trowels trowing trows trowser trowsers troy troôdos truancies truancy truant truanted truanting truantries truantry truants truce trucebreaker trucebreakers truced truces trucing truck truckage trucked trucker truckers truckful truckfuls trucking truckle truckled truckler trucklers truckles truckline trucklines truckling truckload truckloads truckman truckmaster truckmasters truckmen trucks truculence truculences truculencies truculency truculent truculently trudge trudged trudgen trudgens trudgeon trudgeons trudger trudgers trudges trudging true trueborn trued truehearted trueheartedness trueing truelove trueloves trueness truepennies truepenny truer trues truest truffle truffled truffles truing truism truisms truistic truk trull trulls truly trump trumped trumperies trumpery trumpet trumpeted trumpeter trumpeters trumpeting trumpetlike trumpets trumping trumps truncate truncated truncately truncates truncating truncation truncations truncheon truncheoned truncheoning truncheons trundle trundled trundler trundlers trundles trundling trunk trunked trunkfish trunkfishes trunkful trunkfuls trunks trunnel trunnels trunnion trunnions truss trussed trusser trussers trusses trussing trust trustability trustable trustbuster trustbusters trustbusting trustbustings trusted trustee trusteed trusteeing trustees trusteeship trusteeships truster trusters trustful trustfully trustfulness trustier trusties trustiest trustily trustiness trusting trustingly trustingness trustless trusts trustworthier trustworthiest trustworthily trustworthiness trustworthy trusty truth truthful truthfully truthfulness truths try trying tryingly tryout tryouts trypanosomal trypanosome trypanosomes trypanosomiases trypanosomiasis trypanosomic tryparsamide tryparsamides trypsin trypsinogen trypsinogens trypsins tryptamine tryptamines tryptic tryptophan tryptophane tryptophanes tryptophans trysail trysails tryst trysted tryster trysters trysting trysts tryworks tsade tsades tsar tsars tsarskoye tsatske tsatskes tsetse tshiluba tsimmes tsimmeses tsimshian tsimshians tsinghai tsk tsked tsking tsks tsunami tsunamic tsunamis tsuris tsurises tsushima tsutsugamushi tswana tswanas tu tuamotu tuan tuareg tuaregs tuatara tuataras tub tuba tubaist tubaists tubal tubas tubate tubbable tubbed tubber tubbers tubbier tubbiest tubbiness tubbing tubby tube tubectomies tubectomy tubed tubeless tubelike tubenose tubenoses tuber tubercle tubercles tubercular tuberculars tuberculate tuberculated tuberculately tuberculation tuberculations tuberculin tuberculins tuberculoid tuberculoses tuberculosis tuberculous tuberculously tuberose tuberoses tuberosities tuberosity tuberous tubers tuberworm tuberworms tubes tubeworm tubeworms tubful tubfuls tubicolous tubifex tubifexes tubificid tubificids tubing tubist tubists tublike tubocurarine tubocurarines tuboplasties tuboplasty tubs tubuai tubular tubularity tubularly tubulate tubulated tubulation tubulations tubulator tubulators tubule tubules tubuliferous tubuliflorous tubulin tubulins tubulous tubulously tucana tuchun tuchuns tuck tuckahoe tuckahoes tucked tucker tuckered tuckering tuckers tucket tuckets tucking tucks tuckshop tuckshops tucson tudor tudors tuesday tuesdays tufa tufaceous tufas tuff tuffaceous tuffet tuffets tuffs tuft tufted tufter tufters tufting tufts tufty tug tugboat tugboats tugged tugger tuggers tugging tughrik tughriks tugrik tugriks tugs tui tuille tuilles tuis tuition tuitional tuitionary tularemia tularemic tule tules tulip tulips tulipwood tulipwoods tulle tulles tullibee tullibees tulsa tumble tumblebug tumblebugs tumbled tumbledown tumblehome tumblehomes tumbler tumblerful tumblerfuls tumblers tumbles tumbleset tumblesets tumbleweed tumbleweeds tumbling tumblings tumbrel tumbrels tumbril tumbrils tumefacient tumefaction tumefactions tumefactive tumefied tumefies tumefy tumefying tumescence tumescences tumescent tumid tumidity tumidly tumidness tummies tummler tummlers tummy tumor tumoral tumorigeneses tumorigenesis tumorigenic tumorigenicity tumorlike tumorous tumors tump tumpline tumplines tumps tumular tumuli tumulose tumulosity tumulous tumult tumults tumultuary tumultuous tumultuously tumultuousness tumulus tun tuna tunability tunable tunableness tunably tunas tundish tundishes tundra tundras tune tuneable tuned tuneful tunefully tunefulness tuneless tunelessly tunelessness tuner tuners tunes tunesmith tunesmiths tung tungstate tungstates tungsten tungstenic tungstic tungstite tungstites tungus tunguses tungusic tunic tunica tunicae tunicate tunicated tunicates tunicle tunicles tunics tuning tunings tunis tunisia tunisian tunisians tunnel tunneled tunneler tunnelers tunneling tunnelled tunneller tunnellers tunnellike tunnelling tunnels tunnies tunny tuns tup tupelo tupelos tupi tupian tupians tupis tupped tuppence tupperware tupping tups tuque tuques turaco turacos turanian turanians turban turbaned turbanned turbans turbaries turbary turbellarian turbellarians turbid turbidimeter turbidimeters turbidimetric turbidimetrically turbidimetry turbidite turbidites turbidities turbidity turbidly turbidness turbinal turbinals turbinate turbinated turbination turbinations turbine turbines turbit turbits turbo turbocar turbocars turbocharged turbocharger turbochargers turboelectric turbofan turbofans turbogenerator turbogenerators turbojet turbojets turbomachinery turboprop turboprops turboramjet turboramjets turbos turboshaft turboshafts turbosupercharger turbosuperchargers turbot turbots turbulence turbulencies turbulency turbulent turbulently turcoman turcomans turd turds tureen tureens turf turfed turfing turfman turfmen turfs turfski turfskiing turfskis turfy turgenev turgescence turgescent turgid turgidity turgidly turgidness turgor turin turing turion turions turista turk turkana turkestan turkey turkeys turki turkic turkics turkis turkish turkism turkistan turkmen turkmenistan turkmens turkoman turkomans turks turmaline turmalines turmeric turmoil turn turnable turnabout turnabouts turnaround turnarounds turnbuckle turnbuckles turncoat turncoats turndown turndowns turned turner turneries turners turnery turning turnings turnip turnips turnkey turnkeys turnoff turnoffs turnout turnouts turnover turnovers turnpike turnpikes turns turnsole turnsoles turnspit turnspits turnstile turnstiles turnstone turnstones turntable turntables turnup turnups turnverein turnvereins turophile turophiles turpentine turpentined turpentines turpentinic turpentining turpentinous turpin turpitude turps turquois turquoise turquoises turret turreted turrets turtle turtleback turtlebacked turtlebacks turtled turtledove turtledoves turtlehead turtleheads turtleneck turtlenecked turtlenecks turtler turtlers turtles turtling turves turvier turvies turviest turvily turviness turvy turvydom tuscan tuscans tuscany tuscarora tuscaroras tusche tusches tush tushes tushie tushies tushy tusk tusked tusker tuskers tusking tusklike tusks tussah tussahs tussal tussaud tusser tusses tussie tussis tussive tussle tussled tussles tussling tussock tussocks tussocky tussore tussores tut tutankhamen tutankhaten tutee tutees tutelage tutelar tutelaries tutelars tutelary tutor tutorage tutorages tutored tutoress tutoresses tutorial tutorials tutoring tutors tutorship tutorships tutoyer tutoyered tutoyering tutoyers tuts tutsi tutsis tutted tutti tutting tuttis tutty tutu tutuila tutus tuvalu tuvaluan tuvaluans tux tuxedo tuxedoed tuxedoes tuxedos tuxes tuyere tuyeres tuyère tuyères tuzzy twaddle twaddled twaddler twaddlers twaddles twaddling twain twains twang twanged twanger twangers twanging twangs twangy twas twat twats twayblade twayblades tweak tweaked tweaking tweaks tweaky twee tweed tweeddale tweedier tweediest tweediness tweedledee tweedledum tweeds tweedy tween tweet tweeted tweeter tweeters tweeting tweets tweeze tweezed tweezer tweezers tweezes tweezing twelfth twelfths twelve twelvefold twelvemo twelvemonth twelvemonths twelvemos twelvepenny twelves twenties twentieth twentieths twenty twentyfold twere twerp twerps twi twibill twibills twice twiddle twiddled twiddler twiddlers twiddles twiddling twig twigged twiggier twiggiest twigging twiggy twigs twilight twilit twill twilled twilling twills twin twinberries twinberry twinborn twine twined twiner twiners twines twinflower twinflowers twinge twinged twingeing twinges twinging twinight twining twinjet twinjets twinkle twinkled twinkler twinklers twinkles twinkling twinkly twinleaf twinleaves twinned twinning twinnings twins twinset twinsets twinship twiny twirl twirled twirler twirlers twirling twirls twirly twirp twirps twist twistability twistable twisted twister twisters twisting twistingly twists twisty twit twitch twitched twitcher twitchers twitches twitchier twitchiest twitchily twitchiness twitching twitchingly twitchy twite twites twits twitted twitter twittered twitterer twitterers twittering twitters twittery twitting twixt two twofaced twofer twofers twofold twomo twomos twopence twopences twopenny twos twosome twosomes tyburn tycho tycoon tycoons tyer tyers tying tyke tykes tylectomies tylectomy tylenol tylose tyloses tylosin tylosins tylosis tymbal tymbals tympan tympana tympanal tympani tympanic tympanies tympanist tympanists tympanites tympanitic tympanitis tympanitises tympanoplasties tympanoplasty tympans tympanum tympanums tympany tyndale tyndareus tyne tynes typal type typeable typecast typecasting typecasts typed typeface typefaces typefounder typefounders typefounding types typescript typescripts typeset typesets typesetter typesetters typesetting typestyle typestyles typewrite typewriter typewriters typewrites typewriting typewritings typewritten typewrote typey typhlitic typhlitis typhlology typhlosole typhlosoles typhoean typhoeus typhogenic typhoid typhoidal typhoidin typhoidins typhon typhoon typhoons typhous typhus typic typical typicality typically typicalness typier typiest typification typifications typified typifier typifiers typifies typify typifying typing typist typists typo typograph typographed typographer typographers typographic typographical typographically typographies typographing typographs typography typologic typological typologically typologies typologist typologists typology typos typy tyramine tyramines tyrannic tyrannical tyrannically tyrannicalness tyrannicide tyrannicides tyrannies tyrannize tyrannized tyrannizer tyrannizers tyrannizes tyrannizing tyrannizingly tyrannosaur tyrannosaurs tyrannosaurus tyrannosauruses tyrannous tyrannously tyranny tyrant tyrants tyrian tyrians tyro tyrocidin tyrocidine tyrocidines tyrocidins tyrol tyrolean tyroleans tyrolese tyrolian tyrollean tyrone tyros tyrosinase tyrosinases tyrosine tyrosines tyrothricin tyrothricins tyrrhenian tzaddik tzaddikim tzar tzars tzetze tzigane tziganes tzimmes tzimmeses tzitzis tzitzit tzuris tzurises tène tête têtes tínos tórshavn tôle tôles u ubangi ubiety ubiquinone ubiquinones ubiquitous ubiquitously ubiquitousness ubiquity uccello udall udder udders udine udo udometer udometers udos udzungwa uffizi ufo ufological ufologist ufologists ufology ufos uganda ugandan ugandans ugaritic ugh ugli uglier uglies ugliest uglification uglifications uglified uglifier uglifiers uglifies uglify uglifying uglily ugliness ugly ugrian ugrians ugric ugsome ugsomeness uh uhf uhlan uhlans uighur uighurs uigur uigurian uiguric uigurs uilleann uintahite uintahites uintaite uintaites uitlander uitlanders uk ukase ukases uke ukelele ukeleles ukes ukraine ukrainian ukrainians ukulele ukuleles ulama ulamas ulan ulans ulcer ulcerate ulcerated ulcerates ulcerating ulceration ulcerations ulcerative ulcerogenic ulcerous ulcerously ulcerousness ulcers ulema ulexite ulexites ullage ullages ulna ulnae ulnar ulnas ulster ulsters ulterior ulteriorly ultima ultimacies ultimacy ultimas ultimata ultimate ultimately ultimateness ultimatum ultimatums ultimo ultimogeniture ultra ultrabasic ultracareful ultracasual ultracautious ultracentrifugal ultracentrifugally ultracentrifugation ultracentrifugations ultracentrifuge ultracentrifuges ultrachic ultracivilized ultraclean ultracold ultracommercial ultracompact ultracompetent ultraconservatism ultraconservative ultraconservatives ultracontemporary ultraconvenient ultracool ultracritical ultrademocratic ultradense ultradian ultradistance ultradistant ultradry ultraefficient ultraenergetic ultraexclusive ultrafamiliar ultrafashionable ultrafast ultrafastidious ultrafeminine ultrafiche ultrafiches ultrafiltrate ultrafiltrating ultrafiltration ultrafiltrations ultrafine ultraglamorous ultrahazardous ultraheat ultraheavy ultrahigh ultrahip ultrahot ultrahuman ultraism ultraist ultraistic ultraists ultraleft ultraleftism ultraleftist ultraleftists ultraliberal ultraliberalism ultraliberals ultralight ultralights ultralightweight ultralow ultramafic ultramarathon ultramarathoner ultramarathoners ultramarathons ultramarine ultramarines ultramasculine ultramicro ultramicrofiche ultramicrofiches ultramicrometer ultramicrometers ultramicroscope ultramicroscopes ultramicroscopic ultramicroscopical ultramicroscopically ultramicroscopy ultramicrotome ultramicrotomes ultramicrotomy ultramilitant ultramilitants ultraminiature ultraminiaturization ultraminiaturizations ultraminiaturize ultraminiaturized ultraminiaturizes ultraminiaturizing ultramodern ultramodernism ultramodernist ultramodernistic ultramodernists ultramontane ultramontanes ultramontanism ultramontanist ultramontanists ultramundane ultranational ultranationalism ultranationalist ultranationalistic ultranationalists ultraorthodox ultraparadoxical ultrapatriotic ultraphysical ultrapowerful ultrapractical ultraprecise ultraprecision ultraprofessional ultraprogressive ultrapure ultraquiet ultraradical ultrarapid ultrarare ultrararefied ultrarational ultrarealism ultrarealist ultrarealistic ultrarealists ultrarefined ultrareliable ultrarespectable ultrarevolutionary ultrarich ultraright ultrarightist ultrarightists ultraromantic ultraroyalist ultraroyalists ultras ultrasafe ultrasecret ultrasegregationist ultrasegregationists ultrasensitive ultraserious ultrasharp ultrashort ultrasimple ultraslick ultraslow ultrasmall ultrasmart ultrasmooth ultrasoft ultrasonic ultrasonically ultrasonics ultrasonogram ultrasonograms ultrasonograph ultrasonographer ultrasonographers ultrasonographic ultrasonographs ultrasonography ultrasophisticated ultrasound ultrasounds ultrastructural ultrastructurally ultrastructure ultrastructures ultrathin ultravacuum ultraviolence ultraviolent ultraviolet ultraviolets ultravirile ultravirility ultravirus ultraviruses ultrawide ululant ululate ululated ululates ululating ululation ululations ulva ulysses um umatilla umatillas umbel umbellate umbellated umbellately umbellet umbellets umbellifer umbelliferous umbellifers umbellule umbellules umbels umber umbered umbering umbers umbilical umbilically umbilicals umbilicate umbilicated umbilication umbilications umbilici umbilicus umbilicuses umbles umbo umbonal umbonate umbones umbonic umbos umbra umbrae umbrage umbrageous umbrageously umbrageousness umbral umbras umbrella umbrellaless umbrellas umbrette umbrettes umbria umbrian umbrians umbriel umbundu umiak umiaks umlaut umlauted umlauting umlauts umm umnak ump umped umping umpirage umpirages umpire umpired umpires umpiring umps umpteen umpteenth umtata un una unabashed unabashedly unabated unabatedly unabbreviated unable unabraded unabridged unabsorbed unabsorbent unacademic unacademically unaccented unacceptability unacceptable unacceptably unaccepted unacclimated unacclimatized unaccommodated unaccommodating unaccompanied unaccomplished unaccountability unaccountable unaccountableness unaccountably unaccounted unaccredited unacculturated unaccustomed unaccustomedly unaccustomedness unachievable unachieved unacknowledged unacquainted unacquaintedness unactable unacted unactorish unadaptable unadapted unaddressed unadjudicated unadjusted unadmired unadmitted unadoptable unadorned unadult unadulterated unadulteratedly unadventurous unadvertised unadvised unadvisedly unadvisedness unaesthetic unaffected unaffectedly unaffectedness unaffecting unaffectionate unaffectionately unaffiliated unaffluent unaffordability unaffordable unaffordably unafraid unageing unaggressive unaging unai unaided unais unakin unakite unakites unalarmed unalaska unalienable unalienated unaligned unalike unalleviated unallied unallocated unallowable unalloyed unalloyedly unalluring unalterability unalterable unalterableness unalterably unaltered unambiguous unambiguously unambitious unambivalent unambivalently unamenable unamended unami unamiable unamis unamortized unamplified unamusing unanalyzable unanalyzably unanalyzed unanchored unaneled unanesthetized unanimated unanimity unanimous unanimously unanimousness unannotated unannounced unanswerability unanswerable unanswerableness unanswerably unanswered unanticipated unanticipatedly unapologetic unapologetically unapologizing unapparent unappealable unappealably unappealing unappealingly unappeasable unappeasably unappeased unappetizing unappetizingly unapplied unappreciable unappreciated unappreciation unappreciative unappreciatively unapprised unapproachability unapproachable unapproachableness unapproachably unappropriated unapproved unapt unaptly unaptness unarguable unarguably unarm unarmed unarming unarmored unarms unarrogant unarticulated unartistic unary unascertainable unascertained unashamed unashamedly unashamedness unasked unaspirated unassailability unassailable unassailableness unassailably unassailed unassembled unasserted unassertive unassertively unassertiveness unassigned unassimilable unassimilated unassisted unassociated unassuageable unassuaged unassuming unassumingly unassumingness unathletic unattached unattainability unattainable unattainableness unattainably unattained unattended unattenuated unattested unattractive unattractively unattractiveness unattributable unattributed unattuned unau unaudited unaus unauthentic unauthenticated unauthorized unautomated unavailability unavailable unavailing unavailingly unavailingness unaverage unavoidability unavoidable unavoidableness unavoidably unavowed unawake unawakened unawarded unaware unawarely unawareness unawares unawesome unbacked unbaked unbalance unbalanceable unbalanced unbalances unbalancing unballasted unban unbandage unbandaged unbandages unbandaging unbanned unbanning unbans unbaptized unbar unbarbed unbarbered unbarred unbarricaded unbarring unbars unbated unbearable unbearableness unbearably unbeatable unbeatably unbeaten unbeautiful unbeautifully unbecoming unbecomingly unbecomingness unbefitting unbegotten unbeholden unbeknown unbeknownst unbelief unbelievable unbelievably unbeliever unbelievers unbelieving unbelievingly unbelievingness unbelligerent unbeloved unbelted unbemused unbend unbendable unbending unbendingly unbends unbent unbeseeming unbiased unbiasedly unbiasedness unbiassed unbiblical unbid unbidden unbigoted unbilled unbind unbinding unbinds unbitted unbitten unbitter unbleached unblemished unblenched unblended unblessed unblessedness unblest unblinded unblinking unblinkingly unblock unblocked unblocking unblocks unblooded unblushing unblushingly unblushingness unbodied unbolt unbolted unbolting unbolts unbonneted unbookish unborn unbosom unbosomed unbosomer unbosomers unbosoming unbosoms unbought unbound unbounded unboundedly unboundedness unbowdlerized unbowed unbox unboxed unboxes unboxing unbrace unbraced unbraces unbracing unbracketed unbraid unbraided unbraiding unbraids unbrake unbraked unbrakes unbraking unbranched unbranded unbreachable unbreakable unbreakableness unbreakables unbreakably unbreathable unbred unbridgeable unbridgeably unbridged unbridle unbridled unbridledly unbridles unbridling unbriefed unbright unbrilliant unbroke unbroken unbrokenly unbrokenness unbruised unbrushed unbuckle unbuckled unbuckles unbuckling unbudgeable unbudgeably unbudgeted unbudging unbudgingly unbuffered unbuild unbuildable unbuilding unbuilds unbuilt unbulky unbundle unbundled unbundles unbundling unbundlings unburden unburdened unburdening unburdens unbureaucratic unburied unburnable unburned unburnt unbusinesslike unbusy unbuttered unbutton unbuttoned unbuttoning unbuttons uncage uncaged uncages uncaging uncalcified uncalcined uncalculated uncalculating uncalibrated uncalled uncalloused uncanceled uncandid uncandidly uncannier uncanniest uncannily uncanniness uncanny uncanonical uncap uncapitalized uncapped uncapping uncaps uncaptioned uncapturable uncared uncaring uncaringly uncarpeted uncase uncased uncases uncasing uncastrated uncataloged uncatchable uncatchy uncategorizable uncaught uncaused unceasing unceasingly unceasingness uncelebrated uncensored uncensorious uncensured unceremonious unceremoniously unceremoniousness uncertain uncertainly uncertainness uncertainties uncertainty uncertified unchain unchainable unchained unchaining unchains unchallengeable unchallengeably unchallenged unchallenging unchancy unchangeability unchangeable unchangeableness unchangeably unchanged unchanging unchangingly unchangingness unchanneled unchaperoned uncharacteristic uncharacteristically uncharacterized uncharged uncharismatic uncharitable uncharitableness uncharitably uncharming uncharted unchartered unchaste unchastely unchasteness unchaster unchastest unchastity unchauvinistic uncheck uncheckable unchecked unchecking unchecks uncheerful unchewable unchewed unchic unchildlike unchivalrous unchivalrously unchlorinated unchoke unchoked unchokes unchoking unchoreographed unchristened unchristian unchronicled unchronological unchurch unchurched unchurches unchurching unchurchly unci uncial uncially uncials unciform unciforms unciliated uncinaria uncinarias uncinariasis uncinate uncinematic uncirculated uncircumcised uncircumcision uncircumcisions uncivil uncivilized uncivilizedly uncivilizedness uncivilly uncivilness unclad unclaimed unclamp unclamped unclamping unclamps unclarified unclarities unclarity unclasp unclasped unclasping unclasps unclassical unclassifiable unclassified uncle unclean uncleaned uncleaner uncleanest uncleanlier uncleanliest uncleanliness uncleanly uncleanness unclear unclearer unclearest unclearly unclearness uncleless unclench unclenched unclenches unclenching uncles unclichéd unclimbable unclimbableness unclinch unclinched unclinches unclinching unclip unclipped unclipping unclips uncloak uncloaked uncloaking uncloaks unclog unclogged unclogging unclogs unclose unclosed uncloses unclosing unclothe unclothed unclothes unclothing unclouded uncloudedly uncloying unclubbable unclutter uncluttered uncluttering unclutters uncoalesce uncoalesced uncoalesces uncoalescing uncoated uncoating uncock uncocked uncocking uncocks uncoded uncodified uncoerced uncoercive uncoercively uncoffin uncoffined uncoffining uncoffins uncoil uncoiled uncoiling uncoils uncoined uncollected uncollectible uncolored uncombative uncombed uncombined uncomely uncomfortable uncomfortableness uncomfortably uncomforted uncomic uncomment uncommented uncommenting uncomments uncommercial uncommercialized uncommitted uncommon uncommoner uncommonest uncommonly uncommonness uncommunicable uncommunicative uncommunicatively uncommunicativeness uncompahgre uncompassionate uncompelled uncompelling uncompensated uncompetitive uncompetitively uncompetitiveness uncomplacent uncomplaining uncomplainingly uncompleted uncomplicated uncomplimentary uncompounded uncomprehended uncomprehending uncomprehendingly uncompress uncompressed uncompresses uncompressing uncompromisable uncompromising uncompromisingly uncompromisingness uncomputerized unconcealed unconceivable unconceivableness unconceivably unconcern unconcerned unconcernedly unconcernedness unconcluded uncondensed unconditional unconditionality unconditionally unconditionalness unconditioned unconditionedness unconfessed unconfident unconfidently unconfined unconfirmed unconformability unconformable unconformableness unconformably unconformities unconformity unconfounded unconfuse unconfused unconfuses unconfusing uncongealed uncongenial uncongeniality unconjugated unconnected unconnectedly unconnectedness unconquerable unconquerably unconquered unconscionability unconscionable unconscionableness unconscionably unconscious unconsciously unconsciousness unconsecrated unconsidered unconsolidated unconstitutional unconstitutionality unconstitutionally unconstrained unconstraint unconstricted unconstructed unconstructive unconsumed unconsummated uncontainable uncontaminated uncontemplated uncontemporary uncontentious uncontested uncontracted uncontradicted uncontrived uncontrollability uncontrollable uncontrollableness uncontrollably uncontrolled uncontrolledness uncontroversial uncontroversially unconventional unconventionality unconventionally unconverted unconvertible unconvinced unconvincing unconvincingly unconvincingness unconvoyed uncooked uncool uncooled uncooperative uncooperatively uncooperativeness uncoordinated uncoordinatedly uncopyrightable uncork uncorked uncorking uncorks uncorrectable uncorrected uncorrelated uncorroborated uncorrupt uncorrupted uncorrupting uncorseted uncountable uncounted uncouple uncoupled uncoupler uncouplers uncouples uncoupling uncourageous uncouth uncouthly uncouthness uncovenanted uncover uncovered uncovering uncovers uncoy uncracked uncrate uncrated uncrates uncrating uncrazy uncreated uncreative uncredentialed uncredited uncrewed uncrippled uncritical uncritically uncropped uncross uncrossable uncrossed uncrosses uncrossing uncrowded uncrown uncrowned uncrowning uncrowns uncrumple uncrumpled uncrumples uncrumpling uncrushable uncrushed uncrystallized unction unctuosity unctuous unctuously unctuousness uncuff uncuffed uncuffing uncuffs uncultivable uncultivated uncultured uncurbed uncured uncurious uncurl uncurled uncurling uncurls uncurrent uncurtained uncus uncustomarily uncustomary uncut uncute uncuttable uncynical uncynically und undamaged undamped undanceable undated undauntable undaunted undauntedly undauntedness undead undebatable undebatably undecadent undecayed undeceivable undeceivably undeceive undeceived undeceives undeceiving undecidability undecidable undecided undecidedly undecidedness undecideds undecillion undecillions undecipherable undeciphered undecked undeclared undecomposed undecorated undecylenic undedicated undefeatable undefeated undefended undefiled undefinable undefined undeflected undefoliated undeformed undelegated undelete undeleted undeliverable undeliverably undelivered undeluded undemanding undemocratic undemocratically undemonstrated undemonstrative undemonstratively undemonstrativeness undeniable undeniableness undeniably undenominational undented undependability undependable under underachieve underachieved underachievement underachiever underachievers underachieves underachieving underact underacted underacting underactive underactivity underacts underage underaged underappreciated underarm underarms underassessment underbellies underbelly underbid underbidder underbidders underbidding underbids underbodies underbody underboss underbosses underbought underbracing underbred underbrim underbrims underbrush underbudgeted underbuy underbuying underbuys undercapitalization undercapitalizations undercapitalize undercapitalized undercapitalizes undercapitalizing undercard undercards undercarriage undercarriages undercharge undercharged undercharges undercharging underclass underclasses underclassman underclassmen underclothes underclothing undercoat undercoated undercoating undercoats undercook undercooked undercooking undercooks undercool undercooled undercooling undercools undercount undercounted undercounting undercounts undercover undercroft undercrofts undercurrent undercurrents undercut undercuts undercutting underdeveloped underdevelopment underdid underdo underdoes underdog underdogs underdoing underdone underdrawers underdress underdressed underdresses underdressing underdrive underdrives undereducated underemphasis underemphasize underemphasized underemphasizes underemphasizing underemployed underemployment underendow underendowed underendowing underendowment underendows underestimate underestimated underestimates underestimating underestimation underestimations underexpose underexposed underexposes underexposing underexposure underexposures underfed underfeed underfeeding underfeeds underfinanced underflow underflows underfoot underfund underfunded underfunding underfunds underfur underfurs undergarment undergarments undergird undergirded undergirding undergirds undergirt underglaze underglazes undergo undergoes undergoing undergone undergrad undergrads undergraduate undergraduates underground undergrounded undergrounder undergrounders undergrounding undergrounds undergrown undergrowth underhair underhairs underhand underhanded underhandedly underhandedness underhung underinflated underinflation underinsurance underinsure underinsured underinsures underinsuring underinvestment underkill underlaid underlain underlay underlaying underlayment underlayments underlays underlet underlets underletting underlie underlies underline underlined underlines underling underlings underlining underlinings underlip underlips underlying underlyingly undermanned undermine undermined undermines undermining undermodulate undermodulated undermodulates undermodulating undermodulation undermodulations undermost underneath underneaths undernourish undernourished undernourishes undernourishing undernourishment undernutrition undernutritions underpaid underpainting underpants underpart underparts underpass underpasses underpay underpaying underpayment underpayments underpays underperform underperformance underperformances underperformed underperformer underperformers underperforming underperforms underpin underpinned underpinning underpinnings underpins underplay underplayed underplaying underplays underplot underplots underpopulated underpopulation underpowered underprepared underprice underpriced underprices underpricing underprivileged underproduce underproduced underproduces underproducing underproduction underproductions underproductive underproof underprop underpropped underpropping underprops underpublicized underquote underquoted underquotes underquoting underran underrate underrated underrates underrating underreact underreacted underreacting underreaction underreactions underreacts underreport underreported underreporting underreports underrepresent underrepresentation underrepresentations underrepresented underrepresenting underrepresents underrun underrunning underruns undersaturated underscore underscored underscores underscoring undersea underseas undersecretariat undersecretariats undersecretaries undersecretary undersell underseller undersellers underselling undersells underserve underserved underserves underserving underset undersets undersexed undershirt undershirted undershirts undershoot undershooting undershoots undershorts undershot undershrub undershrubs underside undersides undersign undersigned undersigning undersigns undersize undersized underskirt underskirts undersleeve undersleeves underslung undersoil undersoils undersold underspin underspins understaff understaffed understaffing understaffs understand understandability understandable understandably understanding understandingly understandings understands understate understated understatedly understatement understatements understates understating understeer understeered understeering understeers understood understories understory understrapper understrappers understrata understratum understratums understrength understructure understructures understudied understudies understudy understudying undersubscribe undersubscribed undersubscribes undersubscribing undersubscription undersubscriptions undersupplied undersupplies undersupply undersupplying undersurface undersurfaces undertake undertaken undertaker undertakers undertakes undertaking undertakings undertenant undertenants underthings underthrust underthrusting underthrusts undertint undertints undertone undertones undertook undertow undertows undertrick undertricks undertrump undertrumped undertrumping undertrumps underused underutilization underutilize underutilized underutilizes underutilizing undervaluation undervaluations undervalue undervalued undervalues undervaluing undervest undervests underwater underway underwear underweight underwent underwhelm underwhelmed underwhelming underwhelms underwing underwings underwood underwoods underwool underwools underworld underworlds underwrite underwriter underwriters underwrites underwriting underwritten underwrote undescended undescribable undeserved undeservedly undeserving undeservingly undesignated undesigning undesirability undesirable undesirableness undesirables undesirably undesired undestroyed undetached undetectable undetectably undetected undeterminable undetermined undeterred undeveloped undeviating undeviatingly undiagnosable undiagnosed undialectical undid undidactic undies undifferentiated undiffused undigested undigestible undignified undiluted undiminished undimmed undimpled undine undines undiplomatic undiplomatically undirected undiscerning undischarged undisciplined undisclosed undiscouraged undiscoverable undiscovered undiscriminating undiscussed undisguised undisguisedly undismayed undisposed undisputable undisputed undisputedly undisrupted undissociated undissolved undistinguished undistinguishing undistorted undistracted undistributed undisturbed undivided undividedly undo undoable undocile undock undocked undocking undocks undoctored undoctrinaire undocumented undocumenteds undoer undoers undoes undogmatic undogmatically undoing undomestic undomesticated undone undotted undouble undoubled undoubles undoubling undoubtable undoubted undoubtedly undoubting undrained undramatic undramatically undramatized undrape undraped undrapes undraping undraw undrawing undrawn undraws undreamed undreamt undress undressed undresses undressing undrew undrilled undrinkable undrunk undubbed undue undulant undulate undulated undulates undulating undulation undulations undulatory undulled unduly unduplicated undusted undutiful undutifully undutifulness undyed undying undyingly undynamic uneager unearmarked unearned unearth unearthed unearthing unearthlier unearthliest unearthliness unearthly unearths unease uneasier uneasiest uneasily uneasiness uneasy uneatable uneaten uneccentric unecological uneconomic uneconomical uneconomically unedifying unedifyingly unedited uneducable uneducated unelaborate unelaborated unelectable unelected unelectrified unembarrassed unembellished unembittered unemotional unemotionally unemphatic unemphatically unempirical unemployability unemployable unemployables unemployed unemployment unenchanted unenclosed unencouraging unencumbered unendearing unending unendingly unendorsed unendurable unendurableness unendurably unenforceable unenforced unengaged unenlarged unenlightened unenlightening unenriched unenterprising unentertaining unenthusiastic unenthusiastically unenviable unenvied unenvious unequal unequaled unequalize unequalized unequalizes unequalizing unequalled unequally unequals unequipped unequivocably unequivocal unequivocally unerotic unerring unerringly unescapable unesco unescorted unessential unessentials unestablished unethical unethically unevaluated uneven unevener unevenest unevenly unevenness uneventful uneventfully uneventfulness unexacting unexaggerated unexamined unexampled unexcelled unexceptionable unexceptionableness unexceptionably unexceptional unexceptionally unexcitable unexcited unexciting unexcused unexecuted unexercised unexhausted unexotic unexpanded unexpected unexpectedly unexpectedness unexpended unexpired unexplainable unexplainably unexplained unexploded unexploited unexplored unexposed unexpressed unexpressive unexpressively unexpressiveness unexpurgated unextraordinary unfading unfadingly unfailing unfailingly unfailingness unfair unfairer unfairest unfairly unfairness unfaith unfaithful unfaithfully unfaithfulness unfaked unfallen unfalsifiable unfaltering unfalteringly unfamiliar unfamiliarity unfamiliarly unfamous unfancy unfashionable unfashionableness unfashionably unfasten unfastened unfastening unfastens unfastidious unfathered unfathomable unfathomed unfavorable unfavorableness unfavorably unfavorite unfazed unfeasibility unfeasible unfecundated unfeeling unfeelingly unfeelingness unfeigned unfeignedly unfelt unfeminine unfenced unfermented unfertile unfertilized unfetter unfettered unfettering unfetters unfilial unfilially unfilled unfiltered unfindable unfinished unfired unfit unfitly unfitness unfits unfitted unfitting unfittingly unfix unfixable unfixed unfixes unfixing unflagging unflaggingly unflamboyant unflappability unflappable unflappably unflapped unflashy unflattering unflatteringly unflavored unflawed unfledged unflinching unflinchingly unflinchingness unflustered unflyable unfocused unfocussed unfold unfolded unfolding unfoldment unfolds unfond unforced unforeseeable unforeseeably unforeseen unforested unforgettability unforgettable unforgettableness unforgettably unforgivable unforgivably unforgiving unforgivingness unforgotten unforked unformatted unformed unformulated unforthcoming unfortified unfortunate unfortunately unfortunateness unfortunates unfossiliferous unfound unfounded unfoundedly unfoundedness unframed unfree unfreedom unfreeze unfreezes unfreezing unfrequented unfriended unfriendlier unfriendliest unfriendliness unfriendly unfrivolous unfrock unfrocked unfrocking unfrocks unfrosted unfroze unfrozen unfruitful unfruitfully unfruitfulness unfulfillable unfulfilled unfulfilling unfunded unfunny unfurl unfurled unfurling unfurls unfurnished unfused unfussily unfussy ungainlier ungainliest ungainliness ungainly ungallant ungallantly ungarnished ungava ungenerosity ungenerous ungenerously ungenial ungenteel ungentle ungentlemanly ungentrified ungerminated ungifted ungimmicky ungird ungirded ungirding ungirds ungirt unglamorized unglamorous unglamorously unglazed unglue unglued unglues ungluing ungodlier ungodliest ungodliness ungodly ungot ungotten ungovernable ungovernableness ungovernably ungoverned ungraceful ungracefully ungracious ungraciously ungraciousness ungraded ungrammatical ungrammaticality ungrammatically ungraspable ungrateful ungratefully ungratefulness ungratified unground ungrounded ungrouped ungrudging ungrudgingly ungual unguard unguarded unguardedly unguardedness unguarding unguards unguent unguentary unguents ungues unguessable unguiculate unguiculated unguided unguis ungula ungulate ungulates unguligrade unguligrades unhackneyed unhallow unhallowed unhallowing unhallows unhampered unhand unhanded unhandier unhandiest unhandily unhandiness unhanding unhands unhandsome unhandsomely unhandsomeness unhandy unhappier unhappiest unhappily unhappiness unhappinesses unhappy unhardened unharmed unharmonious unharness unharnessed unharnesses unharnessing unharvested unhatched unhealed unhealthful unhealthier unhealthiest unhealthily unhealthiness unhealthy unheard unhearing unheated unhedged unheeded unheeding unheedingly unhelpful unhelpfully unheralded unheroic unhesitant unhesitating unhesitatingly unhidden unhighlight unhighlighted unhighlighting unhighlights unhindered unhinge unhinged unhinges unhinging unhip unhistorical unhitch unhitched unhitches unhitching unholier unholiest unholily unholiness unholy unhomogenized unhonored unhood unhooded unhooding unhoods unhook unhooked unhooking unhooks unhoped unhopeful unhorse unhorsed unhorses unhorsing unhoused unhouseled unhumorous unhurried unhurriedly unhurt unhydrolyzed unhygienic unhyphenated unhysterical unhysterically unialgal uniat uniate uniaxial uniaxially unicameral unicamerally unicef unicellular unicellularity unicolor unicorn unicorns unicostate unicuspid unicuspids unicycle unicycles unicyclist unicyclists unidentifiable unidentifiably unidentified unideological unidimensional unidimensionality unidiomatic unidirectional unidirectionally unifactorial unifiable unification unifications unified unifier unifiers unifies unifilar uniflow unifoliate unifoliolate uniform uniformed uniforming uniformitarian uniformitarianism uniformitarians uniformity uniformly uniformness uniforms unify unifying unignorable unilateral unilateralism unilateralisms unilateralist unilateralists unilaterally unilineal unilinear unilingual unilingually uniliteral unilluminated unilluminating unillusioned unillustrated unilobar unilocular unimaginable unimaginably unimaginative unimaginatively unimagined unimak unimmunized unimpaired unimpassioned unimpeachable unimpeachably unimpeded unimplemented unimportance unimportant unimposing unimpressed unimpressionable unimpressive unimpressively unimproved unincorporated unindexed unindicted unindustrialized uninfected uninflammable uninflated uninflected uninfluenced uninformative uninformatively uninformed uningratiating uninhabitability uninhabitable uninhabited uninhibited uninhibitedly uninhibitedness uninitialized uninitiate uninitiated uninitiates uninjured uninoculated uninominal uninspected uninspired uninspiring uninstalled uninstructed uninstructive uninsulated uninsurability uninsurable uninsured uninsureds unintegrated unintellectual unintelligence unintelligent unintelligently unintelligibility unintelligible unintelligibleness unintelligibly unintended unintentional unintentionally uninterest uninterested uninterestedly uninterestedness uninteresting uninterestingly uninterrupted uninterruptedly unintimidated unintuitive uninucleate uninventive uninvestigated uninvited uninviting uninvitingly uninvolved union unionism unionist unionistic unionists unionization unionizations unionize unionized unionizer unionizers unionizes unionizing unions uniparental uniparentally uniparous uniped unipersonal uniplanar unipolar unipolarity unipotent unique uniquely uniqueness unironically unirradiated unirrigated uniserial uniseriate unisex unisexual unisexuality unisexually unison unisonant unisonous unisons unissued unit unitage unitard unitards unitarian unitarianism unitarians unitarily unitary unite united unitedly unitedness uniter uniters unites unities uniting unitive unitization unitizations unitize unitized unitizes unitizing unitrust unitrusts units unity univalent univalents univalve univalves univariate universal universalism universalist universalistic universalists universalities universality universalizability universalization universalizations universalize universalized universalizes universalizing universally universalness universals universe universes universities university univocal univocally univocals unix unjacketed unjaded unjoined unjoint unjointed unjointing unjoints unjust unjustifiable unjustifiably unjustified unjustly unjustness unjustnesses unkempt unkennel unkenneled unkenneling unkennelled unkennelling unkennels unkept unkind unkinder unkindest unkindlier unkindliest unkindliness unkindly unkindness unkindnesses unkink unkinked unkinking unkinks unknit unknits unknitted unknitting unknot unknots unknotted unknotting unknowability unknowable unknowableness unknowably unknowing unknowingly unknowingness unknowledgeable unknown unknowns unkosher unlabeled unlabored unlace unlaced unlaces unlacing unlade unladed unladen unlades unlading unladylike unlaid unlamented unlash unlashed unlashes unlashing unlatch unlatched unlatches unlatching unlaundered unlawful unlawfully unlawfulness unlay unlaying unlays unlead unleaded unleading unleads unlearn unlearnable unlearned unlearnedly unlearning unlearns unlearnt unleash unleashed unleashes unleashing unleavened unless unlettered unleveled unliberated unlicensed unlicked unlighted unlikable unlike unlikelier unlikeliest unlikelihood unlikeliness unlikely unlikeness unlimber unlimbered unlimbering unlimbers unlimited unlimitedly unlimitedness unlined unlink unlinked unlinking unlinks unliquidated unlisted unlistenable unlit unliterary unlivable unlive unlived unlives unliving unload unloaded unloader unloaders unloading unloads unlocalized unlock unlocked unlocking unlocks unlooked unloose unloosed unloosen unloosened unloosening unloosens unlooses unloosing unlovable unloved unlovelier unloveliest unloveliness unlovely unloving unluckier unluckiest unluckily unluckiness unlucky unlyrical unmacho unmade unmagnified unmake unmakes unmaking unmalicious unmaliciously unman unmanageability unmanageable unmanageably unmanaged unmanipulated unmanlier unmanliest unmanliness unmanly unmanned unmannered unmanneredly unmannerliness unmannerly unmanning unmans unmapped unmarked unmarketable unmarred unmarriageable unmarried unmarrieds unmasculine unmask unmasked unmasking unmasks unmatchable unmatched unmated unmeaning unmeaningly unmeant unmeasurable unmeasured unmechanical unmechanically unmechanized unmediated unmedicated unmeet unmelodic unmelodious unmelodiousness unmemorable unmemorably unmentionable unmentionableness unmentionables unmentionably unmentioned unmerciful unmercifully unmercifulness unmerited unmeritorious unmerry unmeshed unmet unmetabolized unmethodical unmethodically unmilitary unmilled unmindful unmindfully unmindfulness unmined unmingled unmissed unmistakable unmistakably unmitigated unmitigatedly unmitigatedness unmix unmixable unmixed unmixedly unmixes unmixing unmodernized unmodified unmodish unmold unmolded unmolding unmolds unmolested unmonitored unmoor unmoored unmooring unmoors unmoral unmorality unmorally unmortise unmortised unmortises unmortising unmotivated unmounted unmovable unmoved unmoving unmuffle unmuffled unmuffles unmuffling unmurmuring unmusical unmusically unmusicalness unmuzzle unmuzzled unmuzzles unmuzzling unmyelinated unnail unnailed unnailing unnails unnamable unnameable unnamed unnatural unnaturally unnaturalness unnecessarily unnecessary unneeded unnegotiable unnerve unnerved unnerves unnerving unnervingly unneurotic unnewsworthy unnilhexium unnilpentium unnilquadium unnilquintium unnormalized unnoted unnoticeable unnoticeably unnoticed unnoticing unnourished unnourishing unnumbered unobjectionable unobscured unobservable unobservant unobserved unobserving unobstructed unobtainable unobtrusive unobtrusively unobtrusiveness unoccupied unoffending unofficial unofficially unopenable unopened unopposed unordered unordinary unorganized unoriginal unornament unornamented unornamenting unornaments unorthodox unorthodoxly unorthodoxy unostentatious unostentatiously unostentatiousness unowned unoxygenated unpack unpacked unpacker unpackers unpacking unpacks unpadded unpaged unpaginated unpaid unpainted unpaired unpalatability unpalatable unpalatably unparalleled unparasitized unpardonable unparliamentary unparsed unparticular unpartisan unpassable unpasteurized unpastoral unpatentable unpatriotic unpatriotically unpatronizing unpaved unpedantic unpeeled unpeg unpegged unpegging unpegs unpeople unpeopled unpeoples unpeopling unperceived unperceiving unperceptive unperfect unperfected unperforated unperformable unperformed unperson unpersuaded unpersuasive unperturbed unphysical unpick unpicked unpicking unpicks unpicturesque unpile unpiled unpiles unpiling unpin unpinned unpinning unpins unpitying unpityingly unplaced unplanned unplanted unplausible unplayable unpleasant unpleasantly unpleasantness unpleasantries unpleasantry unpleased unpleasing unplowed unplug unplugged unplugging unplugs unplumbed unpoetic unpolarized unpoliced unpolished unpolitical unpolled unpolluted unpopular unpopularity unpopulated unposed unpractical unpracticed unprecedented unprecedentedly unpredictability unpredictable unpredictables unpredictably unpredicted unpregnant unprejudiced unpremeditated unpremeditatedly unprepared unpreparedly unpreparedness unprepossessing unprepossessingly unpressed unpressured unpressurized unpresuming unpretending unpretentious unpretentiously unpretentiousness unpretty unpriced unprimed unprincipled unprincipledness unprintable unprintably unprivileged unproblematic unprocessed unprocurable unproduced unproductive unproductively unproductiveness unprofaned unprofessed unprofessional unprofessionalism unprofessionally unprofitability unprofitable unprofitableness unprofitably unprogrammable unprogrammed unprogressive unprolific unpromising unpromisingly unprompted unpronounceable unpronounced unpropitious unpropitiously unprosperous unprotected unprovable unproved unproven unprovided unprovidedly unprovoked unpruned unpublicized unpublishable unpublished unpunctual unpunctuality unpunctuated unpunished unpurified unputdownable unqualified unqualifiedly unquantifiable unquantified unquenchable unquenchably unquenched unquestionability unquestionable unquestionableness unquestionably unquestioned unquestioning unquestioningly unquiet unquieter unquietest unquietly unquietness unquotable unquote unquoted unraised unranked unrated unravel unraveled unraveling unravelled unravelling unravels unravished unreachability unreachable unreachably unreached unread unreadability unreadable unreadier unreadiest unreadily unreadiness unready unreal unrealistic unrealistically unrealities unreality unrealizable unrealized unreason unreasonable unreasonableness unreasonably unreasoned unreasoning unreasoningly unreassuringly unrecalled unreceptive unreckonable unreclaimable unreclaimed unrecognizable unrecognizableness unrecognizably unrecognized unrecognizing unrecompensed unreconcilable unreconciled unreconstructed unrecorded unrecoverable unrecovered unrectified unrecyclable unredeemable unredeemed unredressed unreduced unreel unreeled unreeling unreels unreeve unreeved unreeves unreeving unrefined unreflecting unreflectingly unreflective unreflectively unreformed unrefrigerated unregenerable unregeneracy unregenerate unregenerately unregimented unregistered unregulated unrehearsed unreinforced unrelated unrelaxed unreleased unrelenting unrelentingly unreliability unreliable unreliableness unreliably unrelieved unrelievedly unreligious unreluctant unremarkable unremarkably unremarked unremembered unreminiscent unremitting unremittingly unremittingness unremovable unremunerated unremunerative unrenowned unrepaired unrepeatable unrepentant unrepentantly unreported unrepresentative unrepresentativeness unrepresented unrepressed unreproved unrequited unrequitedly unreserve unreserved unreservedly unreservedness unresistant unresisting unresistingly unresolvable unresolved unrespectable unresponsive unresponsively unresponsiveness unrest unrestful unrestored unrestrained unrestrainedly unrestrainedness unrestraint unrestraints unrestricted unrestrictedly unretouched unreturnable unrevealed unrevealing unrevealingly unreviewable unreviewed unrevised unrevolutionary unrewarded unrewarding unrhetorical unrhymed unrhythmic unridable unriddle unriddled unriddler unriddlers unriddles unriddling unrifled unrig unrigged unrigging unrighteous unrighteously unrighteousness unrightfully unrigs unrip unripe unripened unripeness unriper unripest unripped unripping unrips unrivaled unrivalled unrobed unroll unrolled unrolling unrolls unromantic unromantically unromanticized unroof unroofed unroofing unroofs unroot unrooted unrooting unroots unround unrounded unrounding unrounds unrove unroven unruffled unruled unrulier unruliest unruliness unruly unrushed uns unsacred unsaddle unsaddled unsaddles unsaddling unsafe unsafer unsafest unsaid unsalable unsalaried unsalted unsalvageable unsanctified unsanctioned unsanitary unsatisfactorily unsatisfactoriness unsatisfactory unsatisfied unsatisfiedness unsatisfying unsatisfyingly unsaturate unsaturated unsaturates unsaved unsavorily unsavoriness unsavory unsay unsayable unsayables unsaying unsays unscalable unscarred unscathed unscented unscheduled unscholarly unschooled unscientific unscientifically unscramble unscrambled unscrambler unscramblers unscrambles unscrambling unscratched unscreened unscrew unscrewed unscrewing unscrews unscripted unscriptural unscrupulous unscrupulously unscrupulousness unseal unsealed unsealing unseals unseam unseamed unseaming unseams unsearchable unsearchably unseasonable unseasonableness unseasonably unseasoned unseat unseated unseating unseats unseaworthy unsecured unseeded unseeing unseeingly unseemlier unseemliest unseemliness unseemly unseen unsegmented unsegregated unselected unselective unselectively unself unselfconscious unselfconsciously unselfconsciousness unselfish unselfishly unselfishness unsell unsellable unselling unsells unsensational unsensitized unsent unsentimental unsentimentally unseparated unserious unseriousness unserved unserviceable unset unsetting unsettle unsettled unsettledness unsettlement unsettles unsettling unsettlingly unsew unsewed unsewing unsewn unsex unsexed unsexes unsexing unsexual unsexy unshackle unshackled unshackles unshackling unshaded unshakable unshakably unshaken unshaped unshapely unshapen unshared unsharp unsharpened unshaved unshaven unsheathe unsheathed unsheathes unsheathing unshed unshell unshelled unshelling unshells unsheltered unshielded unshift unshifted unshifting unshifts unship unshipped unshipping unships unshockable unshod unshorn unshowy unshrinking unsight unsighted unsighting unsightlier unsightliest unsightliness unsightly unsights unsigned unsinkable unsized unskilled unskillful unskillfully unskillfulness unslakable unslaked unsleeping unsling unslinging unslings unslung unsmart unsmiling unsmilingly unsmoothed unsnag unsnagged unsnagging unsnags unsnap unsnapped unsnapping unsnaps unsnarl unsnarled unsnarling unsnarls unsociability unsociable unsociableness unsociably unsocial unsocially unsoiled unsold unsolder unsoldered unsoldering unsolders unsoldierly unsolicited unsolvable unsolved unsophisticated unsophisticatedly unsophisticatedness unsophistication unsorted unsought unsound unsounded unsounder unsoundest unsoundly unsoundness unsowed unsown unsparing unsparingly unsparingness unspeak unspeakable unspeakableness unspeakably unspeaking unspeaks unspecialized unspecifiable unspecific unspecified unspectacular unspectacularly unspent unsphere unsphered unspheres unsphering unspiritual unsplit unspoiled unspoilt unspoke unspoken unsporting unsportsmanlike unspotted unspottedness unsprayed unsprung unstable unstableness unstabler unstablest unstably unstained unstamped unstandardized unstapled unstaring unstartling unstated unstaunched unstayed unsteadied unsteadier unsteadies unsteadiest unsteadily unsteadiness unsteady unsteadying unsteel unsteeled unsteeling unsteels unstep unstepped unstepping unsteps unsterile unsterilized unstick unsticking unsticks unstilted unstinted unstinting unstintingly unstirred unstitch unstitched unstitches unstitching unstop unstoppable unstoppably unstopped unstopper unstopping unstops unstrained unstrap unstrapped unstrapping unstraps unstratified unstressed unstriated unstring unstringing unstrings unstructured unstrung unstuck unstudied unstuffy unstylish unsubdued unsubscribe unsubscribed unsubscribes unsubscribing unsubsidized unsubstantial unsubstantiality unsubstantially unsubstantiated unsubtle unsubtly unsuccess unsuccessful unsuccessfully unsuccessfulness unsuitability unsuitable unsuitableness unsuitably unsuited unsullied unsung unsupervised unsupportable unsupported unsuppressed unsure unsurpassable unsurpassed unsurprised unsurprising unsurprisingly unsusceptible unsuspected unsuspectedly unsuspecting unsuspectingly unsuspended unsuspicious unsustainable unswathe unswathed unswathes unswathing unswayable unswear unswearing unswears unsweetened unswerving unswervingly unswore unsworn unsymmetrical unsymmetrically unsympathetic unsympathetically unsynchronized unsystematic unsystematically unsystematized untactful untagged untainted untalented untamable untamed untangle untangled untangles untangling untanned untapped untarnished untaught untaxed unteach unteachable unteaches unteaching untechnical untellable untempered untenability untenable untenableness untenably untenanted untended untented untenured untestable untested untether untethered untethering untethers unthankful unthankfully unthankfulness unthawed unthawing untheoretical untheorized unthink unthinkability unthinkable unthinkableness unthinkably unthinking unthinkingly unthinkingness unthinks unthought unthread unthreaded unthreading unthreads unthreatening unthrift unthrifty unthrone unthroned unthrones unthroning untidier untidiest untidily untidiness untidy untie untied unties until untillable untilled untimelier untimeliest untimeliness untimely untiring untiringly untitled unto untogether untold untouchability untouchable untouchables untouchably untouched untoward untowardly untowardness untraceable untracked untraditional untraditionally untrained untrammeled untransformed untranslatability untranslatable untranslated untraveled untraversed untread untreading untreads untreatable untreatably untreated untrendy untried untrimmed untrod untrodden untroubled untroubledness untrue untruer untruest untruly untruss untrussed untrusses untrussing untrusting untrustworthily untrustworthiness untrustworthy untruth untruthful untruthfully untruthfulness untruths untuck untucked untucking untucks untufted untune untuned untunes untuning unturned untutored untwine untwined untwines untwining untwist untwisted untwisting untwists untying untypical untypically ununderstandable unusable unused unusual unusually unusualness unutilized unutterable unutterableness unutterably unuttered unvaccinated unvalued unvanquished unvaried unvarnished unvarying unvaryingly unveil unveiled unveiling unveilings unveils unventilated unverbalized unverifiable unverified unversed unvested unviable unviewed unvigilant unviolated unvisited unvocal unvoice unvoiced unvoices unvoicing unwanted unwarier unwariest unwarily unwariness unwarlike unwarned unwarrantable unwarrantably unwarranted unwarrantedly unwary unwashed unwashedness unwatchable unwatched unwatchful unwavering unwaveringly unwaxed unweakened unweaned unwearable unwearied unweariedly unweathered unweave unweaves unweaving unwed unwedded unweeting unweetingly unweight unweighted unweighting unweights unwelcome unwell unwept unwhite unwholesome unwholesomely unwholesomeness unwieldier unwieldiest unwieldily unwieldiness unwieldy unwilled unwilling unwillingly unwillingness unwind unwinding unwinds unwinnable unwire unwired unwires unwiring unwisdom unwisdoms unwise unwisely unwiser unwisest unwish unwished unwishes unwishing unwitting unwittingly unwomanly unwon unwonted unwontedly unwontedness unworkability unworkable unworkableness unworkably unworked unworldlier unworldliest unworldliness unworldly unworn unworried unworthier unworthiest unworthily unworthiness unworthy unwound unwounded unwove unwoven unwrap unwrapped unwrapping unwraps unwreathe unwreathed unwreathes unwreathing unwrinkled unwritten unyielding unyieldingly unyieldingness unyoke unyoked unyokes unyoking unyoung unzip unzipped unzipping unzips up upanishad upanishadic upanishads upas upbeat upbeats upbraid upbraided upbraider upbraiders upbraiding upbraidingly upbraids upbringing upbringings upbuild upbuilder upbuilders upbuilding upbuilds upbuilt upcast upcasts upchuck upchucked upchucking upchucks upcoast upcoming upcountry update updated updates updating updo updos updraft updrafts upend upended upending upends upfield upfront upgrade upgraded upgrades upgrading upgrowth upgrowths upheaval upheavals upheave upheaved upheaver upheavers upheaves upheaving upheld uphill uphills uphold upholder upholders upholding upholds upholster upholstered upholsterer upholsterers upholsteries upholstering upholsters upholstery upityness upkeep upland uplander uplanders uplands uplift uplifted uplifter uplifters uplifting uplifts uplink uplinks upload uploaded uploading uploads upmanship upmanships upmarket upmost upolu upon upped upper uppercase uppercased uppercases uppercasing upperclassman upperclassmen uppercut uppercuts uppermost upperpart upperparts uppers upping uppish uppishly uppishness uppitiness uppity uppityness uppsala upraise upraised upraises upraising uprate uprated uprates uprating uprear upreared uprearing uprears upright uprightly uprightness uprights uprise uprisen upriser uprisers uprises uprising uprisings upriver uproar uproarious uproariously uproariousness uproars uproot uprooted uprootedness uprooter uprooters uprooting uproots uprose uprush uprushes ups upscale upscaled upscales upscaling upset upsets upsetter upsetters upsetting upsettingly upshift upshifted upshifting upshifts upshot upshots upside upsides upsilon upsmanship upsprang upspring upspringing upsprings upsprung upstage upstaged upstager upstagers upstages upstaging upstairs upstanding upstandingness upstart upstarted upstarting upstarts upstate upstater upstaters upstream upstroke upstrokes upsurge upsurged upsurges upsurging upsweep upsweeping upsweeps upswept upswing upswings uptake uptakes uptempo uptempos upthrow upthrows upthrust upthrusting upthrusts uptick upticks uptight uptightness uptilt uptilted uptilting uptilts uptime uptimes uptown uptowner uptowners uptowns uptrend uptrended uptrending uptrends upturn upturned upturning upturns upward upwardly upwardness upwards upwell upwelled upwelling upwells upwind uracil uraei uraemia uraemias uraeus uraeuses ural uralian uralic urals urania uranian uranias uranic uraninite uraninites uranium uranography uranous uranus uranyl urase urases urate urates uratic urban urbane urbanely urbaner urbanest urbanism urbanist urbanistic urbanistically urbanists urbanite urbanites urbanities urbanity urbanization urbanizations urbanize urbanized urbanizes urbanizing urbanologist urbanologists urbanology urbino urceolate urchin urchins urd urds urdu urea urease ureases uredia uredinia uredinial urediniospore urediniospores uredinium urediospore urediospores uredium uredospore uredospores uredostage uredostages ureide ureides uremia uremias uremic ureotelic ureotelism ureter ureteral ureteric ureters urethan urethane urethanes urethans urethra urethrae urethral urethras urethrectomies urethrectomy urethritis urethritises urethroscope urethroscopes urethroscopy uretic urge urged urgencies urgency urgent urgently urger urgers urges urging urgings urial uric uricosuric uricotelic uricotelism uridine uridines urim urinal urinals urinalyses urinalysis urinary urinate urinated urinates urinating urination urinations urinative urinator urinators urine uriniferous urinogenital urinometer urinometers urinose urinous urn urns urocanic urochord urochordate urochordates urochords urochrome urochromes urodele urodeles urogenital urogenous urogram urograms urographic urographies urography urokinase urokinases urolith urolithiasis urolithic uroliths urologic urological urologist urologists urology uronic uropod uropods uropygial uropygium uropygiums uroscopies uroscopy urostomies urostomy urostyle urostyles ursa ursine ursprache ursula ursuline ursulines urtext urtexts urticant urticants urticaria urticarial urticate urticated urticates urticating urtication urtications uruguay uruguayan uruguayans urus uruses urushiol urushiols us usa usability usable usableness usably usage usages usance usances use useable used useful usefully usefulness useless uselessly uselessness user users uses ushak ushant usher ushered usherette usherettes ushering ushers using usnea usneas usnic usquebaugh usquebaughs usual usually usualness usufruct usufructs usufructuaries usufructuary usurer usurers usuries usurious usuriously usuriousness usurp usurpation usurpations usurped usurper usurpers usurping usurpingly usurps usury ut utah utahan utahans ute utensil utensils uteri uterine utero uterus uteruses utes utile utilitarian utilitarianism utilitarians utilities utility utilizable utilization utilizations utilize utilized utilizer utilizers utilizes utilizing utmost utopia utopian utopianism utopians utopias utopism utopist utopistic utopists utrecht utricle utricles utricular utriculi utriculus utrillo uttar utter utterable utterance utterances uttered utterer utterers uttering utterly uttermost utters uvarovite uvarovites uvea uveal uveas uveitis uvula uvulae uvular uvulas uvulitis uvulitises uxorial uxorially uxoricide uxoricides uxorious uxoriously uxoriousness uzbeg uzbek uzbekistan uzbeks uzès v vac vacancies vacancy vacant vacantly vacantness vacatable vacate vacated vacates vacating vacation vacationed vacationeer vacationeers vacationer vacationers vacationing vacationist vacationists vacationland vacationlands vacationless vacations vaccinal vaccinate vaccinated vaccinates vaccinating vaccination vaccinations vaccinator vaccinators vaccine vaccinee vaccinees vaccines vaccinia vaccinial vaccinias vacillant vacillate vacillated vacillates vacillating vacillatingly vacillation vacillations vacillator vacillators vacillatory vacs vacua vacuities vacuity vacuo vacuolar vacuolate vacuolated vacuolation vacuole vacuoles vacuolization vacuous vacuously vacuousness vacuum vacuumed vacuumes vacuuming vacuums vade vadose vaduz vagabond vagabondage vagabondages vagabonded vagabonding vagabondish vagabondism vagabonds vagal vagally vagaries vagarious vagariously vagary vagi vagile vagility vagina vaginae vaginal vaginally vaginas vaginate vaginated vaginectomies vaginectomy vaginismus vaginismuses vaginitis vaginitises vagotomies vagotomy vagotonia vagotonic vagotropic vagrancies vagrancy vagrant vagrantly vagrants vagrom vague vaguely vagueness vaguer vaguest vagus vahine vahines vail vailed vailing vails vain vainer vainest vainglories vainglorious vaingloriously vaingloriousness vainglory vainly vainness vair vairs vaishnava vaishnavas vaishnavism vaisya vaisyas valance valanced valances valancing vale valediction valedictions valedictorian valedictorians valedictories valedictory valence valences valencia valenciennes valency valentine valentines valera valerate valerates valerian valerians valeric vales valet valeted valeting valets valetudinarian valetudinarianism valetudinarians valetudinaries valetudinary valgoid valgus valhalla valiance valiancy valiant valiantly valiantness valiants valid validate validated validates validating validation validations validity validly validness valine valines valinomycin valinomycins valise valises valium valkyrie valkyries vallate vallation vallations vallatory vallecula valleculae vallecular valleculate vallences vallencies valletta valley valleyed valleys valois valonia valonias valor valorem valorization valorizations valorize valorized valorizes valorizing valorous valorously valorousness valors valparaiso valpolicella valproate valproates valsalva valse valses valuable valuableness valuables valuably valuate valuated valuates valuating valuation valuational valuationally valuations valuator valuators value valued valueless valuelessness valuer valuers values valuing valuta valvar valvate valve valved valveless valves valving valvula valvulae valvular valvule valvules valvulitis valvulitises valvuloplasties valvuloplasty vambrace vambraces vamoose vamoosed vamooses vamoosing vamp vamped vamper vampers vamping vampire vampires vampirical vampirish vampirism vampish vampishly vamps vampy van vanadate vanadates vanadic vanadinite vanadinites vanadium vanaspati vanbrugh vancomycin vancomycins vancouver vanda vandal vandalic vandalism vandalistic vandalization vandalizations vandalize vandalized vandalizes vandalizing vandals vanderbilt vandyke vandyked vandykes vane vaned vanes vang vangs vanguard vanguardism vanguardist vanguardists vanguards vanilla vanillas vanillic vanillin vanir vanish vanished vanisher vanishers vanishes vanishing vanishingly vanishment vanities vanity vanload vanloads vanned vanner vanners vanning vanpool vanpooled vanpooler vanpoolers vanpooling vanpools vanquish vanquishable vanquished vanquisher vanquishers vanquishes vanquishing vanquishment vans vansittart vantage vantages vanuatu vanuatuan vanuatuans vanward vapid vapidity vapidly vapidness vapor vapored vaporer vaporers vaporescence vaporetti vaporetto vaporettos vaporific vaporing vaporingly vaporings vaporish vaporishness vaporizable vaporization vaporizations vaporize vaporized vaporizer vaporizers vaporizes vaporizing vaporosity vaporous vaporously vaporousness vapors vaporware vapory vaquero vaqueros vara varactor varactors varas varia variabilities variability variable variableness variables variably variance variances variant variants varias variate variates variation variational variationally variations variceal varicella varicellas varicellate varicelloid varices varicocele varicoceles varicolored varicose varicosed varicoses varicosis varicosities varicosity varicotomies varicotomy varied variedly variegate variegated variegates variegating variegation variegations variegator variegators varier variers varies varietal varietally varietals varieties variety variform variola variolas variolate variolated variolates variolating variole varioles variolite variolites varioloid varioloids variolous variometer variometers variorum variorums various variously variousness varisized varistor varistors varitype varityped varitypes varityping varix varlet varletry varlets varlettries varmint varmints varnish varnished varnisher varnishers varnishes varnishing varnishy varoom varoomed varooming varooms varsities varsity varsovian varuna varus varve varved varves vary varying varyingly vas vasa vasal vascula vascular vascularity vascularization vascularizations vascularize vascularized vascularizes vascularizing vasculature vasculatures vasculitis vasculitises vasculum vase vasectomies vasectomize vasectomized vasectomizes vasectomizing vasectomy vaselike vaseline vases vashon vasoactive vasoactivity vasoconstriction vasoconstrictions vasoconstrictive vasoconstrictor vasoconstrictors vasodilatation vasodilatations vasodilation vasodilations vasodilator vasodilators vasoligate vasoligated vasoligates vasoligating vasoligation vasoligations vasomotor vasopressin vasopressins vasopressor vasopressors vasospasm vasospasms vasospastic vasotocin vasotocins vasovagal vassal vassalage vassals vast vaster vastest vastier vastiest vastities vastitude vastitudes vastity vastly vastness vasty vat vatic vatical vatican vaticanism vaticinal vaticinate vaticinated vaticinates vaticinating vaticination vaticinations vaticinator vaticinators vats vatted vatting vatu vatus vau vaudeville vaudevilles vaudevillian vaudevillians vaudois vaughan vault vaulted vaulter vaulters vaulting vaultingly vaultings vaults vaulty vaunt vaunted vaunter vaunters vauntful vaunting vauntingly vaunts vav vavasor vavasors vavasour vavasours vcr vd ve veadar veal vealer vealers vealy vector vectored vectorial vectorially vectoring vectorization vectorizations vectorize vectorized vectorizes vectorizing vectors veda vedalia vedalias vedanta vedantic vedantism vedantist vedantists vedas vedda veddah veddahs veddas veddoid veddoids vedette vedettes vedic vee veejay veejays veena veenas veep veeps veer veered veeries veering veeringly veers veery vees vega vegan veganism vegans vegas vegetable vegetables vegetably vegetal vegetarian vegetarianism vegetarians vegetate vegetated vegetates vegetating vegetation vegetational vegetations vegetative vegetatively vegetativeness vegetive vegged veggie veggies vegging vegie vegies vehemence vehemency vehement vehemently vehicle vehicles vehicular veil veiled veiling veilings veils vein veinal veined veiner veiners veinier veiniest veining veinings veinlet veinlets veins veinstone veinstones veinule veinules veiny vela velamen velamentous velamina velar velaria velarium velarization velarizations velarize velarized velarizes velarizing velars velasquez velate velcro veld velds veldt veldts veliger veligers velleities velleity vellum vellums veloce velocimeter velocimeters velocipede velocipedes velocities velocity velodrome velodromes velour velours velouté velum velums velure velures velutinous velvet velveteen velveteens velvetier velvetiest velvetleaf velvetleafs velvetlike velvets velvety vena venae venal venalities venality venally venatic venatical venation venational vend venda vendable vendace vendaces vended vendee vendees vender venders vendetta vendettas vendeuse vendeuses vendibility vendible vending vendor vendors vends vendue vendues vendôme veneer veneered veneerer veneerers veneering veneers venenation venenations venene venenes venepuncture venepunctures venerability venerable venerableness venerably venerate venerated venerates venerating veneration venerational venerator venerators venereal venereological venereologist venereologists venereology venereum veneries veneris venery venesection venesections veneti venetia venetian venetians venetic veneto venezia venezuela venezuelan venezuelans venge vengeance venged vengeful vengefully vengefulness venges venging venial veniality venially venialness venice venin venins venipuncture venipunctures venire venireman veniremen venires venison venisons venite venites venn venogram venograms venography venom venomous venomously venomousness venose venosity venosus venous venously venousness vent ventage ventages ventail ventails vented venter venters ventifact ventifacts ventilate ventilated ventilates ventilating ventilation ventilations ventilator ventilators ventilatory venting ventless ventrad ventral ventrally ventrals ventricle ventricles ventricose ventricosity ventricous ventricular ventriculi ventriculus ventriloquial ventriloquially ventriloquism ventriloquist ventriloquistic ventriloquists ventriloquize ventriloquized ventriloquizes ventriloquizing ventriloquy ventrodorsal ventrodorsally ventrolateral ventrolaterally ventromedial ventromedially vents venture ventured venturer venturers ventures venturesome venturesomely venturesomeness venturi venturing venturis venturous venturously venturousness venue venues venular venule venules venus venusberg venushair venusian venusians vera veracious veraciously veraciousness veracities veracity veranda verandaed verandah verandahed verandahs verandas verapamil verapamils veratridine veratridines veratrine veratrines veratrum verb verba verbal verbalism verbalisms verbalist verbalistic verbalists verbalizable verbalization verbalizations verbalize verbalized verbalizer verbalizers verbalizes verbalizing verbally verbals verbatim verbaux verbena verbenas verbiage verbicide verbicides verbid verbified verbifies verbify verbifying verbigeration verbigerations verbless verbose verbosely verboseness verbosity verboten verbs verbum verd verdancy verdant verdantly verde verdean verdeans verderer verderers verderor verderors verdi verdict verdicts verdigris verdin verdins verditer verditers verdun verdure verdured verdurous verdurousness verge verged verger vergers verges verging verglas verglases veridic veridical veridicality veridically verier veriest verifiability verifiable verifiableness verifiably verification verifications verificative verified verifier verifiers verifies verify verifying verily verisimilar verisimilarly verisimilitude verisimilitudes verisimilitudinous verism verismo verismos verist veristic verists veritable veritableness veritably verities verity verjuice verjuices verkhoyansk verlaine vermeer vermeil vermicelli vermicidal vermicide vermicides vermicular vermicularly vermiculate vermiculated vermiculates vermiculating vermiculation vermiculations vermiculite vermiculites vermiform vermifuge vermifuges vermilion vermilioned vermilioning vermilions vermillion vermillioned vermillioning vermillions vermin vermination verminations verminous verminously vermivorous vermont vermonter vermonters vermouth vermouths vernacle vernacular vernacularism vernacularisms vernacularize vernacularized vernacularizes vernacularizing vernacularly vernaculars vernal vernalization vernalizations vernalize vernalized vernalizes vernalizing vernally vernation vernations verner vernicle vernier verniers vernissage vernissages vernix vernon verona veronese veronica veronicas verruca verrucae verrucose verrucous vers versa versailles versant versants versatile versatilely versatileness versatility verse versed verses verset versets versicle versicles versicolor versicolored versicular versification versifications versified versifier versifiers versifies versify versifying versine versing version versional versions verso versos verst versts versus vert verte vertebra vertebrae vertebral vertebrally vertebras vertebrate vertebrates vertebration vertebrations vertex vertexes vertical verticality vertically verticalness verticals vertices verticil verticillaster verticillasters verticillastrate verticillate verticillated verticillately verticillation verticillations verticillium verticils vertiginous vertiginously vertiginousness vertigo vertigoes vertigos verts vertu vertus vervain vervains verve vervet vervets very vesalius vesica vesicae vesical vesicant vesicants vesicate vesicated vesicates vesicating vesication vesications vesicatories vesicatory vesicle vesicles vesicular vesicularity vesicularly vesiculate vesiculated vesiculates vesiculating vesiculation vesiculations vespasian vesper vesperal vesperals vespers vespertilian vespertilionid vespertilionids vespertinal vespertine vespiaries vespiary vespid vespids vespine vespucci vessel vessels vest vesta vestal vestals vestas vested vestee vestees vestiaries vestiary vestibular vestibule vestibuled vestibules vestibulocochlear vestige vestiges vestigia vestigial vestigially vestigium vesting vestings vestlike vestment vestmental vestments vestries vestry vestryman vestrymen vestrywoman vestrywomen vests vesture vestured vestures vesturing vesuvian vesuvianite vesuvianites vesuvians vesuvius vet vetch vetches vetchling vetchlings veteran veterans veterinarian veterinarians veterinaries veterinary vetiver vetivers vetivert vetiverts veto vetoed vetoer vetoers vetoes vetoing vets vetted vetting vex vexation vexations vexatious vexatiously vexatiousness vexed vexedly vexer vexers vexes vexilla vexillaries vexillary vexillate vexillologic vexillological vexillologist vexillologists vexillology vexillum vexing vexingly vext vhf via viability viable viably viaduct viaducts vial vialed vialing vialled vialling vials viand viands viatic viatica viatical viaticum viaticums vibe vibes vibist vibists vibracula vibracular vibraculoid vibraculum vibraharp vibraharpist vibraharpists vibraharps vibrance vibrancy vibrant vibrantly vibraphone vibraphones vibraphonist vibraphonists vibrate vibrated vibrates vibratile vibratility vibrating vibration vibrational vibrationless vibrations vibrative vibrato vibratoless vibrator vibrators vibratory vibratos vibrio vibrioid vibrion vibrionic vibrions vibrios vibrioses vibriosis vibrissa vibrissae vibronic viburnum vicar vicarage vicarages vicarate vicarates vicarial vicariance vicariances vicariant vicariants vicariate vicariates vicarious vicariously vicariousness vicars vicarship vice viced vicegeral vicegerencies vicegerency vicegerent vicegerents vicenary vicennial vicenza viceregal viceregally vicereine vicereines viceroy viceroyalties viceroyalty viceroys viceroyship viceroyships vices vichy vichyssoise vichyssoises vicinage vicinal vicing vicinities vicinity vicious viciously viciousness vicissitude vicissitudes vicissitudinary vicissitudinous victim victimhood victimization victimizations victimize victimized victimizer victimizers victimizes victimizing victimless victimologist victimologists victimology victims victor victoria victorian victoriana victorianism victorianisms victorianization victorianizations victorianize victorianized victorianizes victorianizing victorians victorias victories victorious victoriously victoriousness victors victory victrola victual victualed victualer victualers victualing victualled victualler victuallers victualling victuals vicuna vicunas vicuña vicuñas vidalia vide videlicet video videocassette videocassettes videoconference videoconferences videoconferencing videodisc videodiscs videodisk videodisks videogenic videographer videographers videography videoland videophile videophiles videophone videophones videos videotape videotaped videotapes videotaping videotex videotexs videotext videotexts vidette videttes vidicon vidicons viduity vie vied vienna viennese vientiane vier viers vies vietcong vietminh vietnam vietnamese vietnamization vietnamize vietnamized vietnamizes vietnamizing view viewable viewdata viewed viewer viewers viewership viewfinder viewfinders viewier viewiest viewing viewings viewless viewlessly viewpoint viewpoints views viewy vig viga vigas vigesimal vigil vigilance vigilant vigilante vigilanteism vigilantes vigilantism vigilantly vigils vigintillion vigneron vignerons vignette vignetted vignetter vignetters vignettes vignetting vignettist vignettists vigor vigorish vigoroso vigorous vigorously vigorousness viking vikings vilayet vilayets vile vilely vileness viler vilest vilification vilifications vilified vilifier vilifiers vilifies vilify vilifying vilipend vilipended vilipending vilipends vill villa villadom village villager villagers villagery villages villain villainage villainages villainess villainies villainous villainously villainousness villains villainy villanella villanelle villanelles villanueva villas villatic villein villeinage villeinages villeins villenage villeneuve villi villiers villiform villon villose villosities villosity villous villously vills villus vim viminal vin vina vinaceous vinaigrette vinaigrettes vinal vinas vinasse vinasses vinblastine vinblastines vinca vincent vincentian vincentians vinci vincibility vincible vincibly vincristine vincristines vincula vinculum vinculums vindaloo vindicable vindicate vindicated vindicates vindicating vindication vindications vindicator vindicators vindicatory vindictive vindictively vindictiveness vine vined vinedresser vinedressers vinegar vinegared vinegarish vinegarone vinegarones vinegarroon vinegarroons vinegars vinegary vineries vinery vines vineyard vineyardist vineyardists vineyards vinic vinicultural viniculture vinicultures viniculturist viniculturists vinier viniest vinifera viniferous vinification vinifications vinified vinifies vinify vinifying vining vino vinogradoff vinometer vinometers vinos vinosities vinosity vinous vinously vintage vintager vintagers vintages vintner vintners viny vinyl vinylic vinylidene vinylidenes vinyls viol viola violability violable violableness violably violaceous violas violate violated violates violating violation violations violative violator violators viole violence violent violently violet violets violin violinist violinistic violinists violinmaker violinmakers violinmaking violins violist violists violoncellist violoncellists violoncello violoncellos violone violones viols viomycin viomycins viosterol viosterols viper viperfish viperfishes viperine viperish viperous viperously vipers viraginous virago viragoes viragos viral virally virelay virelays viremia viremias viremic vireo vireos vires virescence virescent virga virgas virgate virgates virgil virgilia virgilian virgin virginal virginalist virginalists virginally virginals virginia virginiamycin virginiamycins virginian virginians virginities virginity virgins virgo virgoan virgoans virgos virgulate virgule virgules viricidal viricide viricides virid viridescence viridescent viridian viridity virile virilely viriles virilis virilism virilisms virility virilization virilizations virilize virilized virilizes virilizing virion virions virogene virogenes virogeneses virogenesis virogenetic virogenic viroid viroids virologic virological virologically virologist virologists virology viroses virosis virtu virtual virtuality virtualizes virtually virtue virtueless virtues virtuosa virtuosas virtuosi virtuosic virtuosically virtuosities virtuosity virtuoso virtuosos virtuous virtuously virtuousness virtus virucidal virucide virucides virulence virulency virulent virulently viruliferous virus viruses vis visa visaed visage visaged visages visaing visard visards visas visayan visayans viscacha viscachas viscera visceral viscerally visceromotor viscid viscidity viscidly viscidness viscoelastic viscoelasticity viscometer viscometers viscometric viscometry visconti viscose viscosimeter viscosimeters viscosimetric viscosities viscosity viscount viscountcies viscountcy viscountess viscountesses viscounties viscounts viscounty viscous viscously viscousness viscus vise vised viseed viseing viselike vises vishnu visibilities visibility visible visibleness visibly visigoth visigothic visigoths vising vision visional visionally visionaries visionariness visionary visioned visioning visionless visions visit visitable visitant visitants visitation visitational visitations visitatorial visited visiting visitor visitors visits visor visored visoring visorless visors vista vistaed vistas vistula visual visuality visualizable visualization visualizations visualize visualized visualizer visualizers visualizes visualizing visually visualness visuals visuomotor visuomotors visuospatial vita vitae vitaes vital vitalism vitalist vitalistic vitalists vitalities vitality vitalization vitalizations vitalize vitalized vitalizer vitalizers vitalizes vitalizing vitally vitalness vitals vitamer vitameric vitamers vitamin vitaminic vitamins vitellaria vitellarium vitellariums vitellin vitelline vitellines vitellins vitellogenesis vitellogenetic vitellogenic vitellus vitelluses viterbo vitiable vitiate vitiated vitiates vitiating vitiation vitiations vitiator vitiators viticultural viticulturally viticulture viticulturist viticulturists vitiligo vitiligos vitrectomies vitrectomy vitreosity vitreous vitreousness vitrescence vitrescent vitrifaction vitrifactions vitrifiability vitrifiable vitrification vitrifications vitrified vitrifies vitrify vitrifying vitrine vitrines vitriol vitrioled vitriolic vitrioling vitriolled vitriolling vitriols vitro vitruvius vitta vittae vittate vittle vittles vituline vituperate vituperated vituperates vituperating vituperation vituperations vituperative vituperatively vituperativeness vituperator vituperators vituperatory vitus viva vivace vivacious vivaciously vivaciousness vivacity vivaldi vivandière vivandières vivant vivants vivaria vivarium vivariums vivax vivaxs vivendi viverrid viverrids viverrine viverrines vivian vivid vivider vividest vividly vividness vivific vivification vivifications vivified vivifier vivifiers vivifies vivify vivifying viviparity viviparous viviparously vivisect vivisected vivisecting vivisection vivisectional vivisectionally vivisectionist vivisectionists vivisector vivisectors vivisects vivo vivos vivre vixen vixenish vixenishly vixenishness vixens viz vizard vizards vizcacha vizier vizierate vizierial viziers viziership vizor vizored vizoring vizors vizsla vizslas vladivostok vlaminck vocable vocables vocabular vocabularies vocabulary vocal vocalic vocalically vocalism vocalist vocalistic vocalists vocality vocalization vocalizations vocalize vocalized vocalizer vocalizers vocalizes vocalizing vocally vocalness vocals vocation vocational vocationalism vocationalisms vocationalist vocationalists vocationally vocations vocative vocatively vocatives voce vociferant vociferate vociferated vociferates vociferating vociferation vociferations vociferator vociferators vociferous vociferously vociferousness vocoder vocoders vodka vodkas vodoun vodouns vodun voduns vogue vogues voguish voguishly voguishness vogul voguls voice voiced voicedness voiceful voicefulness voiceless voicelessly voicelessness voiceover voiceovers voiceprint voiceprints voicer voicers voices voicing voicings void voidable voidableness voidance voidances voided voider voiders voiding voidness voids voile voiles voilà voir volans volant volante volapük volar volatile volatileness volatiles volatility volatilizable volatilization volatilizations volatilize volatilized volatilizer volatilizers volatilizes volatilizing volcanic volcanically volcanicity volcanism volcanisms volcanization volcanizations volcanize volcanized volcanizes volcanizing volcano volcanoes volcanogenic volcanologic volcanological volcanologist volcanologists volcanology volcanos vole volens volente voles volga volgograd volitant volitantes volitation volitational volitations volition volitional volitionally volitive volkslied volkslieder volkswagen volkswagens volley volleyball volleyballer volleyballers volleyballs volleyed volleyer volleyers volleying volleys volplane volplaned volplanes volplaning volpone volsci volscian volscians volt volta voltage voltages voltaic voltaire volte voltes voltmeter voltmeters volts volubility voluble volubleness volubly volume volumed volumes volumeter volumeters volumetric volumetrically voluming voluminosity voluminous voluminously voluminousness volumnia voluntaries voluntarily voluntariness voluntarism voluntarist voluntaristic voluntarists voluntary voluntaryism voluntaryist voluntaryists volunteer volunteered volunteering volunteerism volunteers voluptuaries voluptuary voluptuous voluptuously voluptuousness volute voluted volutes volutin volutins volution volutions volva volvas volvate volvent volvents volvox volvoxes volvulus volvuluses vomer vomerine vomers vomica vomicae vomit vomited vomiter vomiters vomiting vomitive vomitives vomitories vomitory vomits vomiturition vomituritions vomitus vomituses von voodoo voodooed voodooing voodooism voodooist voodooistic voodooists voodoos voracious voraciously voraciousness voracity vorlage vorlages vortex vortexes vortical vortically vorticella vorticellae vorticellas vortices vorticism vorticist vorticists vorticity vorticose vortigern vortiginous vosges votable votaress votaresses votaries votarist votarists votary vote voteable voted voteless voter voters votes voting votive votively votiveness voto votos vouch vouched vouchee vouchees voucher vouchered vouchering vouchers vouches vouching vouchsafe vouchsafed vouchsafement vouchsafes vouchsafing voussoir voussoirs vouvray vouvrays vow vowed vowel vowelization vowelizations vowelize vowelized vowelizes vowelizing vowels vower vowers vowing vows vox voyage voyaged voyager voyagers voyages voyageur voyageurs voyaging voyeur voyeurism voyeuristic voyeuristically voyeurs vroom vroomed vrooming vrooms vu vug vuggy vugs vulcan vulcanian vulcanicity vulcanism vulcanisms vulcanite vulcanizable vulcanizate vulcanizates vulcanization vulcanizations vulcanize vulcanized vulcanizer vulcanizers vulcanizes vulcanizing vulcanologist vulcanologists vulcanology vulgar vulgarian vulgarians vulgaris vulgarism vulgarisms vulgarities vulgarity vulgarization vulgarizations vulgarize vulgarized vulgarizer vulgarizers vulgarizes vulgarizing vulgarly vulgarness vulgate vulgates vulgus vulnerabilities vulnerability vulnerable vulnerableness vulnerably vulneraries vulnerary vulpecula vulpecular vulpine vulture vultures vulturine vulturish vulturous vulva vulvae vulval vulvar vulvas vulvate vulvectomies vulvectomy vulviform vulvitis vulvitises vulvovaginitis vulvovaginitises vying vänern vättern vérité véronique w waals wabanaki wabanakis wabble wabbled wabbles wabbling wac wack wacked wackier wackiest wackily wackiness wacko wackos wacks wacky waco wacs wad wadable wadded waddenzee wadder wadders waddied waddies wadding waddle waddled waddler waddlers waddles waddling waddy waddying wade wadeable waded wader waders wades wadi wadies wading wadis wadmal wadmel wadmol wads wady waf wafer wafered wafering wafers waffle waffled waffler wafflers waffles wafflestomper wafflestompers waffling wafflingly waffly wafs waft waftage wafted wafter wafters wafting wafts wafture wag wage waged wageless wager wagered wagerer wagerers wagering wagers wages wageworker wageworkers wagged wagger waggeries waggers waggery wagging waggish waggishly waggishness waggle waggled waggles waggling waggly waging wagner wagnerian wagnerians wagnerite wagnerites wagon wagoned wagoner wagoners wagonette wagonettes wagoning wagonload wagonloads wagons wags wagtail wagtails wahabi wahabis wahhabi wahhabis wahhabism wahhabite wahhabites wahine wahines wahoo wahoos wahpekute wahpekutes wahpeton wahpetons wahwah waianae waif waiflike waifs waikiki wail wailed wailer wailers wailful wailfully wailing wailingly wails wain wains wainscot wainscoted wainscoting wainscots wainscotted wainscotting wainwright wainwrights waist waistband waistbands waistcloth waistcloths waistcoat waistcoated waistcoats waisted waistless waistline waistlines waists wait waited waiter waiters waiting waitings waitpeople waitperson waitpersons waitress waitresses waitron waitrons waits waive waived waiver waivers waives waiving wakame wakames wakashan wake waked wakeful wakefully wakefulness wakeless waken wakened wakener wakeners wakening wakens waker wakers wakes wakeup waking walachia walapai walapais walcheren walden waldenses waldensian waldensians waldorf wale waled waler walers wales walhalla waling walk walkability walkable walkabout walkabouts walkathon walkathons walkaway walkaways walked walker walkers walkie walking walkingstick walkingsticks walkman walkout walkouts walkover walkovers walks walkup walkups walkway walkways walky walkyrie wall walla wallabies wallaby wallace wallachia wallachian wallachians wallah wallahs wallaroo wallaroos wallas wallboard walled wallenberg wallet wallets walleye walleyed walleyes wallflower wallflowers walling wallis wallless wallonia walloon walloons wallop walloped walloper wallopers walloping wallopings wallops wallow wallowa wallowed wallower wallowers wallowing wallows wallpaper wallpapered wallpapering wallpapers walls walnut walnuts walpole walpurgis walpurgisnacht walrus walruses walsingham walsy walter walton waltz waltzed waltzer waltzers waltzes waltzing wamble wambled wambles wambliness wambling wamblingly wambly wampanoag wampanoags wampum wampumpeag wan wand wander wandered wanderer wanderers wandering wanderingly wanderings wanderlust wanderoo wanderoos wanders wandflower wandflowers wands wane waned wanes wangle wangled wangler wanglers wangles wangling wanigan wanigans waning wanion wankel wanly wanna wanned wanner wanness wannest wannigan wannigans wanning wans want wanted wanter wanters wanting wantless wantlessness wanton wantoned wantoner wantoners wantoning wantonly wantonness wantons wants wapentake wapentakes wapiti wapitis wappenschawing wappinger wappingers wapsipinicon war warble warbled warbler warblers warbles warbling warbonnet warbonnets warburg ward warded warden wardenries wardenry wardens wardenship warder warders wardership wardian warding wardress wardresses wardrobe wardrobes wardroom wardrooms wards wardship wardships ware wared warehouse warehoused warehouseman warehousemen warehouser warehousers warehouses warehousing wareroom warerooms wares warfare warfarin warfront warfronts warhead warheads warhorse warhorses warier wariest warily wariness waring warison warless warlike warlock warlocks warlord warlordism warlords warm warmed warmer warmers warmest warmhearted warmheartedly warmheartedness warming warmish warmly warmness warmonger warmongering warmongers warmouth warmouths warms warmth warmup warmups warn warned warner warners warning warningly warnings warns warp warpage warpath warpaths warped warper warpers warping warplane warplanes warps warrant warrantability warrantable warrantableness warrantably warranted warrantee warrantees warranter warranters warranties warranting warrantless warrantor warrantors warrants warranty warred warren warrener warreners warrens warring warrior warriors wars warsaw warship warships wart warted warthog warthogs wartime wartless warts warty warwickshire wary was wasabi wasatch wash washability washable washbasin washbasins washboard washboards washbowl washbowls washcloth washcloths washday washdays washed washer washerman washermen washers washerwoman washerwomen washes washhouse washhouses washier washiest washiness washing washings washington washingtonian washingtonians washout washouts washrag washrags washroom washrooms washstand washstands washtub washtubs washup washups washwoman washwomen washy wasn wasn't wasp waspdom waspier waspiest waspish waspishly waspishness wasplike wasps waspy wassail wassailed wassailer wassailers wassailing wassails wassermann wastage waste wastebasket wastebaskets wasted wasteful wastefully wastefulness wasteland wastelands wastepaper waster wasters wastes wastewater wastewaters wasting wastingly wastrel wastrels watap watape watapes wataps watch watchable watchband watchbands watchcase watchcases watchdog watchdogged watchdogging watchdogs watched watcher watchers watches watcheye watcheyes watchful watchfully watchfulness watching watchmaker watchmakers watchmaking watchman watchmen watchstrap watchstraps watchtower watchtowers watchword watchwords water waterbed waterbeds waterbird waterbirds waterborne waterbuck waterbucks waterbus waterbuses waterbusses watercolor watercolorist watercolorists watercolors watercooler watercoolers watercourse watercourses watercraft watercrafts watercress waterdog waterdogging waterdogs watered waterer waterers waterfall waterfalls waterfinder waterfinders waterflood waterflooded waterflooding waterfloods waterfowl waterfowler waterfowlers waterfowling waterfowls waterfront waterfronts watergate watergates waterhole waterholes waterier wateriest waterily wateriness watering waterish waterishness waterleaf waterleafs waterless waterlessness waterline waterlines waterlog waterlogged waterlogging waterlogs waterloo waterloos waterman watermanship watermark watermarked watermarking watermarks watermelon watermelons watermen waterpower waterproof waterproofed waterproofer waterproofers waterproofing waterproofness waterproofs waters waterscape waterscapes watershed watersheds waterside watersides waterskiing waterspout waterspouts waterthrush waterthrushes watertight watertightness waterway waterways waterweed waterweeds waterwheel waterwheels waterworks waterworn watery waterzooi watlings watson watt wattage wattages watteau wattle wattlebird wattlebirds wattled wattles wattling wattmeter wattmeters watts watusi watusis waugh wave waveband wavebands waved waveform waveforms waveguide waveguides wavelength wavelengths waveless wavelessly wavelet wavelets wavelike wavell waver wavered waverer waverers wavering waveringly waverley wavers wavery waves waveshape waveshapes wavier waviest wavily waviness waving wavy waw wax waxberries waxberry waxbill waxbills waxed waxen waxer waxers waxes waxier waxiest waxiness waxing waxlike waxwing waxwings waxwork waxworks waxy way waybill waybills wayfarer wayfarers wayfaring waylaid waylay waylayer waylayers waylaying waylays wayless waypoint waypoints ways wayside waysides wayward waywardly waywardness wayworn waziristan wazoo wazoos we we'd we'll we're we've weak weaken weakened weakener weakeners weakening weakens weaker weakest weakfish weakfishes weakhearted weakish weaklier weakliest weakliness weakling weaklings weakly weakness weaknesses weakon weakons weakside weal weald wealds wealth wealthier wealthiest wealthily wealthiness wealthy wean weaned weaner weaners weaning weanling weanlings weans weapon weaponed weaponeer weaponeering weaponeers weaponing weaponless weaponry weapons wear wearability wearable wearables wearer wearers wearied wearier wearies weariest weariful wearifully wearifulness weariless wearilessly wearilessness wearily weariness wearing wearingly wearisome wearisomely wearisomeness wears weary wearying weasand weasands weasel weaseled weaseling weaselled weaselling weaselly weasels weasely weather weatherability weatherboard weatherboarded weatherboarding weathercast weathercaster weathercasters weathercasts weathercock weathercocked weathercocking weathercocks weathered weatherglass weatherglasses weathering weatherization weatherizations weatherize weatherized weatherizes weatherizing weatherliness weatherly weatherman weathermen weatherperson weatherproof weatherproofed weatherproofing weatherproofness weatherproofs weathers weathervane weathervanes weatherworn weave weaved weaver weaverbird weaverbirds weavers weaves weaving weavings web webbed webbier webbiest webbing webbings webby weber webers webfed webfeet webfoot weblike webs webster websters webworm webworms weck wecks wed wedded weddell wedder wedders wedding weddings wedel wedeled wedelling wedeln wedelns wedels wedge wedged wedges wedgie wedgies wedging wedgwood wedgy wedlock wednesday wednesdays weds wee weed weeded weeder weeders weedier weediest weedily weediness weeding weeds weedy week weekday weekdays weekend weekended weekender weekenders weekending weekends weeklies weeklong weekly weeknight weeknights weeks weenie weenier weenies weeniest weensy weeny weep weeper weepers weepie weepier weepies weepiest weeping weeps weepy weer weest weever weevers weevil weevilly weevils weevily weft wefts wegener wehrmacht weigela weigelas weigh weighable weighed weigher weighers weighing weighs weight weighted weightier weightiest weightily weightiness weighting weightings weightless weightlessly weightlessness weightlifter weightlifters weightlifting weights weighty weil weil's weimar weimaraner weimaraners weinberg weiner weiners weir weird weirder weirdest weirdie weirdies weirdly weirdness weirdnesses weirdo weirdoes weirdos weirdy weirs weisenheimer weisenheimers weismann weismannism wejack wejacks weka wekas welch welched welches welching welcome welcomed welcomely welcomeness welcomer welcomers welcomes welcoming weld weldable welded welder welders welding weldment weldments weldor weldors welds welfare welfarism welfarist welfarists welkin welkins well welladay wellaway wellaways wellbeing wellborn welled wellerism wellerisms wellhead wellheads wellie wellies welling wellington wellingtons wellness wells wellspring wellsprings welly welsbach welsh welshed welsher welshers welshes welshing welshman welshmen welshwoman welshwomen welt weltanschauung weltanschauungen weltanschauungs welted welter weltered weltering welters welterweight welterweights welting welts weltschmerz wen wenceslas wench wenched wencher wenchers wenches wenching wend wended wending wendish wends wens went wentletrap wentletraps wept were weregild weregilds weren weren't werewolf werewolves wergeld wergelds wergild wergilds werner wernerite wernerites wernicke werwolf werwolves weser weskit weskits wesley wesleyan wesleyanism wesleyans west westbound wester westered westering westerlies westerly western westerner westerners westernization westernizations westernize westernized westernizes westernizing westernmost westernness westerns westers westing westinghouse westings westphalia westphalian westphalians westward westwardly westwards wet wetback wetbacks wether wethers wetland wetlands wetly wetness wets wetsuit wetsuits wettability wettable wetted wetter wetterhorn wetters wettest wetting wettings wettish whack whacked whacker whackers whackier whackiest whacking whacko whackos whacks whacky whale whaleback whalebacks whaleboat whaleboats whalebone whalebones whaled whalelike whaler whalers whales whaling wham whammed whammies whamming whammo whammy whams whang whanged whangee whangees whanging whangs whap whapped whapping whaps wharf wharfage wharfed wharfing wharfinger wharfingers wharfmaster wharfmasters wharfs wharves what what'd what're what's whatchamacallit whatchamacallum whatever whatness whatnot whatnots whatsis whatsit whatsits whatsoever wheal wheals wheat wheatear wheatears wheaten wheatgrass wheatstone wheatworm wheatworms whee wheedle wheedled wheedler wheedlers wheedles wheedling wheedlingly wheel wheelbarrow wheelbarrows wheelbase wheelchair wheelchairs wheeled wheeler wheelers wheelhorse wheelhorses wheelhouse wheelhouses wheelie wheelies wheeling wheelings wheelless wheelman wheelmen wheels wheelsman wheelsmen wheelwork wheelworks wheelwright wheelwrights wheeze wheezed wheezer wheezers wheezes wheezier wheeziest wheezily wheeziness wheezing wheezingly wheezy whelk whelks whelky whelm whelmed whelming whelms whelp whelped whelping whelps when whence whencesoever whenever whensoever where where'd where're where's whereabout whereabouts whereas whereat whereby wherefore wherefores wherefrom wherein whereinto whereof whereon wheresoever wherethrough whereto whereunto whereupon wherever wherewith wherewithal wherries wherry whet whether whets whetstone whetstones whetted whetter whetters whetting whew whey wheyey wheylike which whichever whichsoever whicker whickered whickering whickers whidah whidahs whidbey whiff whiffed whiffer whiffers whiffet whiffets whiffing whiffle whiffled whiffler whifflers whiffles whiffletree whiffling whiffs whig whiggery whiggish whiggism whigs while whiled whiles whiling whilom whilst whim whimbrel whimbrels whimper whimpered whimperer whimperers whimpering whimperingly whimpers whims whimsey whimseys whimsical whimsicalities whimsicality whimsically whimsicalness whimsies whimsy whin whinchat whinchats whine whined whiner whiners whines whiney whing whinge whinged whingeing whinges whinging whinier whiniest whininess whining whiningly whinnied whinnies whinny whinnying whins whinstone whinstones whiny whip whipcord whipcords whiplash whiplashes whiplike whipped whipper whippers whippersnapper whippersnappers whippet whippets whippier whippiest whipping whippings whippletree whippletrees whippoorwill whippoorwills whippy whips whipsaw whipsawed whipsawing whipsawn whipsaws whipstall whipstalls whipstitch whipstitched whipstitches whipstitching whipstock whipstocks whipt whiptail whiptails whipworm whipworms whir whirl whirled whirler whirlers whirlies whirligig whirligigs whirling whirlpool whirlpools whirls whirlwind whirlwinds whirly whirlybird whirlybirds whirr whirred whirring whirrs whirs whish whished whishes whishing whisk whiskbroom whiskbrooms whisked whisker whiskered whiskerless whiskers whiskery whiskey whiskeys whiskies whisking whisks whisky whisper whispered whisperer whisperers whispering whisperingly whisperings whispers whispery whist whistle whistleable whistleblower whistleblowers whistled whistler whistlers whistles whistling whit white whitebait whitebark whitebeard whitebeards whitecap whitecaps whited whiteface whitefaces whitefish whitefishes whiteflies whitefly whitefriars whitehall whitehead whiteheads whitehorse whitely whiten whitened whitener whiteners whiteness whitening whitens whiteout whiteouts whiteprint whiteprints whiter whites whitesmith whitesmiths whitest whitetail whitetails whitethroat whitethroats whitewall whitewalls whitewash whitewashed whitewasher whitewashers whitewashes whitewashing whitewater whitewing whitewings whitewood whitewoods whitey whiteys whither whithersoever whitherward whiting whitings whitish whitleather whitlow whitman whitmonday whitney whitsun whitsunday whitsuntide whittington whittle whittled whittler whittlers whittles whittling whity whiz whizbang whizbangs whizz whizzbang whizzed whizzer whizzers whizzes whizzing who who'd who'll who's who've whoa whodunit whodunits whodunnit whodunnits whoever whole wholehearted wholeheartedly wholeheartedness wholeness wholes wholesale wholesaled wholesaler wholesalers wholesales wholesaling wholesome wholesomely wholesomeness wholesomer wholesomest wholistic wholly whom whomever whomp whomped whomping whomps whomso whomsoever whoo whoop whooped whoopee whoopees whooper whoopers whooping whoopla whooplas whoops whoos whoosh whooshed whooshes whooshing whop whopped whopper whoppers whopping whops whore whored whoredom whoredoms whorehouse whorehouses whoremaster whoremasters whoremonger whoremongers whores whoreson whoresons whorfian whoring whorish whorishly whorishness whorl whorled whorls whort whortle whortleberries whortleberry whortles whorts whose whosesoever whoso whosoever whump whumped whumping whumps why whydah whydahs whys wicca wiccan wiccans wichita wichitas wick wicked wickeder wickedest wickedly wickedness wicker wickerwork wicket wicketkeeper wicketkeepers wickets wicking wickiup wickiups wicks wicopies wicopy widal widdershins wide wideawake wideawakes wideband widely widemouthed widen widened widener wideners wideness widening widens wideout wideouts wider widespread widest widgeon widgeons widget widgets widish widow widowed widower widowerhood widowers widowhood widowing widows width widths widthwise wiedersehen wield wieldable wielded wielder wielders wieldier wieldiest wielding wields wieldy wien wiener wieners wienerwurst wienerwursts wienie wienies wiesbaden wiesel wife wifehood wifeless wifeliness wifely wiffle wifty wig wigan wigans wigeon wigeons wigged wigging wiggle wiggled wiggler wigglers wiggles wiggling wiggly wight wights wiglet wiglets wigmaker wigmakers wigs wigwag wigwagged wigwagger wigwaggers wigwagging wigwags wigwam wigwams wikiup wikiups wilberforce wilco wild wildcard wildcards wildcat wildcats wildcatted wildcatter wildcatters wildcatting wildebeest wildebeests wilder wildered wildering wilderment wilderness wildernesses wilders wildest wildfire wildfires wildflower wildflowers wildfowl wildfowler wildfowlers wildfowling wildfowls wilding wildings wildish wildland wildlands wildlife wildling wildlings wildly wildness wilds wildwood wildwoods wile wiled wiles wilful wilhelmshaven wilier wiliest wilily wiliness wiling wilkes will willamette willed willedly willedness willemite willemites willemstad willet willets willful willfully willfulness william willies willing willingly willingness williwaw williwaws willow willowed willowier willowiest willowing willowlike willows willowware willowy willpower wills willy wilmington wilms wilson wilt wilted wilting wilton wilts wiltshire wily wimble wimbled wimbledon wimbles wimbling wimp wimpiness wimpish wimpishness wimple wimpled wimples wimpling wimps wimpy wimshurst win wince winced wincer wincers winces winch winched wincher winchers winches winchester winchesters winching wincing wind windage windbag windbags windblast windblasts windblown windbreak windbreaker windbreakers windbreaks windburn windburned windburns windcheater windcheaters windchill windchills winded windedly windedness winder winders windfall windfalls windflaw windflaws windflower windflowers windgall windgalls windhoek windhover windhovers windier windiest windily windiness winding windingly windings windjammer windjammers windjamming windlass windlassed windlasses windlassing windless windlessly windlestraw windlestraws windmill windmilled windmilling windmills window windowed windowing windowless windowpane windowpanes windows windowsill windowsills windpipe windpipes windproof windrow windrowed windrower windrowers windrowing windrows winds windsailing windscreen windscreens windshake windshakes windshield windshields windsock windsocks windsor windstorm windstorms windsucker windsuckers windsucking windsurf windsurfed windsurfer windsurfers windsurfing windsurfs windswept windthrow windup windups windward windwards windway windways windy wine winebibber winebibbers winebibbing winebibbings wined wineglass wineglasses winegrower winegrowers winemaker winemakers winemaking winepress winepresses wineries winery wines winesap winesaps wineshop wineshops wineskin wineskins winetasting winetastings winey wing wingback wingbacks wingbow wingbows wingchair wingchairs wingding wingdings winged winger wingers winging wingless winglessness winglet winglets winglike wingman wingmen wingover wingovers wings wingspan wingspans wingspread wingspreads wingtip wingtips wingy winier winiest wining wink winked winker winkers winking winkle winkled winkles winkling winks winless winnability winnable winnebago winnebagoes winnebagos winner winners winnie winnies winning winningest winningly winningness winnings winnipeg winnipegosis winnipesaukee winnow winnowed winnower winnowers winnowing winnows wino winos wins winsome winsomely winsomeness winter winterberries winterberry wintered winterer winterers wintergreen wintergreens winterier winteriest wintering winterish winterization winterizations winterize winterized winterizes winterizing winterkill winterkilled winterkilling winterkills winterly winters wintertide wintertime wintery wintrier wintriest wintrily wintriness wintry winy winze winzes wipe wiped wipeout wipeouts wiper wipers wipes wiping wirable wire wired wiredraw wiredrawer wiredrawers wiredrawing wiredrawn wiredraws wiredrew wiregrass wiregrasses wirehair wirehaired wirehairs wireless wirelessed wirelesses wirelessing wirelike wireman wiremen wirephoto wirepuller wirepullers wirepulling wirer wirers wires wiretap wiretapped wiretapper wiretappers wiretapping wiretaps wirewalker wirewalkers wirework wireworks wireworm wireworms wirier wiriest wirily wiriness wiring wiry wisconsin wisconsinite wisconsinites wisdom wise wiseacre wiseacres wiseass wiseasses wisecrack wisecracked wisecracker wisecrackers wisecracking wisecracks wised wisely wiseness wisenheimer wisenheimers wisent wisents wiser wises wisest wisewoman wisewomen wish wishbone wishbones wished wisher wishers wishes wishful wishfully wishfulness wishing wishy wising wisp wisped wispily wispiness wisping wispish wisps wispy wistaria wistarias wisteria wisterias wistful wistfully wistfulness wit witan witch witchcraft witched witcher witcheries witchers witchery witches witchgrass witchgrasses witching witchingly witchlike witchweed witchweeds witchy witenagemot witenagemote with withal withdraw withdrawable withdrawal withdrawals withdrawer withdrawers withdrawing withdrawn withdrawnness withdraws withdrew withe wither withered withering witheringly witherite witherites withers withershins withes withheld withhold withholder withholders withholding withholdings withholds withies within withindoors without withoutdoors withstand withstander withstanders withstanding withstands withstood withy witless witlessly witlessness witling witlings witloof witloofs witness witnessed witnesser witnessers witnesses witnessing wits witted wittedly wittedness wittenberg wittgenstein wittgensteinian witticism witticisms wittier wittiest wittily wittiness witting wittingly wittings wittol wittols witty witwatersrand wive wived wivern wiverns wives wiving wiz wizard wizardly wizardries wizardry wizards wizen wizened wizening wizens wizes wkly woad woads woadwaxen woadwaxens wobble wobbled wobbler wobblers wobbles wobblier wobblies wobbliest wobbliness wobbling wobbly wodehouse woden wodge wodges woe woebegone woebegoneness woeful woefully woefulness woes woffington woful wok woke woken woks wold wolds wolf wolfberries wolfberry wolfed wolfer wolfers wolffian wolffish wolfhound wolfhounds wolfing wolfish wolfishly wolfishness wolflike wolfram wolframite wolframites wolframs wolfs wolfsbane wolfsbanes wollastonite wollastonites wolof wolsey wolverine wolverines wolves woman womanfully womanhood womanish womanishly womanishness womanism womanist womanists womanize womanized womanizer womanizers womanizes womanizing womankind womanless womanlier womanliest womanlike womanliness womanly womanpower womb wombat wombats wombed wombs women womenfolk womenfolks womenkind womera womeras wommera wommeras won won't wonder wondered wonderer wonderers wonderful wonderfully wonderfulness wondering wonderingly wonderland wonderlands wonderment wonders wonderwork wonderworker wonderworkers wonderworking wonderworks wondrous wondrously wondrousness wonk wonkier wonkiest wonks wonky wont wonted wontedly wontedness wonting wonton wontons wonts woo wood woodbin woodbine woodbines woodbins woodblock woodblocks woodborer woodborers woodboring woodcarver woodcarvers woodcarving woodcarvings woodchat woodchats woodchopper woodchoppers woodchopping woodchuck woodchucks woodcock woodcocks woodcraft woodcrafter woodcrafters woodcrafting woodcrafts woodcut woodcuts woodcutter woodcutters woodcutting woodcuttings wooded wooden woodenhead woodenheaded woodenheads woodenly woodenness woodenware woodie woodier woodies woodiest woodiness wooding woodland woodlander woodlanders woodlands woodlark woodlarks woodlore woodlot woodlots woodman woodmen woodnote woodnotes woodpecker woodpeckers woodpile woodpiles woodprint woodprints woodruff woodruffs woods woodshed woodshedded woodshedding woodsheds woodshop woodshops woodsia woodsias woodsier woodsiest woodsman woodsmen woodstove woodstoves woodsy woodturner woodturners woodturning woodville woodwaxen woodwaxens woodwind woodwinds woodwork woodworker woodworkers woodworking woodworks woodworm woodworms woody wooed wooer wooers woof woofed woofer woofers woofing woofs woogie wooing wool wooled woolen woolens woolgather woolgathered woolgatherer woolgatherers woolgathering woolgathers woolgrower woolgrowers woolgrowing woolie woolier woolies wooliest woolled woollen woollens woollier woollies woolliest woollily woolliness woolly woolpack woolpacks wools woolsack woolsacks woolsey woolshed woolsheds woolskin woolskins woolsorter woolworker woolworkers woolworth wooly woomera woomeras woops woos woozier wooziest woozily wooziness woozy wop wops worcester worcestershire word wordage wordbook wordbooks worded wordier wordiest wordily wordiness wording wordings wordless wordlessly wordlessness wordmonger wordmongering wordmongers wordplay wordplays words wordsmith wordsmithery wordsmiths wordsworth wordsworthian wordy wore work workability workable workableness workably workaday workaholic workaholics workaholism workaround workarounds workbag workbags workbasket workbaskets workbench workbenches workboat workboats workbook workbooks workbox workboxes workday workdays worked worker workers workfare workflow workflows workfolk workfolks workforce workforces workhorse workhorses workhouse workhouses working workingman workingmen workings workingwoman workingwomen workless worklessness workload workloads workman workmanlike workmanly workmanship workmate workmates workmen workout workouts workpeople workpiece workpieces workplace workplaces workroom workrooms works worksheet worksheets workshop workshops workspace workspaces workstation workstations worktable worktables workup workups workweek workweeks workwoman workwomen world worlder worlders worldlier worldliest worldliness worldling worldlings worldly worlds worldview worldviews worldwide worm wormed wormer wormers wormgrass wormgrasses wormhole wormholes wormier wormiest worminess worming wormlike worms wormseed wormseeds wormwood wormwoods wormy worn worried worriedly worrier worriers worries worriment worriments worrisome worrisomely worrisomeness worry worrying worryingly worrywart worrywarts worse worsen worsened worsening worsens worship worshiped worshiper worshipers worshipful worshipfully worshipfulness worshiping worshipless worshipped worshipper worshippers worshipping worships worsleya worsleyas worst worsted worsteds worsting worsts wort worth worthed worthful worthier worthies worthiest worthily worthiness worthing worthless worthlessly worthlessness worths worthwhile worthwhileness worthy wot wotan wots wotted wotting would would've wouldest wouldn wouldn't wouldst wound wounded woundedly wounding woundingly woundless wounds woundwort woundworts wove woven wow wowed wowing wows wowser wowsers wp wpm wrack wracked wrackful wracking wracks wraith wraithlike wraiths wrangel wrangell wrangle wrangled wrangler wranglers wrangles wrangling wrap wraparound wraparounds wrapped wrapper wrappers wrapping wrappings wraps wrapt wrasse wrasses wrath wrathful wrathfully wrathfulness wrathy wreak wreaked wreaking wreaks wreath wreathe wreathed wreathes wreathing wreaths wreathy wreck wreckage wrecked wrecker wreckers wrecking wrecks wren wrench wrenched wrenches wrenching wrenchingly wrens wrest wrested wrester wresters wresting wrestle wrestled wrestler wrestlers wrestles wrestling wrests wretch wretched wretcheder wretchedest wretchedly wretchedness wretches wried wrier wries wriest wriggle wriggled wriggler wrigglers wriggles wriggling wriggly wright wrights wrigley wring wringer wringers wringing wrings wrinkle wrinkled wrinkles wrinkling wrinkly wrist wristband wristbands wristed wristier wristiest wristlet wristlets wristlock wristlocks wrists wristwatch wristwatches wristy writ writable write writer writerly writers writes writhe writhed writhen writher writhers writhes writhing writing writings writs written wrong wrongdoer wrongdoers wrongdoing wrongdoings wronged wronger wrongers wrongest wrongful wrongfully wrongfulness wrongheaded wrongheadedly wrongheadedness wronging wrongly wrongness wrongs wrote wroth wrought wrung wry wryer wryest wrying wryly wryneck wrynecks wryness wt wulfenite wulfenites wunderbar wunderkind wunderkinder wurst wurtemburg wurzburg wurzel wurzels wushu wyandot wyandots wyandotte wyandottes wyatt wych wycherley wyclif wycliffe wycliffite wycliffites wye wyes wyn wynn wynns wyoming wysiwyg wyvern wyverns württemberg x xanadu xanadus xanthan xanthate xanthates xanthene xanthenes xanthic xanthine xanthines xanthippe xanthochroic xanthochroid xanthochroids xanthoma xanthomas xanthomata xanthomatoses xanthomatosis xanthomatous xanthone xanthones xanthophore xanthophores xanthophyll xanthophyllic xanthophyllous xanthophylls xanthopterin xanthopterins xanthous xantippe xaverian xavier xebec xebecs xed xenia xenias xenobiotic xenobiotics xenoblast xenoblasts xenocryst xenocrysts xenodiagnoses xenodiagnosis xenodiagnostic xenogamies xenogamous xenogamy xenogeneic xenogenesis xenogenetic xenogenic xenograft xenografts xenolith xenolithic xenoliths xenon xenophanes xenophile xenophiles xenophilia xenophilous xenophobe xenophobes xenophobia xenophobic xenophobically xenophon xenotropic xerarch xeric xerically xericity xeriscape xeroderma xerodermas xerodermia xerodermias xerographer xerographers xerographic xerographically xerography xerophile xerophilous xerophily xerophthalmia xerophthalmias xerophthalmic xerophyte xerophytes xerophytic xerophytically xerophytism xeroradiography xerosere xeroseres xeroses xerosis xerothermic xerox xeroxed xeroxes xeroxing xerxes xhosa xhosas xi xinjiang xiphisterna xiphisternum xiphoid xiphoids xiphosuran xiphosurans xis xizang xmas xmases xosa xosas xray xs xu xylan xylans xylem xylene xylenes xylidine xylidines xylitol xylitols xylograph xylographed xylographer xylographers xylographic xylographical xylographically xylographing xylographs xylography xyloid xylol xylols xylophage xylophages xylophagous xylophone xylophones xylophonist xylophonists xylose xyloses xylotomies xylotomist xylotomists xylotomy xyster xysters y y'all yabber yabbered yabbering yabbers yablonovy yacht yachted yachter yachters yachting yachts yachtsman yachtsmen yachtswoman yachtswomen yack yacked yackety yacking yacks yag yagi yagis yahoo yahooism yahoos yahveh yahvist yahweh yahwism yahwist yahwistic yak yakima yakimas yakitori yakitoris yakked yakking yakow yakows yaks yakut yakuts yakuza yale yalta yam yamasee yamasees yamen yamens yammer yammered yammerer yammerers yammering yammers yams yang yangtze yank yanked yankee yankeedom yankeeism yankeeisms yankees yanking yanks yankton yanktonai yanktonais yanktons yanqui yantra yantras yao yaos yaoundé yap yapok yapoks yapped yapper yappers yapping yaps yaqui yaquis yarborough yarboroughs yard yardage yardarm yardarms yardbird yardbirds yarded yarding yardman yardmaster yardmasters yardmen yards yardstick yardsticks yare yarely yarmelke yarmelkes yarmulke yarmulkes yarn yarned yarner yarners yarning yarns yarrow yarrows yashmac yashmacs yashmak yashmaks yasmak yasmaks yatagan yatagans yataghan yataghans yaup yauped yauping yaupon yaupons yaups yautia yavapai yavapais yaw yawed yawing yawl yawls yawn yawned yawner yawners yawning yawningly yawns yawp yawped yawper yawpers yawping yawps yaws ycleped yclept yd ye yea yeah yean yeaned yeaning yeanling yeanlings yeans year yearbook yearbooks yearend yearends yearlies yearling yearlings yearlong yearly yearn yearned yearner yearners yearning yearningly yearnings yearns years yeas yeast yeasted yeastier yeastiest yeastily yeastiness yeasting yeasts yeasty yeats yeatsian yecch yech yegg yeggs yell yelled yeller yellers yelling yellow yellowbellied yellowbellies yellowbelly yellowbird yellowbirds yellowcake yellowcakes yellowed yellower yellowest yellowfin yellowhammer yellowhammers yellowing yellowish yellowishness yellowknife yellowlegs yellowness yellows yellowstone yellowtail yellowtails yellowthroat yellowthroats yellowware yellowweed yellowweeds yellowwood yellowwoods yellowy yells yelp yelped yelper yelpers yelping yelps yemen yemeni yemenis yemenite yemenites yen yenned yenning yens yenta yentas yeoman yeomanly yeomanries yeomanry yeomen yep yerba yerkish yersinia yersiniae yersinioses yersiniosis yes yeses yeshiva yeshivah yeshivahs yeshivas yeshivot yessed yessing yesterday yesterdays yestereve yestereven yesterevening yesterevenings yesterevens yestereves yestermorn yestermorning yestermornings yestermorns yesternight yesternights yesteryear yesteryears yet yeti yetis yew yews ygdrasil yggdrasil yid yiddish yiddishism yiddishist yiddishists yids yield yielded yielder yielders yielding yieldingly yieldingness yields yikes yin yinglish yip yipe yipes yipped yippee yippie yippies yipping yips ylang ylem ylems ymca ymir yo yock yocked yocking yocks yod yodel yodeled yodeler yodelers yodeling yodelled yodelling yodels yodh yoed yoga yogh yoghourt yoghourts yoghurt yoghurts yogi yogic yogin yogins yogis yogurt yogurts yohimbine yohimbines yoicks yoing yoke yoked yokefellow yokefellows yokel yokels yokes yoking yokohama yokuts yolk yolked yolks yolky yom yon yonder yoni yonic yonis yoo yore yorick york yorker yorkers yorkie yorkies yorkist yorkists yorkshire yoruba yoruban yorubas yos yosemite you you'd you'll you're you've young young'un young'uns youngberries youngberry younger youngest youngish youngling younglings youngness youngster youngsters younker younkers your yours yourself yourselfer yourselfers yourselves youth youthful youthfully youthfulness youthquake youths yow yowl yowled yowling yowls ypres yquem yquems ytterbia ytterbias ytterbic ytterbium yttria yttrias yttric yttrium yuan yuans yuca yucatec yucatecan yucatecans yucatecs yucatán yucca yuccas yuchi yuchis yuck yuckier yuckiest yuckiness yucky yuga yugoslav yugoslavia yugoslavian yugoslavians yugoslavs yuk yukon yulan yulans yule yuletide yum yuma yuman yumas yummier yummiest yumminess yummy yunnan yup yupik yupiks yuppie yuppiedom yuppies yurok yuroks yurt yurts ywis z zabaglione zabagliones zacharias zaddik zaddikim zaffer zaffers zaffre zaffres zaftig zag zagged zagging zagreb zagreus zagros zags zaibatsu zaikai zaire zairean zaireans zaires zairian zairians zambesi zambezi zambia zambian zambians zamia zamias zamindar zamindari zamindaris zamindars zanana zananas zander zanders zanier zanies zaniest zanily zaniness zany zanzibar zap zapata zapateado zapateados zapateo zapotec zapotecs zapped zapper zappers zappier zappiest zapping zappy zaps zarathustra zareba zarebas zareeba zareebas zarf zarfs zariba zaribas zarzuela zastruga zastrugas zauberflöte zax zaxes zayin zazen zaïrean zaïreans zeal zealand zealander zealanders zealot zealotries zealotry zealots zealous zealously zealousness zeatin zeatins zebec zebeck zebecks zebecs zebedee zebra zebras zebrawood zebrawoods zebrine zebroid zebroids zebu zebulon zebulun zebus zecchin zecchini zecchino zecchinos zecchins zechariah zechin zechins zed zedoaries zedoary zedonk zedonks zeds zee zeebrugge zeeland zeeman zees zeffirelli zein zeins zeitgeber zeitgebers zeitgeist zeitgeists zek zeks zelkova zelkovas zemindar zemindaries zemindars zemindary zemlya zemstvo zemstvos zen zenana zenanas zend zener zenist zenists zenith zenithal zeniths zeno zeolite zeolites zeolitic zephaniah zephyr zephyrs zephyrus zeppelin zeppelins zerk zerks zermatt zero zeroed zeroes zeroing zeros zeroth zest zested zester zesters zestful zestfully zestfulness zestier zestiest zesting zestless zests zesty zeta zethos zethus zeugma zeugmas zeus zeuxis zhejiang zibeline zibelines zibelline zibellines zibet zibeth zibeths zibets zidovudine zidovudines ziegfeld zig zigged zigging ziggurat ziggurats zigs zigzag zigzagged zigzagger zigzaggers zigzagging zigzags zilch zilches zill zillion zillionaire zillionaires zillions zillionth zillionths zills zimbabwe zimbabwean zimbabweans zimmermann zinc zincate zincates zinced zincing zincite zincites zincked zinckenite zinckenites zincking zincks zincograph zincographer zincographers zincographic zincographical zincographs zincography zincs zineb zinebs zinfandel zinfandels zing zingari zingaro zinged zinger zingers zingier zingiest zinging zings zingy zinkenite zinkenites zinnia zinnias zion zionism zionist zionistic zionists zip zipless zipped zipper zippered zippering zippers zippier zippiest zipping zippy zips ziram zirams zircaloy zircaloys zircon zirconia zirconias zirconium zircons zit zither zitherist zitherists zithern zitherns zithers ziti zits zizith zloty zlotys zoa zoantharian zoantharians zoaria zoarial zoarium zoariums zocalo zocalos zodiac zodiacal zodiacs zoea zoeae zoeas zoecia zoecium zoffany zoftig zoisite zoisites zola zombi zombie zombielike zombies zombification zombifications zombified zombifies zombify zombifying zombiism zombis zona zonae zonal zonally zonary zonate zonated zonation zone zoned zoner zoners zones zonetime zonetimes zonian zonians zoning zonk zonked zonking zonks zontian zontians zonule zonules zoo zoochlorella zoochlorellae zoochlorellas zoochore zoochores zooecia zooecium zooflagellate zooflagellates zoogenic zoogenous zoogeographer zoogeographers zoogeographic zoogeographical zoogeographically zoogeography zooglea zoogleae zoogleal zoogleas zoogloea zoogloeae zoogloeas zoographic zoographical zoography zooid zooidal zooids zookeeper zookeepers zooks zoolater zoolaters zoolatrous zoolatry zoologic zoological zoologically zoologies zoologist zoologists zoology zoom zoomed zoometric zoometrical zoometrically zoometries zoometry zooming zoomorph zoomorphic zoomorphism zoomorphs zooms zoon zoonoses zoonosis zoonotic zoons zooparasite zooparasites zooparasitic zoophagous zoophile zoophiles zoophilia zoophilic zoophilism zoophilous zoophily zoophobe zoophobes zoophobia zoophyte zoophytes zoophytic zoophytical zooplankter zooplankters zooplankton zooplanktonic zooplastic zooplasties zooplasty zoos zoosperm zoosperms zoosporangia zoosporangium zoospore zoospores zoosporic zoosporous zoosterol zoosterols zoot zootechnical zootechnician zootechnicians zootechnics zootechny zootomic zootomical zootomies zootomist zootomists zootomy zootoxin zootoxins zooty zooxanthella zooxanthellae zori zoril zorilla zorillas zorille zorilles zorils zoris zorn zoroaster zoroastrian zoroastrianism zoroastrians zoster zosters zouave zouaves zounds zowie zoysia zucchetto zucchettos zucchini zucchinis zugspitze zugunruhe zugzwang zugzwangs zulu zululand zulus zuni zunian zunis zuppa zurich zutphen zuñi zuñian zuñis zwieback zwiebacks zwingli zwinglian zwinglianism zwinglians zwitterion zwitterionic zwitterions zydeco zygapophyseal zygapophyses zygapophysial zygapophysis zygodactyl zygodactylous zygodactyls zygogeneses zygogenesis zygogenetic zygoma zygomas zygomata zygomatic zygomorphic zygomorphism zygomorphous zygomorphy zygoses zygosis zygosity zygospore zygospores zygote zygotene zygotenes zygotes zygotic zygotically zymase zymases zymogen zymogenic zymogenous zymogens zymogram zymograms zymologic zymological zymologist zymologists zymology zymolysis zymolytic zymometer zymometers zymosan zymosans zymoscope zymoscopes zymoses zymosis zymotic zymotically zymurgy zyzzyva zyzzyvas zákros zöllner zöllner's zürich à âge åland ångstrom ångstroms éclair éclaircissement éclairs éclat éclats école écoles écorché écrasez écu écus élan élans élite élites élitism élitist élitists émigré émigrés éminence éminences époque épée épéeist épéeists épées étagère étagères état étienne étoile étoiles étouffée étouffées étui étuis évian évêque être öland öre øresund œil œuvre ================================================ FILE: Trie/Trie/Trie.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ EB798DFE1DFEF79900F0628D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798DFD1DFEF79900F0628D /* AppDelegate.swift */; }; EB798E001DFEF79900F0628D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798DFF1DFEF79900F0628D /* ViewController.swift */; }; EB798E021DFEF79900F0628D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EB798E011DFEF79900F0628D /* Assets.xcassets */; }; EB798E051DFEF79900F0628D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EB798E031DFEF79900F0628D /* Main.storyboard */; }; EB798E101DFEF79900F0628D /* TrieTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E0F1DFEF79900F0628D /* TrieTests.swift */; }; EB798E1B1DFEF79900F0628D /* TrieUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E1A1DFEF79900F0628D /* TrieUITests.swift */; }; EB798E291DFEF81400F0628D /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E281DFEF81400F0628D /* Trie.swift */; }; EB798E2A1DFEF81400F0628D /* Trie.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB798E281DFEF81400F0628D /* Trie.swift */; }; EB798E2C1DFEF90B00F0628D /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB798E2B1DFEF90B00F0628D /* dictionary.txt */; }; EB798E2D1DFEF90B00F0628D /* dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB798E2B1DFEF90B00F0628D /* dictionary.txt */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ EB798E0C1DFEF79900F0628D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = EB798DF21DFEF79900F0628D /* Project object */; proxyType = 1; remoteGlobalIDString = EB798DF91DFEF79900F0628D; remoteInfo = Trie; }; EB798E171DFEF79900F0628D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = EB798DF21DFEF79900F0628D /* Project object */; proxyType = 1; remoteGlobalIDString = EB798DF91DFEF79900F0628D; remoteInfo = Trie; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ EB798DFA1DFEF79900F0628D /* Trie.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Trie.app; sourceTree = BUILT_PRODUCTS_DIR; }; EB798DFD1DFEF79900F0628D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; EB798DFF1DFEF79900F0628D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; EB798E011DFEF79900F0628D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; EB798E041DFEF79900F0628D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; EB798E061DFEF79900F0628D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; EB798E0B1DFEF79900F0628D /* TrieTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TrieTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; EB798E0F1DFEF79900F0628D /* TrieTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrieTests.swift; sourceTree = ""; }; EB798E111DFEF79900F0628D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; EB798E161DFEF79900F0628D /* TrieUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TrieUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; EB798E1A1DFEF79900F0628D /* TrieUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrieUITests.swift; sourceTree = ""; }; EB798E1C1DFEF79900F0628D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; EB798E281DFEF81400F0628D /* Trie.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Trie.swift; sourceTree = ""; }; EB798E2B1DFEF90B00F0628D /* dictionary.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dictionary.txt; sourceTree = ""; }; EB8369AC1E15C5710003A7F8 /* ReadMe.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = ReadMe.md; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ EB798DF71DFEF79900F0628D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; EB798E081DFEF79900F0628D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; EB798E131DFEF79900F0628D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ EB798DF11DFEF79900F0628D = { isa = PBXGroup; children = ( EB798DFC1DFEF79900F0628D /* Trie */, EB798E0E1DFEF79900F0628D /* TrieTests */, EB798E191DFEF79900F0628D /* TrieUITests */, EB798DFB1DFEF79900F0628D /* Products */, ); indentWidth = 2; sourceTree = ""; tabWidth = 2; }; EB798DFB1DFEF79900F0628D /* Products */ = { isa = PBXGroup; children = ( EB798DFA1DFEF79900F0628D /* Trie.app */, EB798E0B1DFEF79900F0628D /* TrieTests.xctest */, EB798E161DFEF79900F0628D /* TrieUITests.xctest */, ); name = Products; sourceTree = ""; }; EB798DFC1DFEF79900F0628D /* Trie */ = { isa = PBXGroup; children = ( EB8369AC1E15C5710003A7F8 /* ReadMe.md */, EB798DFD1DFEF79900F0628D /* AppDelegate.swift */, EB798DFF1DFEF79900F0628D /* ViewController.swift */, EB798E011DFEF79900F0628D /* Assets.xcassets */, EB798E031DFEF79900F0628D /* Main.storyboard */, EB798E061DFEF79900F0628D /* Info.plist */, EB798E281DFEF81400F0628D /* Trie.swift */, EB798E2B1DFEF90B00F0628D /* dictionary.txt */, ); path = Trie; sourceTree = ""; }; EB798E0E1DFEF79900F0628D /* TrieTests */ = { isa = PBXGroup; children = ( EB798E0F1DFEF79900F0628D /* TrieTests.swift */, EB798E111DFEF79900F0628D /* Info.plist */, ); path = TrieTests; sourceTree = ""; }; EB798E191DFEF79900F0628D /* TrieUITests */ = { isa = PBXGroup; children = ( EB798E1A1DFEF79900F0628D /* TrieUITests.swift */, EB798E1C1DFEF79900F0628D /* Info.plist */, ); path = TrieUITests; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ EB798DF91DFEF79900F0628D /* Trie */ = { isa = PBXNativeTarget; buildConfigurationList = EB798E1F1DFEF79900F0628D /* Build configuration list for PBXNativeTarget "Trie" */; buildPhases = ( EB798DF61DFEF79900F0628D /* Sources */, EB798DF71DFEF79900F0628D /* Frameworks */, EB798DF81DFEF79900F0628D /* Resources */, ); buildRules = ( ); dependencies = ( ); name = Trie; productName = Trie; productReference = EB798DFA1DFEF79900F0628D /* Trie.app */; productType = "com.apple.product-type.application"; }; EB798E0A1DFEF79900F0628D /* TrieTests */ = { isa = PBXNativeTarget; buildConfigurationList = EB798E221DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieTests" */; buildPhases = ( EB798E071DFEF79900F0628D /* Sources */, EB798E081DFEF79900F0628D /* Frameworks */, EB798E091DFEF79900F0628D /* Resources */, ); buildRules = ( ); dependencies = ( EB798E0D1DFEF79900F0628D /* PBXTargetDependency */, ); name = TrieTests; productName = TrieTests; productReference = EB798E0B1DFEF79900F0628D /* TrieTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; EB798E151DFEF79900F0628D /* TrieUITests */ = { isa = PBXNativeTarget; buildConfigurationList = EB798E251DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieUITests" */; buildPhases = ( EB798E121DFEF79900F0628D /* Sources */, EB798E131DFEF79900F0628D /* Frameworks */, EB798E141DFEF79900F0628D /* Resources */, ); buildRules = ( ); dependencies = ( EB798E181DFEF79900F0628D /* PBXTargetDependency */, ); name = TrieUITests; productName = TrieUITests; productReference = EB798E161DFEF79900F0628D /* TrieUITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ EB798DF21DFEF79900F0628D /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0810; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Rick Zaccone"; TargetAttributes = { EB798DF91DFEF79900F0628D = { CreatedOnToolsVersion = 8.1; LastSwiftMigration = 1000; ProvisioningStyle = Automatic; }; EB798E0A1DFEF79900F0628D = { CreatedOnToolsVersion = 8.1; LastSwiftMigration = 1000; ProvisioningStyle = Automatic; TestTargetID = EB798DF91DFEF79900F0628D; }; EB798E151DFEF79900F0628D = { CreatedOnToolsVersion = 8.1; LastSwiftMigration = 1000; ProvisioningStyle = Automatic; TestTargetID = EB798DF91DFEF79900F0628D; }; }; }; buildConfigurationList = EB798DF51DFEF79900F0628D /* Build configuration list for PBXProject "Trie" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = EB798DF11DFEF79900F0628D; productRefGroup = EB798DFB1DFEF79900F0628D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( EB798DF91DFEF79900F0628D /* Trie */, EB798E0A1DFEF79900F0628D /* TrieTests */, EB798E151DFEF79900F0628D /* TrieUITests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ EB798DF81DFEF79900F0628D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( EB798E2C1DFEF90B00F0628D /* dictionary.txt in Resources */, EB798E021DFEF79900F0628D /* Assets.xcassets in Resources */, EB798E051DFEF79900F0628D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; EB798E091DFEF79900F0628D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( EB798E2D1DFEF90B00F0628D /* dictionary.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; EB798E141DFEF79900F0628D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ EB798DF61DFEF79900F0628D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( EB798E291DFEF81400F0628D /* Trie.swift in Sources */, EB798E001DFEF79900F0628D /* ViewController.swift in Sources */, EB798DFE1DFEF79900F0628D /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; EB798E071DFEF79900F0628D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( EB798E101DFEF79900F0628D /* TrieTests.swift in Sources */, EB798E2A1DFEF81400F0628D /* Trie.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; EB798E121DFEF79900F0628D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( EB798E1B1DFEF79900F0628D /* TrieUITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ EB798E0D1DFEF79900F0628D /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = EB798DF91DFEF79900F0628D /* Trie */; targetProxy = EB798E0C1DFEF79900F0628D /* PBXContainerItemProxy */; }; EB798E181DFEF79900F0628D /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = EB798DF91DFEF79900F0628D /* Trie */; targetProxy = EB798E171DFEF79900F0628D /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ EB798E031DFEF79900F0628D /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( EB798E041DFEF79900F0628D /* Base */, ); name = Main.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ EB798E1D1DFEF79900F0628D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; EB798E1E1DFEF79900F0628D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; EB798E201DFEF79900F0628D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Trie/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.Trie; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Debug; }; EB798E211DFEF79900F0628D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = Trie/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.Trie; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; }; name = Release; }; EB798E231DFEF79900F0628D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = TrieTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.TrieTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Trie.app/Contents/MacOS/Trie"; }; name = Debug; }; EB798E241DFEF79900F0628D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = TrieTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.TrieTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Trie.app/Contents/MacOS/Trie"; }; name = Release; }; EB798E261DFEF79900F0628D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = TrieUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.TrieUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; TEST_TARGET_NAME = Trie; }; name = Debug; }; EB798E271DFEF79900F0628D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = TrieUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = edu.bucknell.zaccone.TrieUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.2; TEST_TARGET_NAME = Trie; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ EB798DF51DFEF79900F0628D /* Build configuration list for PBXProject "Trie" */ = { isa = XCConfigurationList; buildConfigurations = ( EB798E1D1DFEF79900F0628D /* Debug */, EB798E1E1DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; EB798E1F1DFEF79900F0628D /* Build configuration list for PBXNativeTarget "Trie" */ = { isa = XCConfigurationList; buildConfigurations = ( EB798E201DFEF79900F0628D /* Debug */, EB798E211DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; EB798E221DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieTests" */ = { isa = XCConfigurationList; buildConfigurations = ( EB798E231DFEF79900F0628D /* Debug */, EB798E241DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; EB798E251DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( EB798E261DFEF79900F0628D /* Debug */, EB798E271DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = EB798DF21DFEF79900F0628D /* Project object */; } ================================================ FILE: Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Trie/Trie/Trie.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist ================================================ classNames TrieTests testInsertPerformance() com.apple.XCTPerformanceMetric_WallClockTime baselineAverage 3.407 baselineIntegrationDisplayName Local Baseline ================================================ FILE: Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist ================================================ runDestinationsByUUID 6ABF2F62-9363-4450-8DE1-D20F57026950 localComputer busSpeedInMHz 100 cpuCount 1 cpuKind Intel Core i7 cpuSpeedInMHz 3300 logicalCPUCoresPerPackage 4 modelCode MacBookPro13,2 physicalCPUCoresPerPackage 2 platformIdentifier com.apple.platform.macosx targetArchitecture x86_64 ================================================ FILE: Trie/Trie/TrieTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Trie/Trie/TrieTests/TrieTests.swift ================================================ // // TrieTests.swift // TrieTests // // Created by Rick Zaccone on 2016-12-12. // Copyright © 2016 Rick Zaccone. All rights reserved. // import XCTest @testable import Trie class TrieTests: XCTestCase { var wordArray: [String]? var trie = Trie() /// Makes sure that the wordArray and trie are initialized before each test. override func setUp() { super.setUp() createWordArray() insertWordsIntoTrie() } /// Don't need to do anything here because the wordArray and trie should /// stay around. override func tearDown() { super.tearDown() } /// Reads words from the dictionary file and inserts them into an array. If /// the word array already has words, do nothing. This allows running all /// tests without repeatedly filling the array with the same values. func createWordArray() { guard wordArray == nil else { return } let resourcePath = Bundle.main.resourcePath! as NSString let fileName = "dictionary.txt" let filePath = resourcePath.appendingPathComponent(fileName) var data: String? do { data = try String(contentsOfFile: filePath, encoding: String.Encoding.utf8) } catch let error as NSError { XCTAssertNil(error) } XCTAssertNotNil(data) let dictionarySize = 162825 wordArray = data!.components(separatedBy: "\n") XCTAssertEqual(wordArray!.count, dictionarySize) } /// Inserts words into a trie. If the trie is non-empty, don't do anything. func insertWordsIntoTrie() { guard let wordArray = wordArray, trie.count == 0 else { return } for word in wordArray { trie.insert(word: word) } } /// Tests that a newly created trie has zero words. func testCreate() { let trie = Trie() XCTAssertEqual(trie.count, 0) } /// Tests the insert method func testInsert() { let trie = Trie() trie.insert(word: "cute") trie.insert(word: "cutie") trie.insert(word: "fred") XCTAssertTrue(trie.contains(word: "cute")) XCTAssertFalse(trie.contains(word: "cut")) trie.insert(word: "cut") XCTAssertTrue(trie.contains(word: "cut")) XCTAssertEqual(trie.count, 4) } /// Tests the remove method func testRemove() { let trie = Trie() trie.insert(word: "cute") trie.insert(word: "cut") XCTAssertEqual(trie.count, 2) trie.remove(word: "cute") XCTAssertTrue(trie.contains(word: "cut")) XCTAssertFalse(trie.contains(word: "cute")) XCTAssertEqual(trie.count, 1) } /// Tests the words property func testWords() { let trie = Trie() var words = trie.words XCTAssertEqual(words.count, 0) trie.insert(word: "foobar") words = trie.words XCTAssertEqual(words[0], "foobar") XCTAssertEqual(words.count, 1) } /// Tests the performance of the insert method. func testInsertPerformance() { self.measure { let trie = Trie() for word in self.wordArray! { trie.insert(word: word) } } XCTAssertGreaterThan(trie.count, 0) XCTAssertEqual(trie.count, wordArray?.count) } /// Tests the performance of the insert method when the words are already /// present. func testInsertAgainPerformance() { self.measure { for word in self.wordArray! { self.trie.insert(word: word) } } } /// Tests the performance of the contains method. func testContainsPerformance() { self.measure { for word in self.wordArray! { XCTAssertTrue(self.trie.contains(word: word)) } } } /// Tests the performance of the remove method. Since setup has already put /// words into the trie, remove them before measuring performance. func testRemovePerformance() { for word in self.wordArray! { self.trie.remove(word: word) } self.measure { self.insertWordsIntoTrie() for word in self.wordArray! { self.trie.remove(word: word) } } XCTAssertEqual(trie.count, 0) } /// Tests the performance of the words computed property. Also tests to see /// if it worked properly. func testWordsPerformance() { var words: [String]? self.measure { words = self.trie.words } XCTAssertEqual(words?.count, trie.count) for word in words! { XCTAssertTrue(self.trie.contains(word: word)) } } /// Tests the archiving and unarchiving of the trie. func testArchiveAndUnarchive() { let resourcePath = Bundle.main.resourcePath! as NSString let fileName = "dictionary-archive" let filePath = resourcePath.appendingPathComponent(fileName) NSKeyedArchiver.archiveRootObject(trie, toFile: filePath) let trieCopy = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? Trie XCTAssertEqual(trieCopy?.count, trie.count) } /// Tests whether word prefixes are properly found and returned. func testFindWordsWithPrefix() { let trie = Trie() trie.insert(word: "test") trie.insert(word: "another") trie.insert(word: "exam") let wordsAll = trie.findWordsWithPrefix(prefix: "") XCTAssertEqual(wordsAll.sorted(), ["another", "exam", "test"]) let words = trie.findWordsWithPrefix(prefix: "ex") XCTAssertEqual(words, ["exam"]) trie.insert(word: "examination") let words2 = trie.findWordsWithPrefix(prefix: "exam") XCTAssertEqual(words2, ["exam", "examination"]) let noWords = trie.findWordsWithPrefix(prefix: "tee") XCTAssertEqual(noWords, []) let unicodeWord = "😬😎" trie.insert(word: unicodeWord) let wordsUnicode = trie.findWordsWithPrefix(prefix: "😬") XCTAssertEqual(wordsUnicode, [unicodeWord]) trie.insert(word: "Team") let wordsUpperCase = trie.findWordsWithPrefix(prefix: "Te") XCTAssertEqual(wordsUpperCase.sorted(), ["team", "test"]) } /// Tests whether word prefixes are properly detected on a boolean contains() check. func testContainsWordMatchPrefix() { let trie = Trie() trie.insert(word: "test") trie.insert(word: "another") trie.insert(word: "exam") let wordsAll = trie.contains(word: "", matchPrefix: true) XCTAssertEqual(wordsAll, true) let words = trie.contains(word: "ex", matchPrefix: true) XCTAssertEqual(words, true) trie.insert(word: "examination") let words2 = trie.contains(word: "exam", matchPrefix: true) XCTAssertEqual(words2, true) let noWords = trie.contains(word: "tee", matchPrefix: true) XCTAssertEqual(noWords, false) let unicodeWord = "😬😎" trie.insert(word: unicodeWord) let wordsUnicode = trie.contains(word: "😬", matchPrefix: true) XCTAssertEqual(wordsUnicode, true) trie.insert(word: "Team") let wordsUpperCase = trie.contains(word: "Te", matchPrefix: true) XCTAssertEqual(wordsUpperCase, true) } } ================================================ FILE: Trie/Trie/TrieUITests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleVersion 1 ================================================ FILE: Trie/Trie/TrieUITests/TrieUITests.swift ================================================ // // TrieUITests.swift // TrieUITests // // Created by Rick Zaccone on 2016-12-12. // Copyright © 2016 Rick Zaccone. All rights reserved. // import XCTest class TrieUITests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. // In UI tests it is usually best to stop immediately when a failure occurs. continueAfterFailure = false // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. XCUIApplication().launch() // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testExample() { // Use recording to get started writing UI tests. // Use XCTAssert and related functions to verify your tests produce the correct results. } } ================================================ FILE: Two-Sum Problem/README.markdown ================================================ # Two-Sum Problem Given an array of integers and an integer target, return the indices of two numbers that add up to the target. There are a variety of solutions to this problem (some better than others). The following solutions both run in **O(n)** time. # Solution 1 This solution looks at one number at a time, storing each number in the dictionary. It uses the number as the key and the number's index in the array as the value. For each number n, we know the complementing number to sum up to the target is `target - n`. By looking up the complement in the dictionary, we'd know whether we've seen the complement before and what its index is. ```swift func twoSum(_ nums: [Int], target: Int) -> (Int, Int)? { var dict = [Int: Int]() // For every number n, for (currentIndex, n) in nums.enumerated() { // Find the complement to n that would sum up to the target. let complement = target - n // Check if the complement is in the dictionary. if let complementIndex = dict[complement] { return (complementIndex, currentIndex) } // Store n and its index into the dictionary. dict[n] = currentIndex } return nil } ``` The `twoSum` function takes two parameters: the `numbers` array and the target sum. It returns the two indicies of the pair of elements that sums up to the target, or `nil` if they can't be found. Let's run through the algorithm to see how it works. Given the array: ```swift [3, 2, 9, 8] ``` Let's find out if there exist two entries whose sum is 10. Initially, our dictionary is empty. We begin looping through each element: - **currentIndex = 0** | n = nums[0] = 3 | complement = 10 - 3 = 7 Is the complement `7` in the dictionary? No, so we add `3` and its index `0` to the dictionary. ```swift [3: 0] ``` - **currentIndex = 1** | n = 2 | complement = 10 - 2 = 8 Is the complement `8` in the dictionary? No, so we add `2` and its index `1` to the dictionary. ```swift [3: 0, 2: 1] ``` - **currentIndex = 2** | n = 9 | complement = 10 - 9 = 1 Is the complement `1` in the dictionary? No, so we add `9` and its index `2` to the dictionary.: ```swift [3: 0, 2: 1, 9: 2] ``` - **currentIndex = 3** | n = 8 | complement = 10 - 8 = 2 Is the complement `2` in the dictionary? Yes! That means that we have found a pair of entries that sum to the target! Therefore, the `complementIndex = dict[2] = 1` and the `currentIndex = 3`. The tuple we return is `(1, 3)`. If the given array has multiple solutions, only the first solution is returned. The running time of this algorithm is **O(n)** because it may look at every element in the array. It also requires **O(n)** additional storage space for the dictionary. # Solution 2 **Note**: This particular algorithm requires that the array is sorted, so if the array isn't sorted yet (usually it won't be), you need to sort it first. The time complexity of the algorithm itself is **O(n)** and, unlike the previous solution, it does not require extra storage. Of course, if you have to sort first, the total time complexity becomes **O(n log n)**. Slightly worse but still quite acceptable. Here is the code in Swift: ```swift func twoSumProblem(_ a: [Int], k: Int) -> ((Int, Int))? { var i = 0 var j = a.count - 1 while i < j { let sum = a[i] + a[j] if sum == k { return (i, j) } else if sum < k { i += 1 } else { j -= 1 } } return nil } ``` As in the first solution, the `twoSumProblem()` function takes as parameters the array `a` with the numbers and `k`, the sum we're looking for. If there are two numbers that add up to `k`, the function returns a tuple containing their array indices. If not, it returns `nil`. The main difference is that `a` is assumed to be sorted. To test it, copy the code into a playground and add the following: ```swift let a = [2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100] if let (i, j) = twoSumProblem(a, k: 33) { a[i] + a[j] // 33 } ``` This returns the tuple `(8, 10)` because `a[8] = 12` and `a[10] = 21`, and together they add up to `33`. So how does this algorithm work? It takes advantage of the array being sorted. That's true for many algorithms, by the way. If you first sort the data, it's often easier to perform your calculations. In the example, the sorted array is: [ 2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100 ] The algorithm uses the two variables `i` and `j` to point to the beginning and end of the array, respectively. Then it increments `i` and decrements `j` until the two meet. While it's doing this, it checks whether `a[i]` and `a[j]` add up to `k`. Let's step through this. Initially, we have: [ 2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100 ] i j The sum of these two is `2 + 100 = 102`. That's obviously too much, since `k = 33` in this example. There is no way that `100` will ever be part of the answer, so decrement `j`. We have: [ 2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100 ] i j The sum is `2 + 22 = 24`. Now the sum is too small. We can safely conclude at this point that the number `2` will never be part of the answer. The largest number on the right is `22`, so we at least need `11` on the left to make `33`. Anything less than `11` is not going to cut it. (This is why we sorted the array!) So, `2` is out and we increment `i` to look at the next small number. [ 2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100 ] i j The sum is `3 + 22 = 25`. Still too small, so increment `i` again. [ 2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100 ] i j In fact, we have to increment `i` a few more times, until we get to `12`: [ 2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100 ] i j Now the sum is `12 + 22 = 34`. It's too high, which means we need to decrement `j`. This gives: [ 2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100 ] i j And finally, we have the answer: `12 + 21 = 33`. Yay! It's possible, of course, that there are no values for `a[i] + a[j]` that sum to `k`. In that case, eventually `i` and `j` will point at the same number. Then we can conclude that no answer exists and we return `nil`. I'm quite enamored by this little algorithm. It shows that with some basic preprocessing on the input data -- sorting it from low to high -- you can turn a tricky problem into a very simple and beautiful algorithm. ## Additional Reading * [3Sum / 4Sum](https://github.com/raywenderlich/swift-algorithm-club/tree/master/3Sum%20and%204Sum) *Written for Swift Algorithm Club by Matthijs Hollemans and Daniel Speiser updated to swift 4.2 by Farrukh Askari* ================================================ FILE: Two-Sum Problem/Solution 1/2Sum.playground/Contents.swift ================================================ //: Two Sum // Last checked with: Version 10.0 (10A255) func twoSum(_ nums: [Int], target: Int) -> (Int, Int)? { var dict = [Int: Int]() for (currentIndex, n) in nums.enumerated() { let complement = target - n if let complementIndex = dict[complement] { return (complementIndex, currentIndex) } dict[n] = currentIndex } return nil } twoSum([3, 2, 9, 8], target: 10) // expected output: indices 1 and 3 ================================================ FILE: Two-Sum Problem/Solution 1/2Sum.playground/contents.xcplayground ================================================ ================================================ FILE: Two-Sum Problem/Solution 1/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Two-Sum Problem/Solution 1/2Sum.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Two-Sum Problem/Solution 2/2Sum.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play // Last checked with: Version 10.0 (10A255) func twoSumProblem(_ a: [Int], k: Int) -> ((Int, Int))? { var i = 0 var j = a.count - 1 while i < j { let sum = a[i] + a[j] if sum == k { return (i, j) } else if sum < k { i += 1 } else { j -= 1 } } return nil } let a = [2, 3, 4, 4, 7, 8, 9, 10, 12, 14, 21, 22, 100] if let (i, j) = twoSumProblem(a, k: 33) { i // 8 a[i] // 12 j // 10 a[j] // 21 a[i] + a[j] // 33 } twoSumProblem(a, k: 37) // nil ================================================ FILE: Two-Sum Problem/Solution 2/2Sum.playground/contents.xcplayground ================================================ ================================================ FILE: Two-Sum Problem/Solution 2/2Sum.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Two-Sum Problem/Solution 2/2Sum.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: Under Construction.markdown ================================================ # Under Construction :construction: Here you'll find algorithms that are currently under construction. Suggestions and feedback is welcome! ### Sorting Special-purpose sorts: - [Radix Sort](Radix%20Sort/) ### Special-purpose sorts: - [Bucket Sort](Bucket%20Sort/) ### Queues - [Bounded Priority Queue](Bounded%20Priority%20Queue). A queue that is bounded to have a limited number of elements. ### Trees - [AVL Tree](AVL%20Tree/). A binary search tree that balances itself using rotations. - [Red-Black Tree](Red-Black%20Tree/) - [Threaded Binary Tree](Threaded%20Binary%20Tree/) - [Ternary Search Tree](Ternary%20Search%20Tree/) - [Trie](Trie/) - [Radix Tree](Radix%20Tree/) ### Miscellaneous - [Minimum Edit Distance](Minimum%20Edit%20Distance/). Measure the similarity of two strings by counting the number of operations required to transform one string into the other. - [Treap](Treap/) - [Set Cover (Unweighted)](Set%20Cover%20(Unweighted)/) ================================================ FILE: Union-Find/README.markdown ================================================ # Union-Find Union-Find is a data structure that can keep track of a set of elements partitioned into a number of disjoint (non-overlapping) subsets. It is also known as disjoint-set data structure. What do we mean by this? For example, the Union-Find data structure could be keeping track of the following sets: [ a, b, f, k ] [ e ] [ g, d, c ] [ i, j ] These sets are **disjoint** because they have no members in common. Union-Find supports three basic operations: 1. **Find(A)**: Determine which subset an element **A** is in. For example, `find(d)` would return the subset `[ g, d, c ]`. 2. **Union(A, B)**: Join two subsets that contain **A** and **B** into a single subset. For example, `union(d, j)` would combine `[ g, d, c ]` and `[ i, j ]` into the larger set `[ g, d, c, i, j ]`. 3. **AddSet(A)**: Add a new subset containing just that element **A**. For example, `addSet(h)` would add a new set `[ h ]`. The most common application of this data structure is keeping track of the connected components of an undirected [graph](../Graph/). It is also used for implementing an efficient version of Kruskal's algorithm to find the minimum spanning tree of a graph. ## Implementation Union-Find can be implemented in many ways but we'll look at an efficient and easy to understand implementation: Weighted Quick Union. > __PS: Multiple implementations of Union-Find has been included in playground.__ ```swift public struct UnionFind { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() } ``` Our Union-Find data structure is actually a forest where each subset is represented by a [tree](../Tree/). For our purposes we only need to keep track of the parent of each tree node, not the node's children. To do this we use the array `parent` so that `parent[i]` is the index of node `i`'s parent. Example: If `parent` looks like this, parent [ 1, 1, 1, 0, 2, 0, 6, 6, 6 ] i 0 1 2 3 4 5 6 7 8 then the tree structure looks like: 1 6 / \ / \ 0 2 7 8 / \ / 3 5 4 There are two trees in this forest, each of which corresponds to one set of elements. (Note: due to the limitations of ASCII art the trees are shown here as binary trees but that is not necessarily the case.) We give each subset a unique number to identify it. That number is the index of the root node of that subset's tree. In the example, node `1` is the root of the first tree and `6` is the root of the second tree. So in this example we have two subsets, the first with the label `1` and the second with the label `6`. The **Find** operation actually returns the set's label, not its contents. Note that the `parent[]` of a root node points to itself. So `parent[1] = 1` and `parent[6] = 6`. That's how we can tell something is a root node. ## Add set Let's look at the implementation of these basic operations, starting with adding a new set. ```swift public mutating func addSetWith(_ element: T) { index[element] = parent.count // 1 parent.append(parent.count) // 2 size.append(1) // 3 } ``` When you add a new element, this actually adds a new subset containing just that element. 1. We save the index of the new element in the `index` dictionary. That lets us look up the element quickly later on. 2. Then we add that index to the `parent` array to build a new tree for this set. Here, `parent[i]` is pointing to itself because the tree that represents the new set contains only one node, which of course is the root of that tree. 3. `size[i]` is the count of nodes in the tree whose root is at index `i`. For the new set this is 1 because it only contains the one element. We'll be using the `size` array in the Union operation. ## Find Often we want to determine whether we already have a set that contains a given element. That's what the **Find** operation does. In our `UnionFind` data structure it is called `setOf()`: ```swift public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { return nil } } ``` This looks up the element's index in the `index` dictionary and then uses a helper method to find the set that this element belongs to: ```swift private mutating func setByIndex(_ index: Int) -> Int { if parent[index] == index { // 1 return index } else { parent[index] = setByIndex(parent[index]) // 2 return parent[index] // 3 } } ``` Because we're dealing with a tree structure, this is a recursive method. Recall that each set is represented by a tree and that the index of the root node serves as the number that identifies the set. We're going to find the root node of the tree that the element we're searching for belongs to, and return its index. 1. First, we check if the given index represents a root node (i.e. a node whose `parent` points back to the node itself). If so, we're done. 2. Otherwise we recursively call this method on the parent of the current node. And then we do a **very important thing**: we overwrite the parent of the current node with the index of root node, in effect reconnecting the node directly to the root of the tree. The next time we call this method, it will execute faster because the path to the root of the tree is now much shorter. Without that optimization, this method's complexity is **O(n)** but now in combination with the size optimization (covered in the Union section) it is almost **O(1)**. 3. We return the index of the root node as the result. Here's illustration of what I mean. Let's say the tree looks like this: ![BeforeFind](Images/BeforeFind.png) We call `setOf(4)`. To find the root node we have to first go to node `2` and then to node `7`. (The indices of the elements are marked in red.) During the call to `setOf(4)`, the tree is reorganized to look like this: ![AfterFind](Images/AfterFind.png) Now if we need to call `setOf(4)` again, we no longer have to go through node `2` to get to the root. So as you use the Union-Find data structure, it optimizes itself. Pretty cool! There is also a helper method to check that two elements are in the same set: ```swift public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false } } ``` Since this calls `setOf()` it also optimizes the tree. ## Union (Weighted) The final operation is **Union**, which combines two sets into one larger set. ```swift public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { // 1 if firstSet != secondSet { // 2 if size[firstSet] < size[secondSet] { // 3 parent[firstSet] = secondSet // 4 size[secondSet] += size[firstSet] // 5 } else { parent[secondSet] = firstSet size[firstSet] += size[secondSet] } } } } ``` Here is how it works: 1. We find the sets that each element belongs to. Remember that this gives us two integers: the indices of the root nodes in the `parent` array. 2. Check that the sets are not equal because if they are it makes no sense to union them. 3. This is where the size optimization comes in (Weighting). We want to keep the trees as shallow as possible so we always attach the smaller tree to the root of the larger tree. To determine which is the smaller tree we compare trees by their sizes. 4. Here we attach the smaller tree to the root of the larger tree. 5. Update the size of larger tree because it just had a bunch of nodes added to it. An illustration may help to better understand this. Let's say we have these two sets, each with its own tree: ![BeforeUnion](Images/BeforeUnion.png) Now we call `unionSetsContaining(4, and: 3)`. The smaller tree is attached to the larger one: ![AfterUnion](Images/AfterUnion.png) Note that, because we call `setOf()` at the start of the method, the larger tree was also optimized in the process -- node `3` now hangs directly off the root. Union with optimizations also takes almost **O(1)** time. ## Path Compression ```swift private mutating func setByIndex(_ index: Int) -> Int { if index != parent[index] { // Updating parent index while looking up the index of parent. parent[index] = setByIndex(parent[index]) } return parent[index] } ``` Path Compression helps keep trees very flat, thus find operation could take __ALMOST__ in __O(1)__ ## Complexity Summary ##### To process N objects | Data Structure | Union | Find | |---|---|---| |Quick Find|N|1| |Quick Union|Tree height|Tree height| |Weighted Quick Union|lgN|lgN| |Weighted Quick Union + Path Compression| very close, but not O(1)| very close, but not O(1) | ##### To process M union commands on N objects | Algorithm | Worst-case time| |---|---| |Quick Find| M N | |Quick Union| M N | |Weighted Quick Union| N + M lgN | |Weighted Quick Union + Path Compression| (M + N) lgN | ## See also See the playground for more examples of how to use this handy data structure. [Union-Find at Wikipedia](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) *Written for Swift Algorithm Club by [Artur Antonov](https://github.com/goingreen)*, *modified by [Yi Ding](https://github.com/antonio081014).* ================================================ FILE: Union-Find/UnionFind.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play var dsu = UnionFindQuickUnion() for i in 1...10 { dsu.addSetWith(i) } // now our dsu contains 10 independent sets // let's divide our numbers into two sets by divisibility by 2 for i in 3...10 { if i % 2 == 0 { dsu.unionSetsContaining(2, and: i) } else { dsu.unionSetsContaining(1, and: i) } } // check our division print(dsu.inSameSet(2, and: 4)) print(dsu.inSameSet(4, and: 6)) print(dsu.inSameSet(6, and: 8)) print(dsu.inSameSet(8, and: 10)) print(dsu.inSameSet(1, and: 3)) print(dsu.inSameSet(3, and: 5)) print(dsu.inSameSet(5, and: 7)) print(dsu.inSameSet(7, and: 9)) print(dsu.inSameSet(7, and: 4)) print(dsu.inSameSet(3, and: 6)) var dsuForStrings = UnionFindQuickUnion() let words = ["all", "border", "boy", "afternoon", "amazing", "awesome", "best"] dsuForStrings.addSetWith("a") dsuForStrings.addSetWith("b") // In that example we divide strings by its first letter for word in words { dsuForStrings.addSetWith(word) if word.hasPrefix("a") { dsuForStrings.unionSetsContaining("a", and: word) } else if word.hasPrefix("b") { dsuForStrings.unionSetsContaining("b", and: word) } } print(dsuForStrings.inSameSet("a", and: "all")) print(dsuForStrings.inSameSet("all", and: "awesome")) print(dsuForStrings.inSameSet("amazing", and: "afternoon")) print(dsuForStrings.inSameSet("b", and: "boy")) print(dsuForStrings.inSameSet("best", and: "boy")) print(dsuForStrings.inSameSet("border", and: "best")) print(dsuForStrings.inSameSet("amazing", and: "boy")) print(dsuForStrings.inSameSet("all", and: "border")) ================================================ FILE: Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift ================================================ import Foundation /// Quick-find algorithm may take ~MN steps /// to process M union commands on N objects public struct UnionFindQuickFind { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() public init() {} public mutating func addSetWith(_ element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } private mutating func setByIndex(_ index: Int) -> Int { return parent[index] } public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { return nil } } public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { if firstSet != secondSet { for index in 0.. Bool { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false } } } ================================================ FILE: Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift ================================================ import Foundation /// Quick-Union algorithm may take ~MN steps /// to process M union commands on N objects public struct UnionFindQuickUnion { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() public init() {} public mutating func addSetWith(_ element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } private mutating func setByIndex(_ index: Int) -> Int { if parent[index] == index { return index } else { parent[index] = setByIndex(parent[index]) return parent[index] } } public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { return nil } } public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { if firstSet != secondSet { parent[firstSet] = secondSet size[secondSet] += size[firstSet] } } } public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false } } } ================================================ FILE: Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift ================================================ import Foundation /// Quick-find algorithm may take ~MN steps /// to process M union commands on N objects public struct UnionFindWeightedQuickFind { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() public init() {} public mutating func addSetWith(_ element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } private mutating func setByIndex(_ index: Int) -> Int { return parent[index] } public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { return nil } } public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { if firstSet != secondSet { if size[firstSet] < size[secondSet] { for index in 0.. Bool { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false } } } ================================================ FILE: Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift ================================================ import Foundation public struct UnionFindWeightedQuickUnion { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() public init() {} public mutating func addSetWith(_ element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } private mutating func setByIndex(_ index: Int) -> Int { if parent[index] == index { return index } else { parent[index] = setByIndex(parent[index]) return parent[index] } } public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { return nil } } /// Weighted, by comparing set size. /// Merge small set into the large one. public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { if firstSet != secondSet { if size[firstSet] < size[secondSet] { parent[firstSet] = secondSet size[secondSet] += size[firstSet] } else { parent[secondSet] = firstSet size[firstSet] += size[secondSet] } } } } public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false } } } ================================================ FILE: Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift ================================================ import Foundation public struct UnionFindWeightedQuickUnionPathCompression { private var index = [T: Int]() private var parent = [Int]() private var size = [Int]() public init() {} public mutating func addSetWith(_ element: T) { index[element] = parent.count parent.append(parent.count) size.append(1) } /// Path Compression. private mutating func setByIndex(_ index: Int) -> Int { if index != parent[index] { parent[index] = setByIndex(parent[index]) } return parent[index] } public mutating func setOf(_ element: T) -> Int? { if let indexOfElement = index[element] { return setByIndex(indexOfElement) } else { return nil } } public mutating func unionSetsContaining(_ firstElement: T, and secondElement: T) { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { if firstSet != secondSet { if size[firstSet] < size[secondSet] { parent[firstSet] = secondSet size[secondSet] += size[firstSet] } else { parent[secondSet] = firstSet size[firstSet] += size[secondSet] } } } } public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool { if let firstSet = setOf(firstElement), let secondSet = setOf(secondElement) { return firstSet == secondSet } else { return false } } } ================================================ FILE: Union-Find/UnionFind.playground/contents.xcplayground ================================================ ================================================ FILE: Union-Find/UnionFind.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Union-Find/UnionFind.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: What are Algorithms.markdown ================================================ # What are algorithms and data structures? An algorithm is a recipe for making the computer do something. If you know how to cook, you understand algorithms! Here's a [recipe for pancakes](http://allrecipes.com/recipe/21014/good-old-fashioned-pancakes/): 1. In a large bowl, sift together flour, baking powder, salt and sugar. 2. Pour in the milk, egg, and melted butter. 3. Mix until smooth. 4. Heat a frying pan over medium heat. 5. Scoop the batter into the pan, using approximately 1/4 cup for each pancake. 6. Brown the pancake on both sides. The recipe consists of a series of steps that you perform one after the other. An algorithm is just like that, except that it contains instructions for a computer to perform, not for a cook. The ingredients -- flour, milk, eggs, butter -- are the data that the algorithm works on. The data goes into the algorithm in one form (raw, separate ingredients) and comes out in another (delicious pancakes!). So what are the data structures? They are the containers that hold the data while the algorithm works on it. In the pancake recipe, the data structures are the bag that holds the flour, the mixing bowl where you combine everything, the frying pan that browns the pancake, and finally the plate used to serve the finished pancake. ================================================ FILE: Why Algorithms.markdown ================================================ # Why learn algorithms and data structures? If you've been coding for while you may wonder what the point is of learning about algorithms and data structures, especially if you don't have a formal computer science or engineering background. After all, how often do you actually have to use a linked list or write your own sort routine when you're making apps? The answer is: almost never. #### **However...** Knowing a little bit about the strategies used by algorithms to solve tricky problems gives you ideas for improvements you can make to your own code. Knowing more data structures than just the standard array and dictionary gives you a bigger collection of tools you can use to build your own apps. It will make you a better developer! (And better developers make more $$$.) #### Algorithms lets you build software you couldn't otherwise build There have been apps that I've been unable to create in the past because I got stuck on fundamental issues. Often it was a matter of speed: I just couldn't make the program go fast enough. Thinking back on this now, I had chosen the wrong algorithms for these problems. If I had known more about the difference between **O(n)** and **O(n^2)**, then maybe I would have had better luck. Naive brute-force solutions work fine for small amounts of data, but sometimes you need to deal with lots of data. And then you need smarter algorithms. There were also times I wasn't able to solve my programming problems at all, not even slowly. I simply didn't know where to begin. Understanding a bit of algorithm theory gives you various tactics you can try. #### Don't spend any time memorizing algorithms That's not the point. Instead, try to understand how different algorithms approach different problems. Learn about techniques such as divide-and-conquer, dynamic programming, greedy algorithms. See what makes one approach slow and another fast, and learn what the tradeoffs are. The key thing here is to get insight in how we can make computers do things. #### It's not as scary as it sounds A lot of algorithm textbooks start with a bunch of math. Truth is, the math is useful but most of the time you won't need it. So don't let that scare you. If you can write code, you can also understand all these fancy algorithms and data structures. Trust me, algorithms are fun. :-) ================================================ FILE: Z-Algorithm/README.markdown ================================================ # Z-Algorithm String Search Goal: Write a simple linear-time string matching algorithm in Swift that returns the indexes of all the occurrencies of a given pattern. In other words, we want to implement an `indexesOf(pattern: String)` extension on `String` that returns an array `[Int]` of integers, representing all occurrences' indexes of the search pattern, or `nil` if the pattern could not be found inside the string. For example: ```swift let str = "Hello, playground!" str.indexesOf(pattern: "ground") // Output: [11] let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" traffic.indexesOf(pattern: "🚑") // Output: [4, 21] ``` Many string search algorithms use a pre-processing function to compute a table that will be used in successive stage. This table can save some time during the pattern search stage because it allows to avoid un-needed characters comparisons. The [Z-Algorithm]() is one of these functions. It borns as a pattern pre-processing function (this is its role in the [Knuth-Morris-Pratt algorithm](../Knuth-Morris-Pratt/) and others) but, just like we will show here, it can be used also as a single string search algorithm. ### Z-Algorithm as pattern pre-processor As we said, the Z-Algorithm is foremost an algorithm that process a pattern in order to calculate a skip-comparisons-table. The computation of the Z-Algorithm over a pattern `P` produces an array (called `Z` in the literature) of integers in which each element, call it `Z[i]`, represents the length of the longest substring of `P` that starts at `i` and matches a prefix of `P`. In simpler words, `Z[i]` records the longest prefix of `P[i...|P|]` that matches a prefix of `P`. As an example, let's consider `P = "ffgtrhghhffgtggfredg"`. We have that `Z[5] = 0 (f...h...)`, `Z[9] = 4 (ffgtr...ffgtg...)` and `Z[15] = 1 (ff...fr...)`. But how do we compute `Z`? Before we describe the algorithm we must indroduce the concept of Z-box. A Z-box is a pair `(left, right)` used during the computation that records the substring of maximal length that occurs also as a prefix of `P`. The two indices `left` and `right` represent, respectively, the left-end index and the right-end index of this substring. The definition of the Z-Algorithm is inductive and it computes the elements of the array for every position `k` in the pattern, starting from `k = 1`. The following values (`Z[k + 1]`, `Z[k + 2]`, ...) are computed after `Z[k]`. The idea behind the algorithm is that previously computed values can speed up the calculus of `Z[k + 1]`, avoiding some character comparisons that were already done before. Consider this example: suppose we are at iteration `k = 100`, so we are analyzing position `100` of the pattern. All the values between `Z[1]` and `Z[99]` were correctly computed and `left = 70` and `right = 120`. This means that there is a substring of length `51` starting at position `70` and ending at position `120` that matches the prefix of the pattern/string we are considering. Reasoning on it a little bit we can say that the substring of length `21` starting at position `100` matches the substring of length `21` starting at position `30` of the pattern (because we are inside a substring that matches a prefix of the pattern). So we can use `Z[30]` to compute `Z[100]` without additional character comparisons. This a simple description of the idea that is behind this algorithm. There are a few cases to manage when the use of pre-computed values cannot be directly applied and some comparisons are to be made. Here is the code of the function that computes the Z-array: ```swift func ZetaAlgorithm(ptrn: String) -> [Int]? { let pattern = Array(ptrn) let patternLength: Int = pattern.count guard patternLength > 0 else { return nil } var zeta: [Int] = [Int](repeating: 0, count: patternLength) var left: Int = 0 var right: Int = 0 var k_1: Int = 0 var betaLength: Int = 0 var textIndex: Int = 0 var patternIndex: Int = 0 for k in 1 ..< patternLength { if k > right { // Outside a Z-box: compare the characters until mismatch patternIndex = 0 while k + patternIndex < patternLength && pattern[k + patternIndex] == pattern[patternIndex] { patternIndex = patternIndex + 1 } zeta[k] = patternIndex if zeta[k] > 0 { left = k right = k + zeta[k] - 1 } } else { // Inside a Z-box k_1 = k - left + 1 betaLength = right - k + 1 if zeta[k_1 - 1] < betaLength { // Entirely inside a Z-box: we can use the values computed before zeta[k] = zeta[k_1 - 1] } else if zeta[k_1 - 1] >= betaLength { // Not entirely inside a Z-box: we must proceed with comparisons too textIndex = betaLength patternIndex = right + 1 while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } zeta[k] = patternIndex - k left = k right = patternIndex - 1 } } } return zeta } ``` Let's make an example reasoning with the code above. Let's consider the string `P = “abababbb"`. The algorithm begins with `k = 1`, `left = right = 0`. So, no Z-box is "active" and thus, because `k > right` we start with the character comparisons beetwen `P[1]` and `P[0]`. 01234567 k: x abababbb x Z: 00000000 left: 0 right: 0 We have a mismatch at the first comparison and so the substring starting at `P[1]` does not match a prefix of `P`. So, we put `Z[1] = 0` and let `left` and `right` untouched. We begin another iteration with `k = 2`, we have `2 > 0` and again we start comparing characters `P[2]` with `P[0]`. This time the characters match and so we continue the comparisons until a mismatch occurs. It happens at position `6`. The characters matched are `4`, so we put `Z[2] = 4` and set `left = k = 2` and `right = k + Z[k] - 1 = 5`. We have our first Z-box that is the substring `"abab"` (notice that it matches a prefix of `P`) starting at position `left = 2`. 01234567 k: x abababbb x Z: 00400000 left: 2 right: 5 We then proceed with `k = 3`. We have `3 <= 5`. We are inside the Z-box previously found and inside a prefix of `P`. So we can look for a position that has a previously computed value. We calculate `k_1 = k - left = 1` that is the index of the prefix's character equal to `P[k]`. We check `Z[1] = 0` and `0 < (right - k + 1 = 3)` and we find that we are exactly inside the Z-box. We can use the previously computed value, so we put `Z[3] = Z[1] = 0`, `left` and `right` remain unchanged. At iteration `k = 4` we initially execute the `else` branch of the outer `if`. Then in the inner `if` we have that `k_1 = 2` and `(Z[2] = 4) >= 5 - 4 + 1`. So, the substring `P[k...r]` matches for `right - k + 1 = 2` chars the prefix of `P` but it could not for the following characters. We must then compare the characters starting at `r + 1 = 6` with those starting at `right - k + 1 = 2`. We have `P[6] != P[2]` and so we have to set `Z[k] = 6 - 4 = 2`, `left = 4` and `right = 5`. 01234567 k: x abababbb x Z: 00402000 left: 4 right: 5 With iteration `k = 5` we have `k <= right` and then `(Z[k_1] = 0) < (right - k + 1 = 1)` and so we set `z[k] = 0`. In iteration `6` and `7` we execute the first branch of the outer `if` but we only have mismatches, so the algorithms terminates returning the Z-array as `Z = [0, 0, 4, 0, 2, 0, 0, 0]`. The Z-Algorithm runs in linear time. More specifically, the Z-Algorithm for a string `P` of size `n` has a running time of `O(n)`. The implementation of Z-Algorithm as string pre-processor is contained in the [ZAlgorithm.swift](./ZAlgorithm.swift) file. ### Z-Algorithm as string search algorithm The Z-Algorithm discussed above leads to the simplest linear-time string matching algorithm. To obtain it, we have to simply concatenate the pattern `P` and text `T` in a string `S = P$T` where `$` is a character that does not appear neither in `P` nor `T`. Then we run the algorithm on `S` obtaining the Z-array. All we have to do now is scan the Z-array looking for elements equal to `n` (which is the pattern length). When we find such value we can report an occurrence. ```swift extension String { func indexesOf(pattern: String) -> [Int]? { let patternLength: Int = pattern.count /* Let's calculate the Z-Algorithm on the concatenation of pattern and text */ let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) guard zeta != nil else { return nil } var indexes: [Int] = [Int]() /* Scan the zeta array to find matched patterns */ for i in 0 ..< zeta!.count { if zeta![i] == patternLength { indexes.append(i - patternLength - 1) } } guard !indexes.isEmpty else { return nil } return indexes } } ``` Let's make an example. Let `P = “CATA“` and `T = "GAGAACATACATGACCAT"` be the pattern and the text. Let's concatenate them with the character `$`. We have the string `S = "CATA$GAGAACATACATGACCAT"`. After computing the Z-Algorithm on `S` we obtain: 1 2 01234567890123456789012 CATA$GAGAACATACATGACCAT Z 00000000004000300001300 ^ We scan the Z-array and at position `10` we find `Z[10] = 4 = n`. So we can report a match occuring at text position `10 - n - 1 = 5`. As said before, the complexity of this algorithm is linear. Defining `n` and `m` as pattern and text lengths, the final complexity we obtain is `O(n + m + 1) = O(n + m)`. Credits: This code is based on the handbook ["Algorithm on String, Trees and Sequences: Computer Science and Computational Biology"](https://books.google.it/books/about/Algorithms_on_Strings_Trees_and_Sequence.html?id=Ofw5w1yuD8kC&redir_esc=y) by Dan Gusfield, Cambridge University Press, 1997. *Written for Swift Algorithm Club by Matteo Dunnhofer* ================================================ FILE: Z-Algorithm/ZAlgorithm.swift ================================================ /* Z-Algorithm for pattern/string pre-processing The code is based on the book: "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" by Dan Gusfield Cambridge University Press, 1997 */ import Foundation func ZetaAlgorithm(ptrn: String) -> [Int]? { let pattern = Array(ptrn) let patternLength = pattern.count guard patternLength > 0 else { return nil } var zeta = [Int](repeating: 0, count: patternLength) var left = 0 var right = 0 var k_1 = 0 var betaLength = 0 var textIndex = 0 var patternIndex = 0 for k in 1 ..< patternLength { if k > right { patternIndex = 0 while k + patternIndex < patternLength && pattern[k + patternIndex] == pattern[patternIndex] { patternIndex = patternIndex + 1 } zeta[k] = patternIndex if zeta[k] > 0 { left = k right = k + zeta[k] - 1 } } else { k_1 = k - left + 1 betaLength = right - k + 1 if zeta[k_1 - 1] < betaLength { zeta[k] = zeta[k_1 - 1] } else if zeta[k_1 - 1] >= betaLength { textIndex = betaLength patternIndex = right + 1 while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } zeta[k] = patternIndex - k left = k right = patternIndex - 1 } } } return zeta } ================================================ FILE: Z-Algorithm/ZetaAlgorithm.playground/Contents.swift ================================================ //: Playground - noun: a place where people can play func ZetaAlgorithm(ptrn: String) -> [Int]? { let pattern = Array(ptrn) let patternLength = pattern.count guard patternLength > 0 else { return nil } var zeta = [Int](repeating: 0, count: patternLength) var left = 0 var right = 0 var k_1 = 0 var betaLength = 0 var textIndex = 0 var patternIndex = 0 for k in 1 ..< patternLength { if k > right { patternIndex = 0 while k + patternIndex < patternLength && pattern[k + patternIndex] == pattern[patternIndex] { patternIndex = patternIndex + 1 } zeta[k] = patternIndex if zeta[k] > 0 { left = k right = k + zeta[k] - 1 } } else { k_1 = k - left + 1 betaLength = right - k + 1 if zeta[k_1 - 1] < betaLength { zeta[k] = zeta[k_1 - 1] } else if zeta[k_1 - 1] >= betaLength { textIndex = betaLength patternIndex = right + 1 while patternIndex < patternLength && pattern[textIndex] == pattern[patternIndex] { textIndex = textIndex + 1 patternIndex = patternIndex + 1 } zeta[k] = patternIndex - k left = k right = patternIndex - 1 } } } return zeta } extension String { func indexesOf(pattern: String) -> [Int]? { let patternLength = pattern.count let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) guard zeta != nil else { return nil } var indexes: [Int] = [] /* Scan the zeta array to find matched patterns */ for i in 0 ..< zeta!.count { if zeta![i] == patternLength { indexes.append(i - patternLength - 1) } } guard !indexes.isEmpty else { return nil } return indexes } } /* Examples */ let str = "Hello, playground!" str.indexesOf(pattern: "ground") // [11] let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" traffic.indexesOf(pattern: "🚑") // [4, 21] ================================================ FILE: Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground ================================================ ================================================ FILE: Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Z-Algorithm/ZetaAlgorithm.swift ================================================ /* Z-Algorithm based algorithm for pattern/string matching The code is based on the book: "Algorithms on String, Trees and Sequences: Computer Science and Computational Biology" by Dan Gusfield Cambridge University Press, 1997 */ import Foundation extension String { func indexesOf(pattern: String) -> [Int]? { let patternLength = pattern.count let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) guard zeta != nil else { return nil } var indexes: [Int] = [Int]() /* Scan the zeta array to find matched patterns */ for i in 0 ..< zeta!.count { if zeta![i] == patternLength { indexes.append(i - patternLength - 1) } } guard !indexes.isEmpty else { return nil } return indexes } } ================================================ FILE: gfm-render.sh ================================================ #!/usr/bin/env bash set -e # $1 - readme file name function render_markdown_to_html { # escape escaping characters on Darwin only content=$( cat "$1" \ | sed 's/\\/\\\\/g' \ | sed 's/"/\\"/g' \ | sed $'s/\t/\\\\t/g' \ | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\\n/g' \ ) # network call to GitHub API json="{\"text\":\"$content\",\"mode\":\"gfm\",\"context\":\"$USERNAME/swift-algorithm-club\"}" echo -e "$(curl -s --data "$json" -u $USERNAME:$TOKEN https://api.github.com/markdown)" } # download github systax highlight stylesheet echo "> Downloading github-light.css..." curl -s -O https://raw.githubusercontent.com/primer/github-syntax-light/master/lib/github-light.css # slightly modify the main stylesheet echo "> Modifying github-light.css..." cat >> github-light.css << EOF #container { margin: 0 auto; width: 75%; min-width: 768px; max-width: 896px; position: relative; } body { font-size: 18px; } code { padding: 0.2em; margin: 0; font-size: 85%; background-color: #f6f8fa; line-height: 1.45; border-radius: 3px } pre code { padding: 0px; background-color: transparent; } .highlight { margin: 0px; padding: 0px 16px; font-size: 85%; line-height: 1.45; overflow: auto; background-color: #f6f8fa; border-radius: 3px; } @media (max-width: 768px) { #container { position: absolute; margin: 0; width: 100%; height: 100%; min-width: 100%; } } EOF # other markdown articles for title in "What are Algorithms" "Big-O Notation" "Algorithm Design" "Why Algorithms"; do echo "> Generating $title.html..." cat > "$title.html" << EOF $title
$(render_markdown_to_html "$title.markdown")
EOF done # if index.html does not exist, create one; # otherwise, empty its content. echo "> Generating index.html..." cat > index.html << EOF Swift Algorithm Club
$(render_markdown_to_html README.markdown | sed 's/.markdown/.html/g')
EOF # iterate immediate directories find . -maxdepth 1 -type d | while read folder; do readme='' # get the right extension for the README file if there is one if [[ -f $folder/README.md ]]; then readme="$folder/README.md"; fi if [[ -f $folder/README.markdown ]]; then readme="$folder/README.markdown"; fi # skip if there is no README or it it the README of the repository if [[ (-z $readme) || $readme == "./README.markdown" ]]; then continue; fi # render README to HTML name=$(basename "$folder") echo "> Generating $name/index.html..." cat > "$folder/index.html" << EOF $name
$(render_markdown_to_html "$readme")
EOF done # push to gh-pages if [[ $CI = true ]]; then git checkout -b gh-pages git add . git commit -m "$Generated by TravisCI on $(date +%D)" git push -f https://$TOKEN@github.com/$USERNAME/swift-algorithm-club.git gh-pages fi ================================================ FILE: install_swiftlint.sh ================================================ #!/bin/bash # Installs the SwiftLint package. # Tries to get the precompiled .pkg file from Github, but if that # fails just recompiles from source. set -e SWIFTLINT_PKG_PATH="/tmp/SwiftLint.pkg" SWIFTLINT_PKG_URL="https://github.com/realm/SwiftLint/releases/download/0.10.0/SwiftLint.pkg" wget --output-document=$SWIFTLINT_PKG_PATH $SWIFTLINT_PKG_URL if [ -f $SWIFTLINT_PKG_PATH ]; then echo "SwiftLint package exists! Installing it..." sudo installer -pkg $SWIFTLINT_PKG_PATH -target / else echo "SwiftLint package doesn't exist. Compiling from source..." && git clone https://github.com/realm/SwiftLint.git /tmp/SwiftLint && cd /tmp/SwiftLint && git submodule update --init --recursive && sudo make install fi