From 4470e09fd636ddfad61848dc99ed26e07e6a37f3 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 24 Sep 2016 14:04:23 +0200 Subject: [PATCH 0001/1039] first commit: added Knuth-Morris-Pratt and Z algorithms for string search --- .../Contents.swift | 122 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 65 ++++++++++ Z-Algorithm/ZAlgorithm.swift | 66 ++++++++++ .../ZetaAlgorithm.playground/Contents.swift | 95 ++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + Z-Algorithm/ZetaAlgorithm.swift | 32 +++++ 11 files changed, 414 insertions(+) create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.swift create mode 100644 Z-Algorithm/ZAlgorithm.swift create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/Contents.swift create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline create mode 100644 Z-Algorithm/ZetaAlgorithm.swift diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift new file mode 100644 index 000000000..147477c80 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift @@ -0,0 +1,122 @@ +//: Playground - noun: a place where people can play + + +func ZetaAlgorithm(ptnr: String) -> [Int]? { + + let pattern = Array(ptnr.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + 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.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](count: patternLength, repeatedValue: 0) + 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) + + for patternIndex in (1 ..< patternLength).reverse() { + 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("CATA") // [20, 64, 130, 140, 166, 234, 255, 270] + +let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" +concert.indexesOf("🎻🎷") // [6] diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift new file mode 100644 index 000000000..5cce1556f --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -0,0 +1,65 @@ +/* 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.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](count: patternLength, repeatedValue: 0) + 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) + + for patternIndex in (1 ..< patternLength).reverse() { + 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 + } +} diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift new file mode 100644 index 000000000..3b6d34908 --- /dev/null +++ b/Z-Algorithm/ZAlgorithm.swift @@ -0,0 +1,66 @@ +/* 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.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + 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 +} diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift new file mode 100644 index 000000000..dfe24ddf6 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -0,0 +1,95 @@ +//: Playground - noun: a place where people can play + + +func ZetaAlgorithm(ptrn: String) -> [Int]? { + + let pattern = Array(ptrn.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + 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(pattern: String) -> [Int]? { + let patternLength: Int = pattern.characters.count + let zeta = ZetaAlgorithm(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 + } +} + +/* Examples */ + +let str = "Hello, playground!" +str.indexesOf("ground") // [11] + +let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" +traffic.indexesOf("🚑") // [4, 21] diff --git a/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift new file mode 100644 index 000000000..c31e27c66 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -0,0 +1,32 @@ +/* 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: Int = pattern.characters.count + let zeta = ZetaAlgorithm(pattern + "💲" + self) + + var indexes: [Int] = [Int]() + + /* Scan the zeta array to find matched patterns */ + for index in indexes { + if index == patternLength { + indexes.append(index) + } + } + + guard !indexes.isEmpty else { + return nil + } + + return indexes + } +} From 6230a2bbc54bb08b9815764bcfc7909d471131c2 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 24 Sep 2016 14:31:50 +0200 Subject: [PATCH 0002/1039] removed directories --- .../Contents.swift | 122 ------------------ .../contents.xcplayground | 4 - .../contents.xcworkspacedata | 7 - .../timeline.xctimeline | 6 - Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 65 ---------- Z-Algorithm/ZAlgorithm.swift | 66 ---------- .../ZetaAlgorithm.playground/Contents.swift | 95 -------------- .../contents.xcplayground | 4 - .../contents.xcworkspacedata | 7 - .../timeline.xctimeline | 6 - Z-Algorithm/ZetaAlgorithm.swift | 32 ----- 11 files changed, 414 deletions(-) delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.swift delete mode 100644 Z-Algorithm/ZAlgorithm.swift delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/Contents.swift delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline delete mode 100644 Z-Algorithm/ZetaAlgorithm.swift diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift deleted file mode 100644 index 147477c80..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift +++ /dev/null @@ -1,122 +0,0 @@ -//: Playground - noun: a place where people can play - - -func ZetaAlgorithm(ptnr: String) -> [Int]? { - - let pattern = Array(ptnr.characters) - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) - - 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.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](count: patternLength, repeatedValue: 0) - 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) - - for patternIndex in (1 ..< patternLength).reverse() { - 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("CATA") // [20, 64, 130, 140, 166, 234, 255, 270] - -let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" -concert.indexesOf("🎻🎷") // [6] diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground deleted file mode 100644 index 06828af92..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift deleted file mode 100644 index 5cce1556f..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift +++ /dev/null @@ -1,65 +0,0 @@ -/* 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.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](count: patternLength, repeatedValue: 0) - 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) - - for patternIndex in (1 ..< patternLength).reverse() { - 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 - } -} diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift deleted file mode 100644 index 3b6d34908..000000000 --- a/Z-Algorithm/ZAlgorithm.swift +++ /dev/null @@ -1,66 +0,0 @@ -/* 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.characters) - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) - - 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 -} diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift deleted file mode 100644 index dfe24ddf6..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift +++ /dev/null @@ -1,95 +0,0 @@ -//: Playground - noun: a place where people can play - - -func ZetaAlgorithm(ptrn: String) -> [Int]? { - - let pattern = Array(ptrn.characters) - let patternLength: Int = pattern.count - - guard patternLength > 0 else { - return nil - } - - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) - - 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(pattern: String) -> [Int]? { - let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(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 - } -} - -/* Examples */ - -let str = "Hello, playground!" -str.indexesOf("ground") // [11] - -let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" -traffic.indexesOf("🚑") // [4, 21] diff --git a/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground deleted file mode 100644 index 06828af92..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift deleted file mode 100644 index c31e27c66..000000000 --- a/Z-Algorithm/ZetaAlgorithm.swift +++ /dev/null @@ -1,32 +0,0 @@ -/* 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: Int = pattern.characters.count - let zeta = ZetaAlgorithm(pattern + "💲" + self) - - var indexes: [Int] = [Int]() - - /* Scan the zeta array to find matched patterns */ - for index in indexes { - if index == patternLength { - indexes.append(index) - } - } - - guard !indexes.isEmpty else { - return nil - } - - return indexes - } -} From c416818dc12878181d8c5a0e54b78be72f68c665 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 24 Sep 2016 14:41:37 +0200 Subject: [PATCH 0003/1039] first commit: added Knuth-Morris-Pratt and Z algorithms implementation --- .../Contents.swift | 122 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 65 ++++++++++ Z-Algorithm/ZAlgorithm.swift | 66 ++++++++++ .../ZetaAlgorithm.playground/Contents.swift | 95 ++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + Z-Algorithm/ZetaAlgorithm.swift | 32 +++++ 11 files changed, 414 insertions(+) create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline create mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.swift create mode 100644 Z-Algorithm/ZAlgorithm.swift create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/Contents.swift create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline create mode 100644 Z-Algorithm/ZetaAlgorithm.swift diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift new file mode 100644 index 000000000..147477c80 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift @@ -0,0 +1,122 @@ +//: Playground - noun: a place where people can play + + +func ZetaAlgorithm(ptnr: String) -> [Int]? { + + let pattern = Array(ptnr.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + 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.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](count: patternLength, repeatedValue: 0) + 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) + + for patternIndex in (1 ..< patternLength).reverse() { + 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("CATA") // [20, 64, 130, 140, 166, 234, 255, 270] + +let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" +concert.indexesOf("🎻🎷") // [6] diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift new file mode 100644 index 000000000..5cce1556f --- /dev/null +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -0,0 +1,65 @@ +/* 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.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](count: patternLength, repeatedValue: 0) + 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) + + for patternIndex in (1 ..< patternLength).reverse() { + 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 + } +} diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift new file mode 100644 index 000000000..3b6d34908 --- /dev/null +++ b/Z-Algorithm/ZAlgorithm.swift @@ -0,0 +1,66 @@ +/* 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.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + 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 +} diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift new file mode 100644 index 000000000..dfe24ddf6 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -0,0 +1,95 @@ +//: Playground - noun: a place where people can play + + +func ZetaAlgorithm(ptrn: String) -> [Int]? { + + let pattern = Array(ptrn.characters) + let patternLength: Int = pattern.count + + guard patternLength > 0 else { + return nil + } + + var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + + 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(pattern: String) -> [Int]? { + let patternLength: Int = pattern.characters.count + let zeta = ZetaAlgorithm(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 + } +} + +/* Examples */ + +let str = "Hello, playground!" +str.indexesOf("ground") // [11] + +let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" +traffic.indexesOf("🚑") // [4, 21] diff --git a/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground new file mode 100644 index 000000000..06828af92 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift new file mode 100644 index 000000000..c31e27c66 --- /dev/null +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -0,0 +1,32 @@ +/* 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: Int = pattern.characters.count + let zeta = ZetaAlgorithm(pattern + "💲" + self) + + var indexes: [Int] = [Int]() + + /* Scan the zeta array to find matched patterns */ + for index in indexes { + if index == patternLength { + indexes.append(index) + } + } + + guard !indexes.isEmpty else { + return nil + } + + return indexes + } +} From e3967dfdd69b3a04243760d4ce73fd83576fef15 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 24 Sep 2016 21:15:04 +0200 Subject: [PATCH 0004/1039] swift 3 fix --- .../Contents.swift | 12 +++---- .../timeline.xctimeline | 6 ---- Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 32 +++++++++---------- Z-Algorithm/ZAlgorithm.swift | 26 +++++++-------- .../ZetaAlgorithm.playground/Contents.swift | 8 ++--- .../timeline.xctimeline | 6 ---- Z-Algorithm/ZetaAlgorithm.swift | 22 +++++++------ 7 files changed, 52 insertions(+), 60 deletions(-) delete mode 100644 Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline delete mode 100644 Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift index 147477c80..35fb27ff8 100644 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/Contents.swift @@ -10,7 +10,7 @@ func ZetaAlgorithm(ptnr: String) -> [Int]? { return nil } - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + var zeta: [Int] = [Int](repeating: 0, count: patternLength) var left: Int = 0 var right: Int = 0 @@ -71,15 +71,15 @@ extension String { return nil } - var suffixPrefix: [Int] = [Int](count: patternLength, repeatedValue: 0) + 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) + let zeta = ZetaAlgorithm(ptnr: ptnr) - for patternIndex in (1 ..< patternLength).reverse() { + for patternIndex in (1 ..< patternLength).reversed() { textIndex = patternIndex + zeta![patternIndex] - 1 suffixPrefix[textIndex] = zeta![patternIndex] } @@ -116,7 +116,7 @@ extension String { /* Examples */ let dna = "ACCCGGTTTTAAAGAACCACCATAAGATATAGACAGATATAGGACAGATATAGAGACAAAACCCCATACCCCAATATTTTTTTGGGGAGAAAAACACCACAGATAGATACACAGACTACACGAGATACGACATACAGCAGCATAACGACAACAGCAGATAGACGATCATAACAGCAATCAGACCGAGCGCAGCAGCTTTTAAGCACCAGCCCCACAAAAAACGACAATFATCATCATATACAGACGACGACACGACATATCACACGACAGCATA" -dna.indexesOf("CATA") // [20, 64, 130, 140, 166, 234, 255, 270] +dna.indexesOf(ptnr: "CATA") // [20, 64, 130, 140, 166, 234, 255, 270] let concert = "🎼🎹🎹🎸🎸🎻🎻🎷🎺🎤👏👏👏" -concert.indexesOf("🎻🎷") // [6] +concert.indexesOf(ptnr: "🎻🎷") // [6] diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline b/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift index 5cce1556f..46a88c134 100644 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -9,54 +9,54 @@ import Foundation 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](count: patternLength, repeatedValue: 0) + + 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) - - for patternIndex in (1 ..< patternLength).reverse() { + 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 } diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift index 3b6d34908..c9d7de876 100644 --- a/Z-Algorithm/ZAlgorithm.swift +++ b/Z-Algorithm/ZAlgorithm.swift @@ -9,34 +9,34 @@ import Foundation func ZetaAlgorithm(ptrn: String) -> [Int]? { - + let pattern = Array(ptrn.characters) let patternLength: Int = pattern.count - + guard patternLength > 0 else { return nil } - - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) - + + 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 + patternIndex = patternIndex + 1 } - + zeta[k] = patternIndex - + if zeta[k] > 0 { left = k right = k + zeta[k] - 1 @@ -44,18 +44,18 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { } 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 diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift index dfe24ddf6..c9d942149 100644 --- a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -10,7 +10,7 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { return nil } - var zeta: [Int] = [Int](count: patternLength, repeatedValue: 0) + var zeta: [Int] = [Int](repeating: 0, count: patternLength) var left: Int = 0 var right: Int = 0 @@ -63,7 +63,7 @@ extension String { func indexesOf(pattern: String) -> [Int]? { let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(pattern + "💲" + self) + let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) guard zeta != nil else { return nil @@ -89,7 +89,7 @@ extension String { /* Examples */ let str = "Hello, playground!" -str.indexesOf("ground") // [11] +str.indexesOf(pattern: "ground") // [11] let traffic = "🚗🚙🚌🚕🚑🚐🚗🚒🚚🚎🚛🚐🏎🚜🚗🏍🚒🚲🚕🚓🚌🚑" -traffic.indexesOf("🚑") // [4, 21] +traffic.indexesOf(pattern: "🚑") // [4, 21] diff --git a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline b/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Z-Algorithm/ZetaAlgorithm.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift index c31e27c66..4d80aa665 100644 --- a/Z-Algorithm/ZetaAlgorithm.swift +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -9,24 +9,28 @@ import Foundation extension String { - + func indexesOf(pattern: String) -> [Int]? { let patternLength: Int = pattern.characters.count - let zeta = ZetaAlgorithm(pattern + "💲" + self) - + 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 index in indexes { - if index == patternLength { - indexes.append(index) + for i in 0 ..< zeta!.count { + if zeta![i] == patternLength { + indexes.append(i - patternLength - 1) } } - + guard !indexes.isEmpty else { return nil } - + return indexes } } From a172311433bc1c9cbd86f21cc284731ff04a9510 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Wed, 28 Sep 2016 14:14:24 +0200 Subject: [PATCH 0005/1039] added Z-Algorithm README --- Z-Algorithm/README.markdown | 176 ++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 Z-Algorithm/README.markdown diff --git a/Z-Algorithm/README.markdown b/Z-Algorithm/README.markdown new file mode 100644 index 000000000..7fbb9b48b --- /dev/null +++ b/Z-Algorithm/README.markdown @@ -0,0 +1,176 @@ +# 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.characters) + 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 = “abababab"`. 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.characters.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"]() by Dan Gusfield, Cambridge University Press, 1997. + +*Written for Swift Algorithm Club by Matteo Dunnhofer* From 41712e0275fbc50e63f32580d402ca12d1648888 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Wed, 28 Sep 2016 14:20:58 +0200 Subject: [PATCH 0006/1039] edited Z-Algorithm README --- Z-Algorithm/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Z-Algorithm/README.markdown b/Z-Algorithm/README.markdown index 7fbb9b48b..c6c50a23b 100644 --- a/Z-Algorithm/README.markdown +++ b/Z-Algorithm/README.markdown @@ -86,7 +86,7 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { } ``` -Let's make an example reasoning with the code above. Let's consider the string `P = “abababab"`. 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]`. +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 @@ -171,6 +171,6 @@ We scan the Z-array and at position `10` we find `Z[10] = 4 = n`. So we can repo 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"]() by Dan Gusfield, Cambridge University Press, 1997. +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* From 72ee49b05218ce4ca627caabaa9b2960154a9dde Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Wed, 28 Sep 2016 16:32:15 +0200 Subject: [PATCH 0007/1039] edited Z-Algorithm README --- Z-Algorithm/README.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Z-Algorithm/README.markdown b/Z-Algorithm/README.markdown index c6c50a23b..8b84c28bf 100644 --- a/Z-Algorithm/README.markdown +++ b/Z-Algorithm/README.markdown @@ -26,8 +26,7 @@ The definition of the Z-Algorithm is inductive and it computes the elements of t 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 +```swift func ZetaAlgorithm(ptrn: String) -> [Int]? { let pattern = Array(ptrn.characters) From b8ea4fd9b63ac20c3ae521d3a1ff018500a587d3 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 1 Oct 2016 23:02:12 +0200 Subject: [PATCH 0008/1039] added Knuth-Morris-Pratt README --- Knuth-Morris-Pratt/README.markdown | 157 +++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 Knuth-Morris-Pratt/README.markdown diff --git a/Knuth-Morris-Pratt/README.markdown b/Knuth-Morris-Pratt/README.markdown new file mode 100644 index 000000000..ab8e78cdc --- /dev/null +++ b/Knuth-Morris-Pratt/README.markdown @@ -0,0 +1,157 @@ +# 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/) 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 String Search/) 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* From 5423763065c6844d2c573b76435623662670b947 Mon Sep 17 00:00:00 2001 From: dontfollowmeimcrazy Date: Sat, 1 Oct 2016 23:05:50 +0200 Subject: [PATCH 0009/1039] edited Knuth-Morris-Pratt README --- Knuth-Morris-Pratt/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Knuth-Morris-Pratt/README.markdown b/Knuth-Morris-Pratt/README.markdown index ab8e78cdc..f01b87b3d 100644 --- a/Knuth-Morris-Pratt/README.markdown +++ b/Knuth-Morris-Pratt/README.markdown @@ -18,7 +18,7 @@ The [Knuth-Morris-Pratt algorithm](https://en.wikipedia.org/wiki/Knuth–Morris The idea behind the algorithm is not too different from the [naive string search](../Brute-Force String Search/) 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`. +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 From 133f2d85b0fa188da954c837381570efd263a5ec Mon Sep 17 00:00:00 2001 From: Sahn Cha Date: Tue, 18 Oct 2016 23:35:15 +0900 Subject: [PATCH 0010/1039] Miller-Rabin primality test: probabilistic version --- Miller-Rabin Primality Test/MRPrimality.swift | 61 +++++++++++++++++++ .../contents.xcworkspacedata | 7 +++ 2 files changed, 68 insertions(+) create mode 100644 Miller-Rabin Primality Test/MRPrimality.swift diff --git a/Miller-Rabin Primality Test/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.swift new file mode 100644 index 000000000..8be5ab00d --- /dev/null +++ b/Miller-Rabin Primality Test/MRPrimality.swift @@ -0,0 +1,61 @@ +// +// MRPrimality.swift +// +// +// Created by Sahn Cha on 2016. 10. 18.. +// +// + +import Foundation + +public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { + guard n > 2 && n % 2 == 1 else { return false } + + var d = n - 1 + var s = 0 + + while d % 2 == 0 { + d /= 2 + s += 1 + } + + let range = UInt64.max - UInt64.max % (n - 2) + var r: UInt64 = 0 + + repeat { + arc4random_buf(&r, MemoryLayout.size(ofValue: r)) + } while r >= range + + r = r % (n - 2) + 2 + + for _ in 1 ... k { + var x = modpow64(r, d, n) + if x == 1 || x == n - 1 { continue } + + for _ in 1 ... s - 1 { + x = modpow64(x, 2, n) + if x == 1 { return false } + if x == n - 1 { break } + } + + if x != n - 1 { return false } + } + return true +} + +private func modpow64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { + if m == 1 { return 0 } + + var result: UInt64 = 1 + var b = base % m + var e = exp + + while e > 0 { + if e % 2 == 1 { + result = (result * b) % m + } + e >>= 1 + b = (b * b) % m + } + return result +} diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index e7288f299..fb2aeda4b 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -25,6 +25,13 @@ + + + + From 902e6f6a4a9ec8780029e1c9f8277f9b86841948 Mon Sep 17 00:00:00 2001 From: Sahn Cha Date: Thu, 20 Oct 2016 02:09:45 +0900 Subject: [PATCH 0011/1039] Now with playground, comments and pesticide --- .../MRPrimality.playground/Contents.swift | 24 ++++ .../Sources/MRPrimality.swift | 111 ++++++++++++++++++ .../contents.xcplayground | 4 + Miller-Rabin Primality Test/MRPrimality.swift | 66 +++++++++-- .../contents.xcworkspacedata | 3 + 5 files changed, 200 insertions(+), 8 deletions(-) create mode 100644 Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift create mode 100644 Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift create mode 100644 Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift b/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift new file mode 100644 index 000000000..8d97dc409 --- /dev/null +++ b/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift @@ -0,0 +1,24 @@ +//: Playground - noun: a place where people can play + +// Real primes +mrPrimalityTest(5) +mrPrimalityTest(439) +mrPrimalityTest(1201) +mrPrimalityTest(143477) +mrPrimalityTest(1299869) +mrPrimalityTest(15487361) +mrPrimalityTest(179426363) +mrPrimalityTest(32416187747) + +// Fake primes +mrPrimalityTest(15) +mrPrimalityTest(435) +mrPrimalityTest(1207) +mrPrimalityTest(143473) +mrPrimalityTest(1291869) +mrPrimalityTest(15487161) +mrPrimalityTest(178426363) +mrPrimalityTest(32415187747) + +// With iteration +mrPrimalityTest(32416190071, iteration: 10) \ No newline at end of file diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift new file mode 100644 index 000000000..9dca23996 --- /dev/null +++ b/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift @@ -0,0 +1,111 @@ +// +// MRPrimality.swift +// +// +// Created by Sahn Cha on 2016. 10. 18.. +// +// + +import Foundation + +/* + Miller-Rabin Primality Test. + One of the most used algorithms for primality testing. + Since this is a probabilistic algorithm, it needs to be executed multiple times to increase accuracy. + + Inputs: + n: UInt64 { target integer to be tested for primality } + k: Int { optional. number of iterations } + + Outputs: + true { probably prime } + false { composite } + */ +public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { + guard n > 2 && n % 2 == 1 else { return false } + + var d = n - 1 + var s = 0 + + while d % 2 == 0 { + d /= 2 + s += 1 + } + + let range = UInt64.max - UInt64.max % (n - 2) + var r: UInt64 = 0 + repeat { + arc4random_buf(&r, MemoryLayout.size(ofValue: r)) + } while r >= range + + r = r % (n - 2) + 2 + + for _ in 1 ... k { + var x = powmod64(r, d, n) + if x == 1 || x == n - 1 { continue } + + if s == 1 { s = 2 } + + for _ in 1 ... s - 1 { + x = powmod64(x, 2, n) + if x == 1 { return false } + if x == n - 1 { break } + } + + if x != n - 1 { return false } + } + + return true +} + +/* + Calculates (base^exp) mod m. + + Inputs: + base: UInt64 { base } + exp: UInt64 { exponent } + m: UInt64 { modulus } + + Outputs: + the result + */ +private func powmod64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { + if m == 1 { return 0 } + + var result: UInt64 = 1 + var b = base % m + var e = exp + + while e > 0 { + if e % 2 == 1 { result = mulmod64(result, b, m) } + b = mulmod64(b, b, m) + e >>= 1 + } + + return result +} + +/* + Calculates (first * second) mod m, hopefully without overflow. :] + + Inputs: + first: UInt64 { first integer } + second: UInt64 { second integer } + m: UInt64 { modulus } + + Outputs: + the result + */ +private func mulmod64(_ first: UInt64, _ second: UInt64, _ m: UInt64) -> UInt64 { + var result: UInt64 = 0 + var a = first + var b = second + + while a != 0 { + if a % 2 == 1 { result = ((result % m) + (b % m)) % m } // This may overflow if 'm' is a 64bit number && both 'result' and 'b' are very close to but smaller than 'm'. + a >>= 1 + b = (b << 1) % m + } + + return result +} diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground b/Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground new file mode 100644 index 000000000..63b6dd8df --- /dev/null +++ b/Miller-Rabin Primality Test/MRPrimality.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Miller-Rabin Primality Test/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.swift index 8be5ab00d..9dca23996 100644 --- a/Miller-Rabin Primality Test/MRPrimality.swift +++ b/Miller-Rabin Primality Test/MRPrimality.swift @@ -8,6 +8,19 @@ import Foundation +/* + Miller-Rabin Primality Test. + One of the most used algorithms for primality testing. + Since this is a probabilistic algorithm, it needs to be executed multiple times to increase accuracy. + + Inputs: + n: UInt64 { target integer to be tested for primality } + k: Int { optional. number of iterations } + + Outputs: + true { probably prime } + false { composite } + */ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { guard n > 2 && n % 2 == 1 else { return false } @@ -21,7 +34,6 @@ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { let range = UInt64.max - UInt64.max % (n - 2) var r: UInt64 = 0 - repeat { arc4random_buf(&r, MemoryLayout.size(ofValue: r)) } while r >= range @@ -29,21 +41,35 @@ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { r = r % (n - 2) + 2 for _ in 1 ... k { - var x = modpow64(r, d, n) + var x = powmod64(r, d, n) if x == 1 || x == n - 1 { continue } + if s == 1 { s = 2 } + for _ in 1 ... s - 1 { - x = modpow64(x, 2, n) + x = powmod64(x, 2, n) if x == 1 { return false } if x == n - 1 { break } } if x != n - 1 { return false } } + return true } -private func modpow64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { +/* + Calculates (base^exp) mod m. + + Inputs: + base: UInt64 { base } + exp: UInt64 { exponent } + m: UInt64 { modulus } + + Outputs: + the result + */ +private func powmod64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { if m == 1 { return 0 } var result: UInt64 = 1 @@ -51,11 +77,35 @@ private func modpow64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { var e = exp while e > 0 { - if e % 2 == 1 { - result = (result * b) % m - } + if e % 2 == 1 { result = mulmod64(result, b, m) } + b = mulmod64(b, b, m) e >>= 1 - b = (b * b) % m } + + return result +} + +/* + Calculates (first * second) mod m, hopefully without overflow. :] + + Inputs: + first: UInt64 { first integer } + second: UInt64 { second integer } + m: UInt64 { modulus } + + Outputs: + the result + */ +private func mulmod64(_ first: UInt64, _ second: UInt64, _ m: UInt64) -> UInt64 { + var result: UInt64 = 0 + var a = first + var b = second + + while a != 0 { + if a % 2 == 1 { result = ((result % m) + (b % m)) % m } // This may overflow if 'm' is a 64bit number && both 'result' and 'b' are very close to but smaller than 'm'. + a >>= 1 + b = (b << 1) % m + } + return result } diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index fb2aeda4b..dd0c6b668 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -31,6 +31,9 @@ + + Date: Thu, 20 Oct 2016 10:03:44 -0400 Subject: [PATCH 0012/1039] Switched to Double to handle large prime multiplier --- README.markdown | 2 +- Rabin-Karp/README.markdown | 79 ++++++++++++++ .../Rabin-Karp.playground/Contents.swift | 85 +++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 ++ Rabin-Karp/rabin-karp.swift | 103 ++++++++++++++++++ 6 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 Rabin-Karp/README.markdown create mode 100644 Rabin-Karp/Rabin-Karp.playground/Contents.swift create mode 100644 Rabin-Karp/Rabin-Karp.playground/contents.xcplayground create mode 100644 Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Rabin-Karp/rabin-karp.swift diff --git a/README.markdown b/README.markdown index 28a56dfd3..1bf9e7e6a 100644 --- a/README.markdown +++ b/README.markdown @@ -56,7 +56,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Brute-Force String Search](Brute-Force String Search/). A naive method. - [Boyer-Moore](Boyer-Moore/). 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 -- Rabin-Karp +- [Rabin-Karp](Rabin-Karp/) Faster search by using hashing. - [Longest Common Subsequence](Longest Common Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. ### Sorting diff --git a/Rabin-Karp/README.markdown b/Rabin-Karp/README.markdown new file mode 100644 index 000000000..0c3d0b1be --- /dev/null +++ b/Rabin-Karp/README.markdown @@ -0,0 +1,79 @@ +# Rabin-Karp string search algorithm + +The Rabin-Karp string search alogrithm is used to search text for a pattern. + +Algorithms that check for palindromes are a common programming interview question. + +## 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 alogrithm 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 (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.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 +} +``` + +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)* \ No newline at end of file diff --git a/Rabin-Karp/Rabin-Karp.playground/Contents.swift b/Rabin-Karp/Rabin-Karp.playground/Contents.swift new file mode 100644 index 000000000..f9c8c1919 --- /dev/null +++ b/Rabin-Karp/Rabin-Karp.playground/Contents.swift @@ -0,0 +1,85 @@ +//: Taking our rabin-karp algorithm for a walk + +import UIKit + +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") == Int(-1), "Invalid index returned") +assert(search(text:"The big dog jumped over the fox", pattern:"T") == 0, "Invalid index returned") diff --git a/Rabin-Karp/Rabin-Karp.playground/contents.xcplayground b/Rabin-Karp/Rabin-Karp.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Rabin-Karp/Rabin-Karp.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata b/Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Rabin-Karp/Rabin-Karp.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Rabin-Karp/rabin-karp.swift b/Rabin-Karp/rabin-karp.swift new file mode 100644 index 000000000..54ef24fce --- /dev/null +++ b/Rabin-Karp/rabin-karp.swift @@ -0,0 +1,103 @@ +// 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") \ No newline at end of file From 4813ee12dcd26489ab10176694829a6c1d98c669 Mon Sep 17 00:00:00 2001 From: billbarbour Date: Thu, 20 Oct 2016 11:27:13 -0400 Subject: [PATCH 0013/1039] Corrected copy pasta --- Rabin-Karp/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rabin-Karp/README.markdown b/Rabin-Karp/README.markdown index 0c3d0b1be..79699caa8 100644 --- a/Rabin-Karp/README.markdown +++ b/Rabin-Karp/README.markdown @@ -2,7 +2,7 @@ The Rabin-Karp string search alogrithm is used to search text for a pattern. -Algorithms that check for palindromes are a common programming interview question. +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 From 663f902de3b1066c9c8bfc93bdbc05836d05fb02 Mon Sep 17 00:00:00 2001 From: billbarbour Date: Thu, 20 Oct 2016 11:56:09 -0400 Subject: [PATCH 0014/1039] linter cleanup --- .../Rabin-Karp.playground/Contents.swift | 45 ++++++++++++------- Rabin-Karp/rabin-karp.swift | 29 ++++++++---- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/Rabin-Karp/Rabin-Karp.playground/Contents.swift b/Rabin-Karp/Rabin-Karp.playground/Contents.swift index f9c8c1919..4956fabe3 100644 --- a/Rabin-Karp/Rabin-Karp.playground/Contents.swift +++ b/Rabin-Karp/Rabin-Karp.playground/Contents.swift @@ -16,70 +16,81 @@ func ** (radix: Double, power: Int) -> Double { } extension Character { - var asInt:Int { + 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 { +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) { + + 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) - + 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 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)) + 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") == Int(-1), "Invalid index returned") -assert(search(text:"The big dog jumped over the fox", pattern:"T") == 0, "Invalid index returned") +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") diff --git a/Rabin-Karp/rabin-karp.swift b/Rabin-Karp/rabin-karp.swift index 54ef24fce..c337de1a7 100644 --- a/Rabin-Karp/rabin-karp.swift +++ b/Rabin-Karp/rabin-karp.swift @@ -34,14 +34,14 @@ func ** (radix: Double, power: Int) -> Double { } extension Character { - var asInt:Int { + 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 { +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 } @@ -55,7 +55,7 @@ public func search(text: String , pattern: String) -> Int { let firstChars = Array(textArray[0...endIdx]) let firstHash = hash(array: firstChars) - if (patternHash == firstHash) { + if patternHash == firstHash { // Verify this was not a hash collison if firstChars == patternArray { return 0 @@ -67,7 +67,12 @@ public func search(text: String , pattern: String) -> Int { 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) + let windowHash = nextHash( + prevHash: prevHash, + dropped: textArray[idx - 1], + added: textArray[endIdx], + patternSize: patternArray.count - 1 + ) if windowHash == patternHash { if patternArray == window { @@ -82,7 +87,7 @@ public func search(text: String , pattern: String) -> Int { } public func hash(array: Array) -> Double { - var total : Double = 0 + var total: Double = 0 var exponent = array.count - 1 for i in array { total += Double(i) * (Double(Constants.hashMultiplier) ** exponent) @@ -93,11 +98,17 @@ public func hash(array: Array) -> Double { } public func nextHash(prevHash: Double, dropped: Int, added: Int, patternSize: Int) -> Double { - let oldHash = prevHash - (Double(dropped) * (Double(Constants.hashMultiplier) ** patternSize)) + 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") \ No newline at end of file +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") From 263faef2847eb2249e650138984df56dcb5cb702 Mon Sep 17 00:00:00 2001 From: Sahn Cha Date: Fri, 21 Oct 2016 23:18:42 +0900 Subject: [PATCH 0015/1039] README ready. --- .../Images/img_pseudo.png | Bin 0 -> 149885 bytes Miller-Rabin Primality Test/README.markdown | 43 ++++++++++++++++++ .../contents.xcworkspacedata | 12 ++++- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 Miller-Rabin Primality Test/Images/img_pseudo.png create mode 100644 Miller-Rabin Primality Test/README.markdown diff --git a/Miller-Rabin Primality Test/Images/img_pseudo.png b/Miller-Rabin Primality Test/Images/img_pseudo.png new file mode 100644 index 0000000000000000000000000000000000000000..1a06d151aa90ae0d81fd6c413426357f907d2ae1 GIT binary patch literal 149885 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 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 +mrPrimalityTest(7) // test if 7 is prime. (default iteration = 1) +mrPrimalityTest(7, iteration: 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* + +[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 diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index dd0c6b668..75a941c3f 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -28,11 +28,21 @@ + + + + + + + location = "group:README.markdown"> Date: Fri, 21 Oct 2016 23:25:01 +0900 Subject: [PATCH 0016/1039] Update README.markdown --- Miller-Rabin Primality Test/README.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Miller-Rabin Primality Test/README.markdown b/Miller-Rabin Primality Test/README.markdown index 9fa849836..84020a9ec 100644 --- a/Miller-Rabin Primality Test/README.markdown +++ b/Miller-Rabin Primality Test/README.markdown @@ -4,9 +4,9 @@ In 1976, Gray Miller introduced an algorithm, through his ph.d thesis[1], which ## 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*. +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, than we can say with confidence that *the number is pro......bably prime*. +In order to increase the accuracy of the test, it needs to be iterated few times. If it returns `true` in every single iteration, than we can say with confidence that _the number is pro......bably prime_. ## Algorithm @@ -16,7 +16,7 @@ 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`. +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 @@ -32,11 +32,11 @@ mrPrimalityTest(7, iteration: 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. +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* +_Written for Swift Algorithm Club by **Sahn Cha**, @scha00_ [1]: https://cs.uwaterloo.ca/research/tr/1975/CS-75-27.pdf [2]: http://www.sciencedirect.com/science/article/pii/0022314X80900840 From a2fa24d380496152dc83eb81c8ec6a10b600878c Mon Sep 17 00:00:00 2001 From: Sahn Cha Date: Fri, 21 Oct 2016 23:34:08 +0900 Subject: [PATCH 0017/1039] typo. --- Miller-Rabin Primality Test/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Miller-Rabin Primality Test/README.markdown b/Miller-Rabin Primality Test/README.markdown index 84020a9ec..07acb9e18 100644 --- a/Miller-Rabin Primality Test/README.markdown +++ b/Miller-Rabin Primality Test/README.markdown @@ -6,11 +6,11 @@ In 1976, Gray Miller introduced an algorithm, through his ph.d thesis[1], which 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, than we can say with confidence that _the number is pro......bably prime_. +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`. +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: @@ -28,7 +28,7 @@ The following pseudo code is excerpted from Wikipedia[3]: ```swift mrPrimalityTest(7) // test if 7 is prime. (default iteration = 1) -mrPrimalityTest(7, iteration: 10) // test if 7 is prime & iterate 10 times. +mrPrimalityTest(7, iteration: 10) // test if 7 is prime && iterate 10 times. ``` ## Reference From 1de177535f8facdd188464df0c98e50cc5148504 Mon Sep 17 00:00:00 2001 From: Richard Date: Mon, 24 Oct 2016 18:33:25 -0700 Subject: [PATCH 0018/1039] Init & claim of Strassen's Matrix Multiplication Algorithm --- Strassen Matrix Multiplication/README.markdown | 1 + 1 file changed, 1 insertion(+) create mode 100644 Strassen Matrix Multiplication/README.markdown diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown new file mode 100644 index 000000000..d07004bad --- /dev/null +++ b/Strassen Matrix Multiplication/README.markdown @@ -0,0 +1 @@ +## TODO: Examples & Explanation From 95069fd26cd6c0f5c60f9c980411df72c61ce379 Mon Sep 17 00:00:00 2001 From: Richard Date: Wed, 26 Oct 2016 14:12:39 -0700 Subject: [PATCH 0019/1039] Implementation for Strassen Matrix Multiplication Algorithm --- .../Contents.swift | 316 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + 3 files changed, 327 insertions(+) create mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift create mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/contents.xcplayground create mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift new file mode 100644 index 000000000..d4b4d8330 --- /dev/null +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift @@ -0,0 +1,316 @@ +//: Playground - noun: a place where people can play +// Reference - http://mathworld.wolfram.com/StrassenFormulas.html + + +import UIKit + +enum RowOrColumn { + case row, column +} + +protocol Number: Multipliable, Addable { + static var zero: Self { get } +} + +protocol Addable { + static func +(lhs: Self, rhs: Self) -> Self + static func -(lhs: Self, rhs: Self) -> Self +} + +protocol Multipliable { + static func *(lhs: Self, rhs: Self) -> Self +} + +extension Int: Number { + static var zero: Int { + return 0 + } +} + +extension Double: Number { + static var zero: Double { + return 0.0 + } +} + +extension Float: Number { + static var zero: Float { + return 0.0 + } +} + + +extension Array where Element: Number { + 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 }) + } +} + +struct MatrixSize: Equatable { + let rows: Int + let columns: Int + + func forEach(_ body: (Int, Int) throws -> Void) rethrows { + for row in 0.. Bool { + return lhs.columns == rhs.columns && lhs.rows == rhs.rows +} + + +struct Matrix { + + // MARK: - Variables + + let rows: Int, columns: Int + var grid: [T] + + var isSquare: Bool { + return rows == columns + } + + var size: MatrixSize { + return MatrixSize(rows: rows, columns: columns) + } + + // MARK: - Init + + init(rows: Int, columns: Int, initialValue: T = T.zero) { + self.rows = rows + self.columns = columns + self.grid = Array(repeating: initialValue, count: rows * columns) + } + + init(size: Int, initialValue: T = T.zero) { + self.rows = size + self.columns = size + self.grid = Array(repeating: initialValue, count: rows * columns) + } + + // MARK: - Subscript + + 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 + } + } + + subscript(type: RowOrColumn, 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") + var columns: [T] = [] + for row in 0.. Bool { + return row >= 0 && row < rows && column >= 0 && column < columns + } + + private func strassenR(by B: Matrix) -> 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 + + var a11 = Matrix(size: nBy2) + var a12 = Matrix(size: nBy2) + var a21 = Matrix(size: nBy2) + var a22 = Matrix(size: nBy2) + var b11 = Matrix(size: nBy2) + var b12 = Matrix(size: nBy2) + var b21 = Matrix(size: nBy2) + var b22 = Matrix(size: nBy2) + + for i in 0.. Int { + return Int(pow(2, ceil(log2(Double(n))))) + } + + // MARK: - Functions + + func strassenMatrixMultiply(by B: Matrix) -> 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(of: n) + + var APrep = Matrix(size: m) + var BPrep = Matrix(size: m) + + A.size.forEach { (i, j) in + APrep[i,j] = A[i,j] + } + + B.size.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.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..(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..(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.. + + + \ No newline at end of file diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + From 7295526436fa7e8a6dfd16f76f78aaf3a6b72a85 Mon Sep 17 00:00:00 2001 From: Richard Date: Fri, 28 Oct 2016 12:44:05 -0700 Subject: [PATCH 0020/1039] Added File implementations --- Strassen Matrix Multiplication/Matrix.swift | 9 +++++++++ Strassen Matrix Multiplication/MatrixSize.swift | 9 +++++++++ Strassen Matrix Multiplication/Number.swift | 9 +++++++++ 3 files changed, 27 insertions(+) create mode 100644 Strassen Matrix Multiplication/Matrix.swift create mode 100644 Strassen Matrix Multiplication/MatrixSize.swift create mode 100644 Strassen Matrix Multiplication/Number.swift diff --git a/Strassen Matrix Multiplication/Matrix.swift b/Strassen Matrix Multiplication/Matrix.swift new file mode 100644 index 000000000..493e27e06 --- /dev/null +++ b/Strassen Matrix Multiplication/Matrix.swift @@ -0,0 +1,9 @@ +// +// Matrix.swift +// +// +// Created by Richard Ash on 10/28/16. +// +// + +import Foundation diff --git a/Strassen Matrix Multiplication/MatrixSize.swift b/Strassen Matrix Multiplication/MatrixSize.swift new file mode 100644 index 000000000..a01123f3c --- /dev/null +++ b/Strassen Matrix Multiplication/MatrixSize.swift @@ -0,0 +1,9 @@ +// +// MatrixSize.swift +// +// +// Created by Richard Ash on 10/28/16. +// +// + +import Foundation diff --git a/Strassen Matrix Multiplication/Number.swift b/Strassen Matrix Multiplication/Number.swift new file mode 100644 index 000000000..1bd6cf634 --- /dev/null +++ b/Strassen Matrix Multiplication/Number.swift @@ -0,0 +1,9 @@ +// +// Number.swift +// +// +// Created by Richard Ash on 10/28/16. +// +// + +import Foundation From f0c17d5aeedf8d78c5449fa326e91152dc3cc5dc Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Wed, 2 Nov 2016 12:12:45 +0000 Subject: [PATCH 0021/1039] Dining Philosophers Problem Algorithm --- .../project.pbxproj | 250 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcschemes/DiningPhilosophers.xcscheme | 71 +++++ .../xcschemes/xcschememanagement.plist | 12 + DiningPhilosophers/LICENSE | 201 ++++++++++++++ DiningPhilosophers/Package.swift | 5 + DiningPhilosophers/README.md | 13 + DiningPhilosophers/Sources/main.swift | 107 ++++++++ 8 files changed, 666 insertions(+) create mode 100755 DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj create mode 100755 DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100755 DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme create mode 100755 DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist create mode 100755 DiningPhilosophers/LICENSE create mode 100755 DiningPhilosophers/Package.swift create mode 100755 DiningPhilosophers/README.md create mode 100755 DiningPhilosophers/Sources/main.swift diff --git a/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj b/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj new file mode 100755 index 000000000..9743ff7d1 --- /dev/null +++ b/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.pbxproj @@ -0,0 +1,250 @@ +// !$*UTF8*$! +{ + archiveVersion = "1"; + objectVersion = "46"; + objects = { + OBJ_1 = { + isa = "PBXProject"; + attributes = { + LastUpgradeCheck = "9999"; + }; + buildConfigurationList = OBJ_2; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = "English"; + hasScannedForEncodings = "0"; + knownRegions = ( + "en", + ); + mainGroup = OBJ_5; + productRefGroup = OBJ_11; + projectDirPath = "."; + targets = ( + OBJ_13, + ); + }; + OBJ_10 = { + isa = "PBXGroup"; + children = ( + ); + path = "Tests"; + sourceTree = ""; + }; + OBJ_11 = { + isa = "PBXGroup"; + children = ( + OBJ_12, + ); + name = "Products"; + path = ""; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + OBJ_12 = { + isa = "PBXFileReference"; + path = "DiningPhilosophers"; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + OBJ_13 = { + isa = "PBXNativeTarget"; + buildConfigurationList = OBJ_14; + buildPhases = ( + OBJ_17, + OBJ_19, + ); + dependencies = ( + ); + name = "DiningPhilosophers"; + productName = "DiningPhilosophers"; + productReference = OBJ_12; + productType = "com.apple.product-type.tool"; + }; + OBJ_14 = { + isa = "XCConfigurationList"; + buildConfigurations = ( + OBJ_15, + OBJ_16, + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Debug"; + }; + OBJ_15 = { + 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 = "3.0"; + TARGET_NAME = "DiningPhilosophers"; + }; + name = "Debug"; + }; + OBJ_16 = { + 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 = "3.0"; + TARGET_NAME = "DiningPhilosophers"; + }; + name = "Release"; + }; + OBJ_17 = { + isa = "PBXSourcesBuildPhase"; + files = ( + OBJ_18, + ); + }; + OBJ_18 = { + isa = "PBXBuildFile"; + fileRef = OBJ_9; + }; + OBJ_19 = { + isa = "PBXFrameworksBuildPhase"; + files = ( + ); + }; + OBJ_2 = { + isa = "XCConfigurationList"; + buildConfigurations = ( + OBJ_3, + OBJ_4, + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Debug"; + }; + OBJ_3 = { + 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 = { + 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"; + }; + OBJ_5 = { + isa = "PBXGroup"; + children = ( + OBJ_6, + OBJ_7, + OBJ_10, + OBJ_11, + ); + path = ""; + sourceTree = ""; + }; + OBJ_6 = { + isa = "PBXFileReference"; + explicitFileType = "sourcecode.swift"; + path = "Package.swift"; + sourceTree = ""; + }; + OBJ_7 = { + isa = "PBXGroup"; + children = ( + OBJ_8, + ); + path = "Sources"; + sourceTree = ""; + }; + OBJ_8 = { + isa = "PBXGroup"; + children = ( + OBJ_9, + ); + name = "DiningPhilosophers"; + path = "Sources"; + sourceTree = "SOURCE_ROOT"; + }; + OBJ_9 = { + isa = "PBXFileReference"; + path = "main.swift"; + sourceTree = ""; + }; + }; + rootObject = OBJ_1; +} diff --git a/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 000000000..919434a62 --- /dev/null +++ b/DiningPhilosophers/DiningPhilosophers.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme b/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme new file mode 100755 index 000000000..3c17791b7 --- /dev/null +++ b/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/DiningPhilosophers.xcscheme @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist b/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist new file mode 100755 index 000000000..4cd3e1d66 --- /dev/null +++ b/DiningPhilosophers/DiningPhilosophers.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist @@ -0,0 +1,12 @@ + + + + SchemeUserState + + DiningPhilosophers.xcscheme + + + SuppressBuildableAutocreation + + + diff --git a/DiningPhilosophers/LICENSE b/DiningPhilosophers/LICENSE new file mode 100755 index 000000000..8dada3eda --- /dev/null +++ b/DiningPhilosophers/LICENSE @@ -0,0 +1,201 @@ + 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. diff --git a/DiningPhilosophers/Package.swift b/DiningPhilosophers/Package.swift new file mode 100755 index 000000000..c7e5efd4f --- /dev/null +++ b/DiningPhilosophers/Package.swift @@ -0,0 +1,5 @@ +import PackageDescription + +let package = Package( + name: "DiningPhilosophers" +) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md new file mode 100755 index 000000000..06302cf2a --- /dev/null +++ b/DiningPhilosophers/README.md @@ -0,0 +1,13 @@ +# SwiftDiningPhilosophers +Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using GCD and Semaphore in Swift) + +Written by Jacopo Mangiavacchi + + +# from https://en.wikipedia.org/wiki/Dining_philosophers_problem + +In computer science, the dining philosophers problem is an example problem often used in 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 use GCD Dispatch and Semaphone on Swift cross platform diff --git a/DiningPhilosophers/Sources/main.swift b/DiningPhilosophers/Sources/main.swift new file mode 100755 index 000000000..dfde40773 --- /dev/null +++ b/DiningPhilosophers/Sources/main.swift @@ -0,0 +1,107 @@ +// +// Swift Dining philosophers problem Algorithm +// https://en.wikipedia.org/wiki/Dining_philosophers_problem +// +// Created by Jacopo Mangiavacchi on 11/02/16. +// +// + + +import Foundation +import Dispatch + +let numberOfPhilosophers = 4 + +class 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() + } +} + + +class 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 Philosofer: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") + forkPair.pickUp() + print("Start Eating Philosopher: \(philosopherIndex)") + //sleep(1000) + print("Releasing lock for Philosofer: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") + forkPair.putDown() + } + } +} + + +// Layout of the table (P = philosopher, f = fork) for 4 Philosopher +// P0 +// f3 f0 +// P3 P1 +// f2 f1 +// P2 + +let globalSem = DispatchSemaphore(value: 0) + +for i in 0.. Date: Mon, 7 Nov 2016 16:57:54 -0500 Subject: [PATCH 0022/1039] Initial commit and claim --- Rootish Array Stack/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Rootish Array Stack/README.md diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md new file mode 100644 index 000000000..e69de29bb From d7267e911efa8ba6d7b3c26da6c8cef59d82b9c7 Mon Sep 17 00:00:00 2001 From: jsbean Date: Wed, 23 Nov 2016 23:32:37 -0500 Subject: [PATCH 0023/1039] Update code and README for Swift 3.0 --- .../Contents.swift} | 28 ++++++++------- .../contents.xcplayground | 4 +++ .../contents.xcworkspacedata | 7 ++++ Minimum Edit Distance/README.markdown | 35 +++++++++---------- 4 files changed, 43 insertions(+), 31 deletions(-) rename Minimum Edit Distance/{MinimumEditDistance.swift => MinimumEditDistance.playground/Contents.swift} (53%) mode change 100644 => 100755 create mode 100755 Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground create mode 100755 Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata mode change 100644 => 100755 Minimum Edit Distance/README.markdown diff --git a/Minimum Edit Distance/MinimumEditDistance.swift b/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift old mode 100644 new mode 100755 similarity index 53% rename from Minimum Edit Distance/MinimumEditDistance.swift rename to Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift index a128b2dab..d651ddf2e --- a/Minimum Edit Distance/MinimumEditDistance.swift +++ b/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift @@ -1,34 +1,36 @@ extension String { - + public func minimumEditDistance(other: String) -> Int { let m = self.characters.count let n = other.characters.count - var matrix = [[Int]](count: m+1, repeatedValue: [Int](count: n+1, repeatedValue: 0)) - - + 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 + matrix[index][0] = index } + for index in 1...n { // the distance of any second string to an empty first string - matrix[0][index]=index + matrix[0][index] = index } - + // compute Levenshtein distance - for (i, selfChar) in self.characters.enumerate() { - for (j, otherChar) in other.characters.enumerate() { + for (i, selfChar) in self.characters.enumerated() { + for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { // substitution of equal symbols with cost 0 - matrix[i+1][j+1] = matrix[i][j] + 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] = min(matrix[i][j]+1, matrix[i+1][j]+1, matrix[i][j+1]+1) + // minimum of the cost of insertion, deletion, or substitution + // added to the already computed costs in the corresponding cells + matrix[i + 1][j + 1] = min(matrix[i][j] + 1, matrix[i + 1][j] + 1, matrix[i][j + 1] + 1) } - } } return matrix[m][n] } } + +"Door".minimumEditDistance(other: "Dolls") diff --git a/Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground b/Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground new file mode 100755 index 000000000..5da2641c9 --- /dev/null +++ b/Minimum Edit Distance/MinimumEditDistance.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata b/Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100755 index 000000000..919434a62 --- /dev/null +++ b/Minimum Edit Distance/MinimumEditDistance.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Minimum Edit Distance/README.markdown b/Minimum Edit Distance/README.markdown old mode 100644 new mode 100755 index d72e0dbda..905b358ae --- a/Minimum Edit Distance/README.markdown +++ b/Minimum Edit Distance/README.markdown @@ -6,7 +6,7 @@ The minimum edit distance is a possibility to measure the similarity of two stri A common distance measure is given by the *Levenshtein distance*, which allows the following three transformation operations: -* **Inseration** (*ε→x*) of a single symbol *x* with **cost 1**, +* **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. @@ -15,7 +15,7 @@ When transforming a string by a sequence of operations, the costs of the single 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]](count: m+1, repeatedValue: [Int](count: n+1, repeatedValue: 0)) +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: @@ -23,29 +23,30 @@ already computed minimal edit distances of prefixes of *w* and *u* (of length *m ```swift // initialize matrix for index in 1...m { - // the distance of any prefix of the first string to an empty second string - matrix[index][0]=index + // the distance of any first string to an empty second string + matrix[index][0] = index } + for index in 1...n { - // the distance of any prefix of the second string to an empty first string - matrix[0][index]=index + // 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.characters.enumerate() { - for (j, otherChar) in other.characters.enumerate() { +for (i, selfChar) in self.characters.enumerated() { + for (j, otherChar) in other.characters.enumerated() { if otherChar == selfChar { // substitution of equal symbols with cost 0 - matrix[i+1][j+1] = matrix[i][j] + 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 corresponing cells - matrix[i+1][j+1] = min(matrix[i][j]+1, matrix[i+1][j]+1, matrix[i][j+1]+1) - } - + // minimum of the cost of insertion, deletion, or substitution + // added to the already computed costs in the corresponding cells + matrix[i + 1][j + 1] = min(matrix[i][j] + 1, matrix[i + 1][j] + 1, matrix[i][j + 1] + 1) + } } } ``` @@ -58,8 +59,6 @@ return matrix[m][n] This algorithm has a time complexity of Θ(*mn*). -### Other distance measures - -**todo** +**TODO**: Other distance measures. -*Written for Swift Algorithm Club by Luisa Herrmann* \ No newline at end of file +*Written for Swift Algorithm Club by Luisa Herrmann* From 38dc9eefedf61e5edc838fcb034657df2a22dcc6 Mon Sep 17 00:00:00 2001 From: Joe Date: Thu, 24 Nov 2016 15:36:22 +0800 Subject: [PATCH 0024/1039] update Array2D, Deque to swift3.0 update Array2D, Deque to swift3.0 --- Array2D/README.markdown | 6 +++--- Deque/Deque-Optimized.swift | 4 ++-- Deque/README.markdown | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Array2D/README.markdown b/Array2D/README.markdown index e73d453a6..51e77435e 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -30,14 +30,14 @@ let myCookie = cookies[3][6] Actually, you could create the array in a single line of code, like so: ```swift -var cookies = [[Int]](count: 9, repeatedValue: [Int](count: 7, repeatedValue: 0)) +var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9) ``` but that's just ugly. To be fair, you can hide the ugliness in a helper function: ```swift func dim(count: Int, _ value: T) -> [T] { - return [T](count: count, repeatedValue: value) + return [T](repeating: value, count: count) } ``` @@ -72,7 +72,7 @@ public struct Array2D { public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = .init(count: rows*columns, repeatedValue: initialValue) + array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index 17ff89e68..6326b457b 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -10,7 +10,7 @@ public struct Deque { public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) - array = .init(count: capacity, repeatedValue: nil) + array = [T?](repeating: nil, count: capacity) head = capacity } @@ -29,7 +29,7 @@ public struct Deque { public mutating func enqueueFront(_ element: T) { if head == 0 { capacity *= 2 - let emptySpace = [T?](count: capacity, repeatedValue: nil) + let emptySpace = [T?](repeating: nil, count: capacity) array.insertContentsOf(emptySpace, at: 0) head = capacity } diff --git a/Deque/README.markdown b/Deque/README.markdown index 7671555dc..5858f3e6d 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -122,7 +122,7 @@ public struct Deque { public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) - array = .init(count: capacity, repeatedValue: nil) + array = [T?](repeating: nil, count: capacity) head = capacity } @@ -238,8 +238,8 @@ There is one tiny problem... If you enqueue a lot of objects at the front, you'r public mutating func enqueueFront(element: T) { if head == 0 { capacity *= 2 - let emptySpace = [T?](count: capacity, repeatedValue: nil) - array.insertContentsOf(emptySpace, at: 0) + let emptySpace = [T?](repeating: nil, count: capacity) + array.insert(contentsOf: emptySpace, at: 0) head = capacity } From 653452a37c4a491e60ba66ff2d79f76b66c39014 Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 25 Nov 2016 21:33:24 -0500 Subject: [PATCH 0025/1039] Fix for #246: Invalid tree in MinimumMaximum.png and update README.markdown to match. --- Binary Search Tree/Images/MinimumMaximum.png | Bin 12151 -> 11913 bytes Binary Search Tree/README.markdown | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Binary Search Tree/Images/MinimumMaximum.png b/Binary Search Tree/Images/MinimumMaximum.png index 70fe4ea7b2cee1bd641a785981e0015815f3a594..10b4e635291d25cc899f659679dafdf8c8985b1a 100644 GIT binary patch literal 11913 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 delta 11725 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 diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index 483e75a58..bacb1ffe1 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -412,7 +412,7 @@ To see how this works, take the following tree: ![Example](Images/MinimumMaximum.png) -For example, if we look at node `10`, its leftmost descendent is `6`. We get there by following all the `left` pointers until there are no more left children to look at. The leftmost descendent of the root node `7` is `1`. Therefore, `1` is the minimum value in the entire tree. +For example, if we look at node `10`, its leftmost descendent is `7`. We get there by following all the `left` pointers until there are no more left children to look at. The leftmost descendent of the root node `6` is `1`. Therefore, `1` is the minimum value in the entire tree. We won't need it for deleting, but for completeness' sake, here is the opposite of `minimum()`: @@ -426,7 +426,7 @@ We won't need it for deleting, but for completeness' sake, here is the opposite } ``` -It returns the rightmost descendent of the node. We find it by following `right` pointers until we get to the end. In the above example, the rightmost descendent of node `2` is `5`. The maximum value in the entire tree is `11`, because that is the rightmost descendent of the root node `7`. +It returns the rightmost descendent of the node. We find it by following `right` pointers until we get to the end. In the above example, the rightmost descendent of node `2` is `5`. The maximum value in the entire tree is `11`, because that is the rightmost descendent of the root node `6`. Finally, we can write the code that removes a node from the tree: @@ -500,11 +500,11 @@ if let node2 = tree.search(2) { First you find the node that you want to remove with `search()` and then you call `remove()` on that object. Before the removal, the tree printed like this: - ((1) <- 2 -> (5)) <- 7 -> ((9) <- 10) + ((1) <- 2 -> (5)) <- 6 -> ((9) <- 10) But after `remove()` you get: - ((1) <- 5) <- 7 -> ((9) <- 10) + ((1) <- 5) <- 6 -> ((9) <- 10) As you can see, node `5` has taken the place of `2`. From 187f9236924896710b945d879c426370bfb130d7 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 7 Nov 2016 22:38:03 -0500 Subject: [PATCH 0026/1039] Added implementation --- Rootish Array Stack/README.md | 19 +++ Rootish Array Stack/RootishArrayStack.swift | 115 ++++++++++++++++++ .../images/RootishArrayStackExample.png | Bin 0 -> 152134 bytes .../images/RootishArrayStackIntro.png | Bin 0 -> 72856 bytes .../contents.xcworkspacedata | 10 ++ 5 files changed, 144 insertions(+) create mode 100644 Rootish Array Stack/RootishArrayStack.swift create mode 100644 Rootish Array Stack/images/RootishArrayStackExample.png create mode 100644 Rootish Array Stack/images/RootishArrayStackIntro.png diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index e69de29bb..842439a0c 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -0,0 +1,19 @@ +# 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 a swift array does 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). + +### How indices map: +| Subscript index | Indices of Blocks| +| :------------- | :------------- | +| `[0]` | `blocks[0][0]` | + +## A Mathematical Explanation diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift new file mode 100644 index 000000000..f17f9620e --- /dev/null +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -0,0 +1,115 @@ +// +// main.swift +// RootishArrayStack +// +// Created by Benjamin Emdon on 2016-11-07. +// + +import Darwin + +public struct RootishArrayStack { + fileprivate var blocks = [Array]() + fileprivate var internalCount = 0 + + public init() { } + + var count: Int { + return internalCount + } + + var capacity: Int { + return blocks.count * (blocks.count + 1) / 2 + } + + fileprivate static func toBlock(index: Int) -> Int { + let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) + return block + } + + fileprivate mutating func grow() { + let newArray = [T?](repeating: nil, count: blocks.count + 1) + blocks.append(newArray) + } + + fileprivate mutating func shrink() { + var numberOfBlocks = blocks.count + while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + blocks.remove(at: blocks.count - 1) + numberOfBlocks -= 1 + } + } + + public subscript(index: Int) -> T { + get { + let block = RootishArrayStack.toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + return blocks[block][blockIndex]! + } + set(newValue) { + let block = RootishArrayStack.toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + blocks[block][blockIndex] = newValue + } + } + + public mutating func insert(element: T, atIndex index: Int) { + if capacity < count + 1 { + grow() + } + 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 = RootishArrayStack.toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + blocks[block][blockIndex] = nil + } + + public mutating func remove(atIndex index: Int) -> T { + let element = self[index] + for i in index..= count { + shrink() + } + return element + } + + public var memoryDescription: String { + var s = "{\n" + for i in blocks { + s += "\t[" + for j in i { + s += "\(j), " + } + s += "]\n" + } + return s + "}" + } +} + +extension RootishArrayStack: CustomStringConvertible { + public var description: String { + var s = "[" + for index in 0..jgQMsoAU^;^e| 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�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 literal 0 HcmV?d00001 diff --git a/Rootish Array Stack/images/RootishArrayStackIntro.png b/Rootish Array Stack/images/RootishArrayStackIntro.png new file mode 100644 index 0000000000000000000000000000000000000000..74802e4ba978ff729ea594a711a1d61231fae880 GIT binary patch literal 72856 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 F{{XywOS}L8 literal 0 HcmV?d00001 diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 5f2c83aee..ac3a79be9 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1520,6 +1520,16 @@ + + + + + + From dbc751f344f64648c175d83444f8dc0bcb6033ca Mon Sep 17 00:00:00 2001 From: Marcio Klepacz Date: Mon, 28 Nov 2016 22:09:59 -0500 Subject: [PATCH 0027/1039] Fix link to Minimum Spanning Tree (Unweighted) --- Breadth-First Search/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 23edf6da5..084f4611a 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -149,6 +149,6 @@ This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]` Breadth-first search can be used to solve many problems. A small selection: * Computing the [shortest path](../Shortest Path/) between a source node and each of the other nodes (only for unweighted graphs). -* Calculating the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. +* Calculating the [minimum spanning tree](../Minimum Spanning Tree (Unweighted)/) on an unweighted graph. *Written by [Chris Pilcher](https://github.com/chris-pilcher) and Matthijs Hollemans* From 4072983c1fb4725fa21a52421897d82e3040c459 Mon Sep 17 00:00:00 2001 From: Dannel Albert Date: Wed, 7 Dec 2016 00:25:05 -0500 Subject: [PATCH 0028/1039] + methods to append, insert, remove node objects Useful for manipulating linked lists and you already have node objects --- Linked List/LinkedList.swift | 366 ++++++++++++++++++----------------- 1 file changed, 187 insertions(+), 179 deletions(-) diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 86d2bca9b..83f898f6c 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -1,198 +1,206 @@ public class LinkedListNode { - var value: T - var next: LinkedListNode? - weak var previous: LinkedListNode? - - public init(value: T) { - self.value = value - } + var value: T + var next: LinkedListNode? + weak var previous: LinkedListNode? + + public init(value: T) { + self.value = value + } } public class LinkedList { - 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 case let next? = node.next { - node = next - } - return node - } else { - return nil - } - } - - public var count: Int { - if var node = head { - var c = 1 - while case 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) - if let lastNode = last { - newNode.previous = lastNode - lastNode.next = newNode - } else { - head = newNode - } - } - - 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 (prev, next) = nodesBeforeAndAfter(index: index) - - let newNode = Node(value: value) - newNode.previous = prev - newNode.next = next - prev?.next = newNode - next?.previous = newNode - - if prev == nil { - head = newNode - } - } - - public func removeAll() { - head = nil - } - - 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 - } - - public func removeLast() -> T { - assert(!isEmpty) - return remove(node: last!) - } - - public func remove(atIndex index: Int) -> T { - let node = self.node(atIndex: index) - assert(node != nil) - return remove(node: node!) - } + 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 case let next? = node.next { + node = next + } + return node + } else { + return nil + } + } + + public var count: Int { + if var node = head { + var c = 1 + while case 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(_ newNode: Node) { + if let lastNode = last { + newNode.previous = lastNode + lastNode.next = newNode + } else { + head = newNode + } + } + + 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(_ newNode: Node, atIndex index: Int) { + let (prev, next) = nodesBeforeAndAfter(index: index) + + newNode.previous = prev + newNode.next = next + prev?.next = newNode + next?.previous = newNode + + if prev == nil { + head = newNode + } + } + + 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 + "]" - } + 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 - } - } + 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 - } + 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() + convenience init(array: Array) { + self.init() - for element in array { - self.append(element) + for element in array { + self.append(element) + } } - } } From cf5ca9cb198437b589f7c4ffcd47bcefe7e4b12a Mon Sep 17 00:00:00 2001 From: Andreas Date: Mon, 12 Dec 2016 10:13:35 +0100 Subject: [PATCH 0029/1039] Updated to Swift 3. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated to Swift 3 Syntax. The .swift file wasn’t converted yet. Additionally, I fixed a bug in there. --- .../BoyerMoore.playground/Contents.swift | 94 ++++++---- .../BoyerMoore.playground/timeline.xctimeline | 6 +- Boyer-Moore/BoyerMoore.swift | 118 ++++++------ Boyer-Moore/README.markdown | 169 +++++++++--------- 4 files changed, 209 insertions(+), 178 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 9a3d619dc..362a298f9 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -1,42 +1,66 @@ //: Playground - noun: a place where people can play extension String { - func indexOf(pattern: String) -> String.Index? { - let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - - var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerated() { - skipTable[c] = patternLength - i - 1 - } - - let p = pattern.index(before: pattern.endIndex) - let lastChar = pattern[p] - var i = self.index(startIndex, offsetBy: patternLength - 1) - - func backwards() -> String.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 - } - - while i < self.endIndex { - let c = self[i] - if c == lastChar { - if let k = backwards() { return k } - i = index(after: i) - } else { - i = index(i, offsetBy: skipTable[c] ?? patternLength) - } + func indexOf(pattern: String) -> 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.characters.count + assert(patternLength > 0) + assert(patternLength <= self.characters.count) + + // 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.characters.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 = self.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() -> String.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 < self.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 = self.index(i, offsetBy: skipTable[c] ?? patternLength) + } + } + return nil } - return nil - } } // A few simple tests diff --git a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline index a15b8d6e0..89bc76f90 100644 --- a/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline +++ b/Boyer-Moore/BoyerMoore.playground/timeline.xctimeline @@ -3,17 +3,17 @@ version = "3.0"> diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 12a1d86c1..4d7660ec3 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -6,64 +6,64 @@ http://www.drdobbs.com/database/faster-string-searches/184408171 */ extension String { - func indexOf(pattern: String) -> 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.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - - // 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.characters.enumerate() { - skipTable[c] = patternLength - i - 1 - } - - // This points at the last character in the pattern. - let p = pattern.endIndex.predecessor() - 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 = self.startIndex.advancedBy(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() -> String.Index? { - var q = p - var j = i - while q > pattern.startIndex { - j = j.predecessor() - q = q.predecessor() - if self[j] != pattern[q] { return nil } - } - return j - } - - // The main loop. Keep going until the end of the string is reached. - while i < self.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 = i.successor() - } 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 = i.advancedBy(skipTable[c] ?? patternLength) - } + func indexOf(pattern: String) -> 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.characters.count + assert(patternLength > 0) + assert(patternLength <= self.characters.count) + + // 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.characters.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 = self.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() -> String.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 < self.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 = self.index(i, offsetBy: skipTable[c] ?? patternLength) + } + } + return nil } - return nil - } } diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 4acc1ffb3..576f6d17b 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -1,13 +1,13 @@ # Boyer-Moore String Search -Goal: Write a string search algorithm in pure Swift without importing Foundation or using `NSString`'s `rangeOfString()` method. - +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: +// Input: let s = "Hello, World" s.indexOf(pattern: "World") @@ -24,7 +24,7 @@ animals.indexOf(pattern: "🐮") > **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 String Search/) 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 [brute-force approach](../Brute-Force String Search/) 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. @@ -32,75 +32,76 @@ Here's how you could write it in Swift: ```swift extension String { -func indexOf(pattern: String) -> 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.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - - // 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.characters.enumerated() { - skipTable[c] = patternLength - i - 1 - } - - // This points at the last character in the pattern. - let p = 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(self.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() -> String.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 < self.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) - } - } - return nil + func indexOf(pattern: String) -> 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.characters.count + assert(patternLength > 0) + assert(patternLength <= self.characters.count) + + // 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.characters.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 = self.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() -> String.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 < self.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 = self.index(i, offsetBy: skipTable[c] ?? patternLength) + } + } + 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: +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 - ^ +``` +source string: Hello, World +search pattern: World + ^ +``` There are three possibilities: @@ -112,25 +113,31 @@ There are three possibilities: 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 - ^ +``` +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 - ^ +``` +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 +``` +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. @@ -193,4 +200,4 @@ In practice, the Horspool version of the algorithm tends to perform a little bet 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* +_Written for Swift Algorithm Club by Matthijs Hollemans, updated by Andreas Neusüß_ From 24fa81839a45e24a6d5600c774fce3b730eb4de1 Mon Sep 17 00:00:00 2001 From: zaccone Date: Mon, 12 Dec 2016 15:42:21 -0500 Subject: [PATCH 0030/1039] I created an Xcode project with my changes. It makes it easier to test and the playground was crashing! --- Trie/ReadMe.md | 10 + Trie/Trie/Trie.xcodeproj/project.pbxproj | 531 + .../contents.xcworkspacedata | 7 + Trie/Trie/Trie/AppDelegate.swift | 26 + .../AppIcon.appiconset/Contents.json | 58 + Trie/Trie/Trie/Base.lproj/Main.storyboard | 693 + Trie/Trie/Trie/Info.plist | 32 + Trie/Trie/Trie/Trie.swift | 207 + Trie/Trie/Trie/ViewController.swift | 27 + Trie/Trie/Trie/dictionary.txt | 162825 +++++++++++++++ Trie/Trie/TrieTests/Info.plist | 22 + Trie/Trie/TrieTests/TrieTests.swift | 162 + Trie/Trie/TrieUITests/Info.plist | 22 + Trie/Trie/TrieUITests/TrieUITests.swift | 36 + 14 files changed, 164658 insertions(+) create mode 100644 Trie/Trie/Trie.xcodeproj/project.pbxproj create mode 100644 Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Trie/Trie/Trie/AppDelegate.swift create mode 100644 Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Trie/Trie/Trie/Base.lproj/Main.storyboard create mode 100644 Trie/Trie/Trie/Info.plist create mode 100644 Trie/Trie/Trie/Trie.swift create mode 100644 Trie/Trie/Trie/ViewController.swift create mode 100644 Trie/Trie/Trie/dictionary.txt create mode 100644 Trie/Trie/TrieTests/Info.plist create mode 100644 Trie/Trie/TrieTests/TrieTests.swift create mode 100644 Trie/Trie/TrieUITests/Info.plist create mode 100644 Trie/Trie/TrieUITests/TrieUITests.swift diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 30082a450..6b28dd189 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -162,3 +162,13 @@ Let n be the length of some value in the `Trie`. 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. diff --git a/Trie/Trie/Trie.xcodeproj/project.pbxproj b/Trie/Trie/Trie.xcodeproj/project.pbxproj new file mode 100644 index 000000000..70a0626da --- /dev/null +++ b/Trie/Trie/Trie.xcodeproj/project.pbxproj @@ -0,0 +1,531 @@ +// !$*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 = ""; }; +/* 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 */, + ); + sourceTree = ""; + }; + EB798DFB1DFEF79900F0628D /* Products */ = { + isa = PBXGroup; + children = ( + EB798DFA1DFEF79900F0628D /* Trie.app */, + EB798E0B1DFEF79900F0628D /* TrieTests.xctest */, + EB798E161DFEF79900F0628D /* TrieUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + EB798DFC1DFEF79900F0628D /* Trie */ = { + isa = PBXGroup; + children = ( + 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 = 0810; + ORGANIZATIONNAME = "Rick Zaccone"; + TargetAttributes = { + EB798DF91DFEF79900F0628D = { + CreatedOnToolsVersion = 8.1; + ProvisioningStyle = Automatic; + }; + EB798E0A1DFEF79900F0628D = { + CreatedOnToolsVersion = 8.1; + ProvisioningStyle = Automatic; + TestTargetID = EB798DF91DFEF79900F0628D; + }; + EB798E151DFEF79900F0628D = { + CreatedOnToolsVersion = 8.1; + 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_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.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_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.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 = 3.0; + }; + 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 = 3.0; + }; + 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 = 3.0; + 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 = 3.0; + 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 = 3.0; + 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 = 3.0; + 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; + }; + EB798E221DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB798E231DFEF79900F0628D /* Debug */, + EB798E241DFEF79900F0628D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + EB798E251DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB798E261DFEF79900F0628D /* Debug */, + EB798E271DFEF79900F0628D /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = EB798DF21DFEF79900F0628D /* Project object */; +} diff --git a/Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..cd768f89b --- /dev/null +++ b/Trie/Trie/Trie.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Trie/Trie/Trie/AppDelegate.swift b/Trie/Trie/Trie/AppDelegate.swift new file mode 100644 index 000000000..4da9dc345 --- /dev/null +++ b/Trie/Trie/Trie/AppDelegate.swift @@ -0,0 +1,26 @@ +// +// 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 + } + + +} + diff --git a/Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json b/Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..2db2b1c7c --- /dev/null +++ b/Trie/Trie/Trie/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "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" + } +} \ No newline at end of file diff --git a/Trie/Trie/Trie/Base.lproj/Main.storyboard b/Trie/Trie/Trie/Base.lproj/Main.storyboard new file mode 100644 index 000000000..64d3d90d8 --- /dev/null +++ b/Trie/Trie/Trie/Base.lproj/Main.storyboard @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Trie/Trie/Trie/Info.plist b/Trie/Trie/Trie/Info.plist new file mode 100644 index 000000000..ed3668788 --- /dev/null +++ b/Trie/Trie/Trie/Info.plist @@ -0,0 +1,32 @@ + + + + + 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 + + diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift new file mode 100644 index 000000000..bd1abc538 --- /dev/null +++ b/Trie/Trie/Trie/Trie.swift @@ -0,0 +1,207 @@ +// +// 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 { + get { + 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 { + 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 + + /// Creats an empty trie. + init() { + root = Node() + wordCount = 0 + } +} + +// 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 + let charactersInWord = Array(word.lowercased().characters) + var index = 0 + while index < charactersInWord.count { + let character = charactersInWord[index] + if let childNode = currentNode.children[character] { + currentNode = childNode + } else { + currentNode.add(value: character) + currentNode = currentNode.children[character]! + } + index += 1 + } + // Word already present? + guard !currentNode.isTerminating else { + return + } + self.wordCount += 1 + currentNode.isTerminating = true + } + + /// Determines whether a word is in the trie. + /// + /// - Parameter word: the word to check for + /// - Returns: true if the word is present, false otherwise. + func contains(word: String) -> Bool { + guard !word.isEmpty else { + return false + } + var currentNode = root + let charactersInWord = Array(word.lowercased().characters) + var index = 0 + while index < charactersInWord.count, let childNode = currentNode.children[charactersInWord[index]] { + index += 1 + currentNode = childNode + } + return index == charactersInWord.count && currentNode.isTerminating + } + + /// 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? { + var currentNode = root + var charactersInWord = Array(word.lowercased().characters) + var index = 0 + while index < charactersInWord.count { + let character = charactersInWord[index] + guard let childNode = currentNode.children[character] else { + return nil + } + currentNode = childNode + index += 1 + } + return currentNode.isTerminating ? currentNode : 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 + } + self.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 + 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 { + let childWords = wordsInSubtrie(rootNode: childNode, partialWord: previousLetters) + subtrieWords += childWords + } + return subtrieWords + } +} diff --git a/Trie/Trie/Trie/ViewController.swift b/Trie/Trie/Trie/ViewController.swift new file mode 100644 index 000000000..b2e9d9105 --- /dev/null +++ b/Trie/Trie/Trie/ViewController.swift @@ -0,0 +1,27 @@ +// +// 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. + } + } + + +} + diff --git a/Trie/Trie/Trie/dictionary.txt b/Trie/Trie/Trie/dictionary.txt new file mode 100644 index 000000000..4e5bcd075 --- /dev/null +++ b/Trie/Trie/Trie/dictionary.txt @@ -0,0 +1,162825 @@ +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 \ No newline at end of file diff --git a/Trie/Trie/TrieTests/Info.plist b/Trie/Trie/TrieTests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Trie/Trie/TrieTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift new file mode 100644 index 000000000..236908ece --- /dev/null +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -0,0 +1,162 @@ +// +// 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 wordArrayu 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 trie.count == 0 else { + return + } + let numberOfWordsToInsert = wordArray!.count + for i in 0.. + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Trie/Trie/TrieUITests/TrieUITests.swift b/Trie/Trie/TrieUITests/TrieUITests.swift new file mode 100644 index 000000000..f3da2a67f --- /dev/null +++ b/Trie/Trie/TrieUITests/TrieUITests.swift @@ -0,0 +1,36 @@ +// +// 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. + } + +} From 1e23b7f859ed83e21dd37941113102af0d8c4d28 Mon Sep 17 00:00:00 2001 From: Richard Date: Tue, 13 Dec 2016 14:30:07 -0800 Subject: [PATCH 0031/1039] Code updates --- Strassen Matrix Multiplication/Matrix.swift | 237 ++++++++++++++++++ .../MatrixSize.swift | 17 ++ Strassen Matrix Multiplication/Number.swift | 41 +++ 3 files changed, 295 insertions(+) diff --git a/Strassen Matrix Multiplication/Matrix.swift b/Strassen Matrix Multiplication/Matrix.swift index 493e27e06..657cf3c80 100644 --- a/Strassen Matrix Multiplication/Matrix.swift +++ b/Strassen Matrix Multiplication/Matrix.swift @@ -7,3 +7,240 @@ // import Foundation + +enum RowOrColumn { + case row, column +} + +struct Matrix { + + // MARK: - Variables + + let rows: Int, columns: Int + var grid: [T] + + var isSquare: Bool { + return rows == columns + } + + var size: MatrixSize { + return MatrixSize(rows: rows, columns: columns) + } + + // MARK: - Init + + init(rows: Int, columns: Int, initialValue: T = T.zero) { + self.rows = rows + self.columns = columns + self.grid = Array(repeating: initialValue, count: rows * columns) + } + + init(size: Int, initialValue: T = T.zero) { + self.rows = size + self.columns = size + self.grid = Array(repeating: initialValue, count: rows * columns) + } + + // MARK: - Subscript + + 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 + } + } + + subscript(type: RowOrColumn, 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") + var columns: [T] = [] + for row in 0.. Bool { + return row >= 0 && row < rows && column >= 0 && column < columns + } + + private func strassenR(by B: Matrix) -> 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 + + var a11 = Matrix(size: nBy2) + var a12 = Matrix(size: nBy2) + var a21 = Matrix(size: nBy2) + var a22 = Matrix(size: nBy2) + var b11 = Matrix(size: nBy2) + var b12 = Matrix(size: nBy2) + var b21 = Matrix(size: nBy2) + var b22 = Matrix(size: nBy2) + + for i in 0.. Int { + return Int(pow(2, ceil(log2(Double(n))))) + } + + // MARK: - Functions + + func strassenMatrixMultiply(by B: Matrix) -> 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(of: n) + + var APrep = Matrix(size: m) + var BPrep = Matrix(size: m) + + A.size.forEach { (i, j) in + APrep[i,j] = A[i,j] + } + + B.size.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.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..(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..(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.. Void) rethrows { + for row in 0.. Bool { + return lhs.columns == rhs.columns && lhs.rows == rhs.rows +} diff --git a/Strassen Matrix Multiplication/Number.swift b/Strassen Matrix Multiplication/Number.swift index 1bd6cf634..34c6d5308 100644 --- a/Strassen Matrix Multiplication/Number.swift +++ b/Strassen Matrix Multiplication/Number.swift @@ -7,3 +7,44 @@ // import Foundation + +protocol Number: Multipliable, Addable { + static var zero: Self { get } +} + +protocol Addable { + static func +(lhs: Self, rhs: Self) -> Self + static func -(lhs: Self, rhs: Self) -> Self +} + +protocol Multipliable { + static func *(lhs: Self, rhs: Self) -> Self +} + +extension Int: Number { + static var zero: Int { + return 0 + } +} + +extension Double: Number { + static var zero: Double { + return 0.0 + } +} + +extension Float: Number { + static var zero: Float { + return 0.0 + } +} + + +extension Array where Element: Number { + 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 }) + } +} From 31bc4c3159ea7574ee557ad46dbb65be33987395 Mon Sep 17 00:00:00 2001 From: Nagasawa Hiroki Date: Thu, 15 Dec 2016 08:52:41 +0900 Subject: [PATCH 0032/1039] Use lower camel case in enum case --- .../BinaryTree.playground/Contents.swift | 42 +++++++++---------- Binary Tree/BinaryTree.swift | 24 +++++------ 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Binary Tree/BinaryTree.playground/Contents.swift b/Binary Tree/BinaryTree.playground/Contents.swift index b35e90c27..b4d65ec1f 100644 --- a/Binary Tree/BinaryTree.playground/Contents.swift +++ b/Binary Tree/BinaryTree.playground/Contents.swift @@ -1,14 +1,14 @@ //: Playground - noun: a place where people can play public indirect enum BinaryTree { - case Node(BinaryTree, T, BinaryTree) - case Empty + case node(BinaryTree, T, BinaryTree) + case empty public var count: Int { switch self { - case let .Node(left, _, right): + case let .node(left, _, right): return left.count + 1 + right.count - case .Empty: + case .empty: return 0 } } @@ -17,9 +17,9 @@ public indirect enum BinaryTree { extension BinaryTree: CustomStringConvertible { public var description: String { switch self { - case let .Node(left, value, right): + case let .node(left, value, right): return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" - case .Empty: + case .empty: return "" } } @@ -28,24 +28,24 @@ extension BinaryTree: CustomStringConvertible { // 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) +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) +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) +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) +let tree = BinaryTree.node(timesLeft, "+", timesRight) print(tree) tree.count // 12 @@ -54,7 +54,7 @@ tree.count // 12 extension BinaryTree { public func traverseInOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traverseInOrder(process: process) process(value) right.traverseInOrder(process: process) @@ -62,7 +62,7 @@ extension BinaryTree { } public func traversePreOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process: process) right.traversePreOrder(process: process) @@ -70,7 +70,7 @@ extension BinaryTree { } public func traversePostOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traversePostOrder(process: process) right.traversePostOrder(process: process) process(value) diff --git a/Binary Tree/BinaryTree.swift b/Binary Tree/BinaryTree.swift index 0c55af20e..ad5fcfd13 100644 --- a/Binary Tree/BinaryTree.swift +++ b/Binary Tree/BinaryTree.swift @@ -4,14 +4,14 @@ Nodes don't have a reference to their parent. */ public indirect enum BinaryTree { - case Node(BinaryTree, T, BinaryTree) - case Empty + case node(BinaryTree, T, BinaryTree) + case empty public var count: Int { switch self { - case let .Node(left, _, right): + case let .node(left, _, right): return left.count + 1 + right.count - case .Empty: + case .empty: return 0 } } @@ -20,9 +20,9 @@ public indirect enum BinaryTree { extension BinaryTree: CustomStringConvertible { public var description: String { switch self { - case let .Node(left, value, right): + case let .node(left, value, right): return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" - case .Empty: + case .empty: return "" } } @@ -30,7 +30,7 @@ extension BinaryTree: CustomStringConvertible { extension BinaryTree { public func traverseInOrder(@noescape process: T -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traverseInOrder(process) process(value) right.traverseInOrder(process) @@ -38,7 +38,7 @@ extension BinaryTree { } public func traversePreOrder(@noescape process: T -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process) right.traversePreOrder(process) @@ -46,7 +46,7 @@ extension BinaryTree { } public func traversePostOrder(@noescape process: T -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traversePostOrder(process) right.traversePostOrder(process) process(value) @@ -56,10 +56,10 @@ extension BinaryTree { extension BinaryTree { func invert() -> BinaryTree { - if case let .Node(left, value, right) = self { - return .Node(right.invert(), value, left.invert()) + if case let .node(left, value, right) = self { + return .node(right.invert(), value, left.invert()) } else { - return .Empty + return .empty } } } From 95cd7732290fd1b9c100adebe2d52dc96ef12f17 Mon Sep 17 00:00:00 2001 From: Nagasawa Hiroki Date: Thu, 15 Dec 2016 08:57:32 +0900 Subject: [PATCH 0033/1039] Update README in Binary Tree --- Binary Tree/README.markdown | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 4b5fe7180..52089b8e7 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -20,8 +20,8 @@ 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 + case node(BinaryTree, T, BinaryTree) + case empty } ``` @@ -29,24 +29,24 @@ 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) +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) +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) +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) +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. @@ -57,10 +57,10 @@ It will be useful to add a `description` method so you can print the tree: extension BinaryTree: CustomStringConvertible { public var description: String { switch self { - case let .Node(left, value, right): + case let .node(left, value, right): return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" - case .Empty: + case .empty: return "" } } @@ -92,9 +92,9 @@ Another useful method is counting the number of nodes in the tree: ```swift public var count: Int { switch self { - case let .Node(left, _, right): + case let .node(left, _, right): return left.count + 1 + right.count - case .Empty: + case .empty: return 0 } } @@ -112,7 +112,7 @@ Here is how you'd implement that: ```swift public func traverseInOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traverseInOrder(process: process) process(value) right.traverseInOrder(process: process) @@ -120,7 +120,7 @@ Here is how you'd implement that: } public func traversePreOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { process(value) left.traversePreOrder(process: process) right.traversePreOrder(process: process) @@ -128,7 +128,7 @@ Here is how you'd implement that: } public func traversePostOrder(process: (T) -> Void) { - if case let .Node(left, value, right) = self { + if case let .node(left, value, right) = self { left.traversePostOrder(process: process) right.traversePostOrder(process: process) process(value) From 733487f53eadf59a7c702cb8f4db04297db64a0b Mon Sep 17 00:00:00 2001 From: zaccone Date: Wed, 14 Dec 2016 18:58:09 -0500 Subject: [PATCH 0034/1039] Made improvements suggested by others. These changes cause things to be done in a more Swift-like manner. Also updated the project to Xcode 8.2. --- Trie/Trie/Trie.xcodeproj/project.pbxproj | 7 +++++- Trie/Trie/Trie/Trie.swift | 29 ++++++++---------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Trie/Trie/Trie.xcodeproj/project.pbxproj b/Trie/Trie/Trie.xcodeproj/project.pbxproj index 70a0626da..8d3611b6d 100644 --- a/Trie/Trie/Trie.xcodeproj/project.pbxproj +++ b/Trie/Trie/Trie.xcodeproj/project.pbxproj @@ -193,7 +193,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0810; - LastUpgradeCheck = 0810; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Rick Zaccone"; TargetAttributes = { EB798DF91DFEF79900F0628D = { @@ -333,6 +333,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -382,6 +383,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -508,6 +510,7 @@ EB798E211DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; EB798E221DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieTests" */ = { isa = XCConfigurationList; @@ -516,6 +519,7 @@ EB798E241DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; EB798E251DFEF79900F0628D /* Build configuration list for PBXNativeTarget "TrieUITests" */ = { isa = XCConfigurationList; @@ -524,6 +528,7 @@ EB798E271DFEF79900F0628D /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index bd1abc538..ad4e9f2e7 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -81,23 +81,19 @@ extension Trie { return } var currentNode = root - let charactersInWord = Array(word.lowercased().characters) - var index = 0 - while index < charactersInWord.count { - let character = charactersInWord[index] + for character in word.lowercased().characters { if let childNode = currentNode.children[character] { currentNode = childNode } else { currentNode.add(value: character) currentNode = currentNode.children[character]! } - index += 1 } // Word already present? guard !currentNode.isTerminating else { return } - self.wordCount += 1 + wordCount += 1 currentNode.isTerminating = true } @@ -110,13 +106,13 @@ extension Trie { return false } var currentNode = root - let charactersInWord = Array(word.lowercased().characters) - var index = 0 - while index < charactersInWord.count, let childNode = currentNode.children[charactersInWord[index]] { - index += 1 + for character in word.lowercased().characters { + guard let childNode = currentNode.children[character] else { + return false + } currentNode = childNode } - return index == charactersInWord.count && currentNode.isTerminating + return currentNode.isTerminating } /// Attempts to walk to the terminating node of a word. The @@ -127,20 +123,15 @@ extension Trie { /// search failed. private func findTerminalNodeOf(word: String) -> Node? { var currentNode = root - var charactersInWord = Array(word.lowercased().characters) - var index = 0 - while index < charactersInWord.count { - let character = charactersInWord[index] + for character in word.lowercased().characters { guard let childNode = currentNode.children[character] else { return nil } currentNode = childNode - index += 1 } return currentNode.isTerminating ? currentNode : 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. @@ -180,7 +171,7 @@ extension Trie { } else { terminalNode.isTerminating = false } - self.wordCount -= 1 + wordCount -= 1 } /// Returns an array of words in a subtrie of the trie @@ -198,7 +189,7 @@ extension Trie { if rootNode.isTerminating { subtrieWords.append(previousLetters) } - for (_, childNode) in rootNode.children { + for childNode in rootNode.children.values { let childWords = wordsInSubtrie(rootNode: childNode, partialWord: previousLetters) subtrieWords += childWords } From f27c4aa6073bf35191d651d6d02459c7b38776cc Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Fri, 16 Dec 2016 03:47:34 -0800 Subject: [PATCH 0035/1039] Removes old implementation. Updated README to reflect the new code changes. --- Trie/Old Implementation/trie.swift | 523 ------------------ Trie/ReadMe.md | 86 ++- Trie/Trie.playground/Contents.swift | 16 - Trie/Trie.playground/Sources/Node.swift | 21 - Trie/Trie.playground/Sources/Trie.swift | 83 --- Trie/Trie.playground/contents.xcplayground | 4 - .../contents.xcworkspacedata | 7 - Trie/Trie/Trie/Trie.swift | 334 +++++------ 8 files changed, 201 insertions(+), 873 deletions(-) delete mode 100644 Trie/Old Implementation/trie.swift delete mode 100644 Trie/Trie.playground/Contents.swift delete mode 100644 Trie/Trie.playground/Sources/Node.swift delete mode 100644 Trie/Trie.playground/Sources/Trie.swift delete mode 100644 Trie/Trie.playground/contents.xcplayground delete mode 100644 Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Trie/Old Implementation/trie.swift b/Trie/Old Implementation/trie.swift deleted file mode 100644 index 8227d0243..000000000 --- a/Trie/Old Implementation/trie.swift +++ /dev/null @@ -1,523 +0,0 @@ -/// TODO: - Undergoing refactoring. - -/* - Queue implementation (taken from repository, needed for findPrefix()) -*/ -public struct Queue { - private var array = [T?]() - private 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 - } -} -/* - A Trie (Pre-fix Tree) - - Some of the functionality of the trie makes use of the Queue implementation for this project. - - - Every node in the Trie stores a bit of information pertainining to what it references: - -Character (letter of an inserted word) - -Parent (Letter that comes before the current letter in some word) - -Children (Words that have more letters than available in the prefix) - -isAWord (Does the current letter mark the end of a known inserted word?) - -visited (Mainly for the findPrefix() function) -*/ -public class Node { - private var character: String? - private var parent: Node? - private var children: [String:Node] - private var isAWord: Bool - private var visited: Bool //only for findPrefix - - init(c: String?, p: Node?) { - self.character = c - self.children = [String:Node]() - self.isAWord = false - self.parent = p - self.visited = false - } - - /* - Function Name: char() - Input: N/A - Output: String - Functionality: Returns the associated value of the node - */ - func char() -> String { - return self.character! - } - - /* - Function Name: update - Input: String - Output: N/A - Functionality: Updates the associated value of the node - */ - func update(c: String?) { - self.character = c - } - - /* - Function Name: isLeaf - Input: N/A - Output: Bool - Functionality: Returns true if the node is a leaf node, false otherwise - */ - func isLeaf() -> Bool { - return self.children.count == 0 - } - - /* - Function Name: getParent - Input: N/A - Output: Node - Functionality: Returns the parent node of the current node - */ - func getParent() -> Node { - return parent! - } - - /* - Function Name: setParent - Input: Node - Output: N/A - Functionality: Changes the parent of the current node to the passed node - */ - - func setParent(node: Node?) { - self.parent = node - } - - /* - Function Name: getChildAt - Input: String - Output: Node - Functionality: returns the child node that holds the specific passed letter - */ - func getChildAt(s: String) -> Node { - return self.children[s]! - } - - /* - Function Name: isValidWord - Input: N/A - Output: Bool - Functionality: Returns whether or not the current node marks the end of a valid word - */ - func isValidWord() -> Bool { - return self.isAWord - } - - /* - Function Name: isWord - Input: N/A - Output: N/A - Functionality: the current node is indeed a word - */ - func isWord() { - self.isAWord = true - } - - /* - Function Name: isNotWord - Input: N/A - Output: N/A - Functionality: marks the current node as not a word - */ - func isNotWord() { - self.isAWord = false - } - - /* - Function Name: isRoot - Input: N/A - Output: Bool - Functionality: Returns whether or not the current node is the root of the trie - */ - func isRoot() -> Bool { - return self.character == "" - } - - /* - Function Name: numChildren - Input: N/A - Output: Int - Functionality: Returns the number of immediate letters that follow the current node - */ - func numChildren() -> Int { - return self.children.count - } - - /* - Function Name: getChildren - Input: N/A - Output: [String: Node] - Functionality: Returns the letters that immediately follow the current node's value for possible word segments that follow - */ - func getChildren() -> [String: Node] { - return self.children - } - - - /* - Function Name: printNode - Input: String, Bool - Output: N/A - Functionality: prints to the console a string representation of the current node in the trie - */ - func printNode(var indent: String, leaf: Bool) { - - print(indent, terminator: "") - if leaf { - print("\\-", terminator: "") - indent += " " - } else { - print("|-", terminator: "") - indent += "| " - } - - print(self.char()) - - var i = 0 - for (_, node) in self.children { - node.printNode(indent, leaf: i == self.getChildren().count-1) - i+=1 - } - - } - -} - - -/* - The Trie class has the following attributes: - -root (the root of the trie) - -wordList (the words that currently exist in the trie) - -wordCount (the number of words in the trie) -*/ -public class Trie { - private var root: Node - private var wordList: [String] - private var wordCount = 0 - - init() { - self.root = Node(c: "", p: nil) - self.wordList = [] - } - - init(wordList: Set) { - - self.root = Node(c: "", p: nil) - self.wordList = [] - - for word in wordList { - self.insert(word) - } - } - - /* - Function Name: merge - Input: Trie - Output: Trie - Functionality: Merges two tries into one and returns the merged trie - */ - func merge(other: Trie) -> Trie { - let newWordList = Set(self.getWords() + other.getWords()) - return Trie(wordList: newWordList) - } - - /* - Function Name: find - Input: String - Output: (Node?, Bool) - Functionality: Looks for a specific key and returns a tuple that - has a reference to the node(if found) and true/false - depending on if it was found - */ - func find(key: String) -> (node: Node?, found: Bool) { - var currentNode = self.root - - for c in key.characters { - if currentNode.children[String(c)] == nil { - return(nil, false) - } - currentNode = currentNode.children[String(c)]! - } - - return(currentNode, currentNode.isValidWord()) - } - - /* - Function Name: isEmpty - Input: N/A - Output: Bool - Functionality: returns true if the trie is empty, false otherwise - */ - func isEmpty() -> Bool { - return wordCount == 0 - } - - /* - Function Name: count - Input: N/A - Output: Int - Functionality: returns the number of words in the trie - */ - func count() -> Int { - return wordCount - } - - /* - Function Name: getWords - Input: N/A - Output: [String] - Functionality: returns the list of words that exist in the trie - */ - func getWords() -> [String] { - return wordList - } - - /* - Function Name: contains - Input: String - Output: Bool - Functionality: returns true if the tries has the word passed, false otherwise - */ - func contains(w: String) -> Bool { - return find(w.lowercaseString).found - } - - /* - Function Name: isPrefix - Input: String - Output: (Node?, Bool) - Functionality: returns a tuple containing a reference to the final - node in the prefix (if it exists) and true/false - depending on whether or not the prefix exists in the trie - */ - func isPrefix(p: String) -> (node: Node?, found: Bool) { - let prefixP = p.lowercaseString - - var currentNode = self.root - - for c in prefixP.characters { - if currentNode.children[String(c)] == nil { - return (nil, false) - } - - currentNode = currentNode.children[String(c)]! - } - - if currentNode.numChildren() > 0 { - return (currentNode, true) - } - - return (nil, false) - } - - /* - Function Name: insert - Input: String - Output: (String, Bool) - Functionality: Inserts a word int othe trie. Returns a tuple containing - the word attempted to be added, and true/false depending on - whether or not the insertion was successful - */ - func insert(w: String) -> (word: String, inserted: Bool) { - - let word = w.lowercaseString - var currentNode = self.root - var length = word.characters.count - - if self.contains(word) { - return (w, false) - } - - var index = 0 - var c = Array(word.characters)[index] - - while let child = currentNode.children[String(c)] { - currentNode = child - length -= 1 - index += 1 - - if length == 0 { - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) - } - - c = Array(word.characters)[index] - } - - let remainingChars = String(word.characters.suffix(length)) - for c in remainingChars.characters { - currentNode.children[String(c)] = Node(c: String(c), p: currentNode) - currentNode = currentNode.children[String(c)]! - } - - currentNode.isWord() - wordList.append(w) - wordCount += 1 - return (w, true) - } - - /* - Function Name: insertWords - Input: [String] - Output: ([String], Bool) - Functionality: attempts to insert all words from input array. returns a tuple - containing the input array and true if some of the words were - succesffuly added, false if none were added - */ - - func insertWords(wordList: [String]) -> (wordList: [String], inserted: Bool) { - - var succesful: Bool = false - for word in wordList { - succesful = self.insert(word).inserted || succesful - } - - return(wordList, succesful) - } - - /* - Function Name: remove - Input: String - Output: (String, Bool) - Functionality: Removes the specified key from the trie if it exists, returns - tuple containing the word attempted to be removed and true/false - if the removal was succesful - */ - func remove(w: String) -> (word: String, removed: Bool) { - let word = w.lowercaseString - - if !self.contains(w) { - return (w, false) - } - var currentNode = self.root - - for c in word.characters { - currentNode = currentNode.getChildAt(String(c)) - } - - if currentNode.numChildren() > 0 { - currentNode.isNotWord() - } else { - var character = currentNode.char() - while currentNode.numChildren() == 0 && !currentNode.isRoot() { - currentNode = currentNode.getParent() - currentNode.children[character]!.setParent(nil) - currentNode.children[character]!.update(nil) - currentNode.children[character] = nil - character = currentNode.char() - } - } - - wordCount -= 1 - - var index = 0 - for item in wordList { - if item == w { - wordList.removeAtIndex(index) - } - index += 1 - } - - return (w, true) - } - - /* - Function Name: findPrefix - Input: String - Output: [String] - Functionality: returns a list containing all words in the trie that have the specified prefix - */ - func findPrefix(p: String) -> [String] { - - if !self.isPrefix(p).found { - return [] - } - - var q: Queue = Queue() - var n: Node = self.isPrefix(p).node! - - var wordsWithPrefix: [String] = [] - var word = p - var tmp = "" - q.enqueue(n) - - while let current = q.dequeue() { - for (char, child) in current.getChildren() { - if !child.visited { - q.enqueue(child) - child.visited = true - if child.isValidWord() { - var currentNode = child - while currentNode !== n { - tmp += currentNode.char() - currentNode = currentNode.getParent() - } - tmp = String(tmp.characters.reverse()) - wordsWithPrefix.append(word + tmp) - tmp = "" - } - } - } - } - - - return wordsWithPrefix - } - - - /* - Function Name: removeAll - Input: N/A - Output: N/A - Functionality: removes all nodes in the trie using remove as a subroutine - */ - func removeAll() { - for word in wordList { - self.remove(word) - } - } - - - /* - Function Name: printTrie - Input: N/A - Output: N/A - Functionality: prints all the nodes of the trie to console in a nice and easy to understand format - */ - func printTrie() { - self.root.printNode("", leaf: true) - } - -} diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 6b28dd189..172ff4750 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -64,42 +64,38 @@ Insertion into a `Trie` requires you to walk over the nodes until you either hal ```swift func insert(word: String) { - guard !word.isEmpty else { return } + guard !word.isEmpty else { + return + } // 1 var currentNode = root - - // 2 - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - // 3 - while currentIndex < characters.count { - let character = characters[currentIndex] - // 4 - if let child = currentNode.children[character] { - currentNode = child + // 2 + for character in word.lowercased().characters { + // 3 + if let childNode = currentNode.children[character] { + currentNode = childNode } else { - currentNode.add(child: character) + currentNode.add(value: character) currentNode = currentNode.children[character]! } - - currentIndex += 1 - - // 5 - if currentIndex == characters.count { - currentNode.isTerminating = true - } } + // 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. Keep track of the word you want to insert. -3. Begin walking through your word letter by letter -4. 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. -5. Once you get to the end, you mark `isTerminating` to true to mark that specific node as the end of a word. +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 @@ -109,41 +105,27 @@ If you'd like to remove "Apple", you'll need to take care to leave the "App" cha ```swift func remove(word: String) { - guard !word.isEmpty else { return } + guard !word.isEmpty else { + return + } - // 1 - var currentNode = root - - // 2 - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - // 3 - while currentIndex < characters.count { - let character = characters[currentIndex] - guard let child = currentNode.children[character] else { return } - currentNode = child - currentIndex += 1 + // 1 + guard let terminalNode = findTerminalNodeOf(word: word) else { + return } - - // 4 - if currentNode.children.count > 0 { - currentNode.isTerminating = false + + // 2 + if terminalNode.isLeaf { + deleteNodesForWordEndingWith(terminalNode: terminalNode) } else { - var character = currentNode.value - while currentNode.children.count == 0, let parent = currentNode.parent, !parent.isTerminating { - currentNode = parent - currentNode.children[character!] = nil - character = currentNode.value - } + terminalNode.isTerminating = false } + wordCount -= 1 } ``` -1. Once again, you create a reference to the root node. -2. Keep track of the word you want to remove. -3. Attempt to walk to the terminating node of the word. The `guard` statement will return if it can't find one of the letters; It's possible to call `remove` on a non-existant entry. -4. If you reach the node representing the last letter of the word you want to remove, you'll have 2 cases to deal with. Either it's a leaf node, or it has more children. If it has more children, it means the node is used for other words. In that case, you'll just mark `isTerminating` to false. In the other case, you'll delete the nodes. +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 diff --git a/Trie/Trie.playground/Contents.swift b/Trie/Trie.playground/Contents.swift deleted file mode 100644 index 89a160c8d..000000000 --- a/Trie/Trie.playground/Contents.swift +++ /dev/null @@ -1,16 +0,0 @@ -let trie = Trie() - -trie.insert(word: "apple") -trie.insert(word: "ap") -trie.insert(word: "a") - -trie.contains(word: "apple") -trie.contains(word: "ap") -trie.contains(word: "a") - -trie.remove(word: "apple") -trie.contains(word: "a") -trie.contains(word: "apple") - -trie.insert(word: "apple") -trie.contains(word: "apple") diff --git a/Trie/Trie.playground/Sources/Node.swift b/Trie/Trie.playground/Sources/Node.swift deleted file mode 100644 index 56faed3e5..000000000 --- a/Trie/Trie.playground/Sources/Node.swift +++ /dev/null @@ -1,21 +0,0 @@ -public final class TrieNode { - public var value: T? - public weak var parent: TrieNode? - public var children: [T: TrieNode] = [:] - public var isTerminating = false - - init() {} - - init(value: T, parent: TrieNode? = nil) { - self.value = value - self.parent = parent - } -} - -// MARK: - Insertion -public extension TrieNode { - func add(child: T) { - guard children[child] == nil else { return } - children[child] = TrieNode(value: child, parent: self) - } -} diff --git a/Trie/Trie.playground/Sources/Trie.swift b/Trie/Trie.playground/Sources/Trie.swift deleted file mode 100644 index ddce0ba84..000000000 --- a/Trie/Trie.playground/Sources/Trie.swift +++ /dev/null @@ -1,83 +0,0 @@ -/// The Trie class has the following attributes: -/// -root (the root of the trie) -/// -wordList (the words that currently exist in the trie) -/// -wordCount (the number of words in the trie) -public final class Trie { - typealias Node = TrieNode - fileprivate let root: Node - - public init() { - root = TrieNode() - } -} - -// MARK: - Basic Methods -public extension Trie { - func insert(word: String) { - guard !word.isEmpty else { return } - var currentNode = root - - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - while currentIndex < characters.count { - let character = characters[currentIndex] - if let child = currentNode.children[character] { - currentNode = child - } else { - currentNode.add(child: character) - currentNode = currentNode.children[character]! - } - - currentIndex += 1 - if currentIndex == characters.count { - currentNode.isTerminating = true - } - } - } - - func contains(word: String) -> Bool { - guard !word.isEmpty else { return false } - var currentNode = root - - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - while currentIndex < characters.count, let child = currentNode.children[characters[currentIndex]] { - currentNode = child - currentIndex += 1 - } - - if currentIndex == characters.count && currentNode.isTerminating { - return true - } else { - return false - } - } - - func remove(word: String) { - guard !word.isEmpty else { return } - var currentNode = root - - var characters = Array(word.lowercased().characters) - var currentIndex = 0 - - while currentIndex < characters.count { - let character = characters[currentIndex] - guard let child = currentNode.children[character] else { return } - currentNode = child - currentIndex += 1 - } - - if currentNode.children.count > 0 { - currentNode.isTerminating = false - } else { - var character = currentNode.value - while currentNode.children.count == 0, let parent = currentNode.parent, !parent.isTerminating { - currentNode = parent - currentNode.children[character!] = nil - character = currentNode.value - } - } - } -} diff --git a/Trie/Trie.playground/contents.xcplayground b/Trie/Trie.playground/contents.xcplayground deleted file mode 100644 index 5da2641c9..000000000 --- a/Trie/Trie.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata b/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/Trie/Trie.playground/playground.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index ad4e9f2e7..d9b3bbed9 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -11,188 +11,188 @@ 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 { - get { - return children.count == 0 - } + var value: T? + weak var parentNode: TrieNode? + var children: [T: TrieNode] = [:] + var isTerminating = false + var isLeaf: Bool { + get { + 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) + } + + /// 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 { - 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 - - /// Creats an empty trie. - init() { - root = Node() - wordCount = 0 - } + 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 + + /// Creats an empty trie. + init() { + root = Node() + wordCount = 0 + } } // 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().characters { - 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 + + /// 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 } - - /// Determines whether a word is in the trie. - /// - /// - Parameter word: the word to check for - /// - Returns: true if the word is present, false otherwise. - func contains(word: String) -> Bool { - guard !word.isEmpty else { - return false - } - var currentNode = root - for character in word.lowercased().characters { - guard let childNode = currentNode.children[character] else { - return false - } - currentNode = childNode - } - return currentNode.isTerminating + var currentNode = root + for character in word.lowercased().characters { + if let childNode = currentNode.children[character] { + currentNode = childNode + } else { + currentNode.add(value: character) + currentNode = currentNode.children[character]! + } } - - /// 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? { - var currentNode = root - for character in word.lowercased().characters { - guard let childNode = currentNode.children[character] else { - return nil - } - currentNode = childNode - } - return currentNode.isTerminating ? currentNode : nil + // Word already present? + guard !currentNode.isTerminating else { + return } - - /// 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 - } - } + wordCount += 1 + currentNode.isTerminating = true + } + + /// Determines whether a word is in the trie. + /// + /// - Parameter word: the word to check for + /// - Returns: true if the word is present, false otherwise. + func contains(word: String) -> Bool { + guard !word.isEmpty else { + return false } - - /// 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 + var currentNode = root + for character in word.lowercased().characters { + guard let childNode = currentNode.children[character] else { + return false + } + currentNode = childNode } - - /// 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 - 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 + return currentNode.isTerminating + } + + /// 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? { + var currentNode = root + for character in word.lowercased().characters { + guard let childNode = currentNode.children[character] else { + return nil + } + currentNode = childNode + } + return currentNode.isTerminating ? currentNode : 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 + 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 + } } From e7bc36cf645d11539cac9e2c9ffe098457488ad6 Mon Sep 17 00:00:00 2001 From: Anton Date: Sat, 17 Dec 2016 19:41:31 +0100 Subject: [PATCH 0036/1039] Fix Skip-List link in readme --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 4c812b0f3..7ac170a65 100644 --- a/README.markdown +++ b/README.markdown @@ -142,7 +142,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Lists - [Linked List](Linked List/). A sequence of data items connected through links. Covers both singly and doubly linked lists. -- Skip List +- [Skip-List](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. ### Trees From a277fed473caf69108eae0aa3276d7a78f01fa90 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sat, 17 Dec 2016 21:35:42 +0100 Subject: [PATCH 0037/1039] Add AVL tree rotation example image; Update image; Update image; --- AVL Tree/Images/Rotation.jpg | Bin 0 -> 35153 bytes AVL Tree/README.markdown | 5 +++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 AVL Tree/Images/Rotation.jpg diff --git a/AVL Tree/Images/Rotation.jpg b/AVL Tree/Images/Rotation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94a55df4e3268d5e9f8ed5b63a443beb9d6dda6e GIT binary patch literal 35153 zcmd?RcRZZkyDmODL3E;v8quOhkBAmwkmzM1I$G7=QeAskLU5s=YF2G?seVQeXY5kzg`2-KGxFJ0uT@Y z06O>|z%>H!L^HtE2>{U72iye!0OSCIXjcF+zK1^rz=m%C08s$}fC&Ga;IF?G5dP~? zqKE>bf9(^<{&nK@0pPx&3)lzj?E-$qBQ1UpaQ~sMKJi~y!`t6|fxo-7)0_zl$$)y| zoi`L8_Aw7bue$(rkw!i-k|3*MaL`*_TMow{q z5`RJyEr5`Kh=`Dwh=k;?k0A)b9|sWAk*^{PdZLshPQjrM-irle3Gfo41dz zpMOAL(A#&BQPDB6acSxAGcvP2e9SH?E-C$7R$lR?zM-+H8TzfIwWqhQe_-(Y(D3Bc z^vvws`~n<-T;JH-+Wxh(i#|U2eR_6|`E&7?U-$)lUq>WKbFJ4dFVCI)W2%!IR?QhTi zImaUYKY8|Vj{Psc76BUgf%TUW;$K9Bg!o5Agg0Wm3wR?TCHdP(|EH1tZRCF$#lP7# z{vv;0fsl|G|DqrzA^o>w|8(bi89yu)uHgVGA_DwiBBBGR0dTlGMR9=tzqjk3|Bv`N z@&AaQlmCzSIrU%riNFa!v{7L_+yuKY22~y#mCX2}#ip5!iC)=}64&V}xgGvVu5Np+ z7Xg6mbyaTM1c)?L(4`r^9p&2>D}J;wxelE!%6ZZ*KLHqj`SNHT+F}t=56zq)z1#if zuDX1u3YKpQr;O!9({vwL9_vwpY2mUZP}+ncwmRaBUg7au#P|5hdFFcH<5&iUZuxV$ zI@c9}mZV|!y@e7MzoD=I4=}j8i7<6#sckgNOYdc!09ry~;Y_QmQD;5K>+|}N%9E0< zym*bnBYKEGMiRlSiRO-z88N=7V&h`ll6q>?GM?_vV+?5lk=?*3n^l=@$wgiRh~cQM z@G8CPUZiX`a@Az2iCTH6bdff7=OVHnW3_Zo9!k&tkx$;hXy(-ev3A%_>(z>|NdimH zp`s@csZm}O*Z1?k6ZHP<^{F+fbzK8)VC~+nslvWkFJjUV)pSoU6|bsh^{$Y!!m=b# zImr=)#CKjpifyz2V;!P`l`!$F3T>i8cdPFYq%?STt6I2LPM6Kb!w5PF zUBd{r(8_F_NALq>%`evgH{N#g^u7Zyqm*bv#aOpfe1N}UuNTK@ZK24GSfRsxcjkj~ zBTXg}5=Ns3|5ST*4WRGj!>A!>-kgGB^J&HNMl>fp;Je2zi0sWtnO#$MpEOsR=XJ%B z$^d^P)BC$G230Wo)*!-^Kf@Kzs4hfr5ct4WN{(Umt%^XrWgq^EnmuL0{CC&e+s@Uu#-Qu*B5<4tUgl>}lPFx2A09 z5##QL{Ea(BZ~mF4>}+#Yq)Li$9%NCYYFcI7nO)&+gv!6(slIn<81rb#la8v5TbQ-y zjd?jg71dk~``&HZ55wW)WCCwEKGDo2S3|_m_Gh%H=>ApqfW5(1Tnhx+dAH8WLzO8o zbm+5nO^#f)MCfRPs6Ru@cDnt2<2NZK+#dqx`e-mh%sK1AO?&ZRdaa#`-RfXR`!B9N zmj(@und~sd>BT^F;J0>IOJ~%>-4{8->=rLre;Izh_;6xy$z2TBj#XAeQh<4W9zAal zQAAXGX0kGkN`I-8F(wgmk8~6O-sf$u+yX7Y&cIV@&QFmsGCA|7Ue`mvt+R zsSDlid^SrW`HgLjf;OA95&Jg}%XYpDxC#|kSv41GGCoWAzfJz@>Hj?93RCop*$2d1 z)}vO!gOOr7$WdJUXeX#Cw)6^HR!IOz{iLWlWy^sw=tAfz((xTS*+%|$kyiev~Tb?-ld@T^VTV^IRbV}MB-YZt+29<-_si%Gyu;1X) zK{gfZ{;)2OOE)reo;CwDm_pZF49YH50(wnRR~tMZeqUK0Zd*-kt3X<+j~vqiQhtw> zpqO?ESfBm^k#tJxp#?dCy|yA#2I0t~n~yUu2GS-2iv&}cqqgAI68X-r3mO?bj9-1< zO&jEQ9l(9Z@iw5NdwP+HB1p}nes+!4>>_uWRv1qa$7$t_Ydg~1#{KcbZ^L;5Ca^4tq@=q z(C`Ha5S?r`txQvF&3Tr`^7Bx2Bp@Zf?W(Ne;gf;2{Ef z8-EpBPf2L&EdpuX>6SflCy&7t>C>_P6^GOzhM^|+YrA0c&Szz_YA)muPT%z-xVEXP zRWq+7Qn-9Oc5Dp4}lf6!Cc>uvw-OULjaN9G@zdueJ?F1RsMQ}(Qs z;90-wlAYGGbnhZ}(;Z*uV1{ll;xDZHahi934F}vE*5NrN?RZ^2wc~+01d6uac zpG>?9PmX%mfJY?IDNkDwc|YX_*|Ic?SpGWxPuX2RFGAz)6cGNCjaZ23_!`g$jO$cE zbN5k%l0gWQruR%!2j!sEwuRXvno)MG{E~cyEu9}#1FFx9ie6ZJ5Ka`l;On!T$%^_- zxk~4z&3qBko+XvK!29sv;s%O)fu;9c5!|Iu)2|5MwnY1YP-$+H-0kPBwVN`(E?se4;4So_oI@fNfrQx~Z* zC70f1R!-~)9D$*XXyEL9`J^~8EDy>OtJ{LHL)0>Lw#s@KPxj1SIJvW%J2oYnZq4rB zky0S8g1jB#Fq;L{tHo4d?NDDa#g8$m!Dy}F<71GJX=g)ooev#?jU;Y%cEYcc@byF{ zfBuIA`#?jt8{mphZbCv_gN`Vxbw(Jy-85Df*&*|bOB}UP0j_ct6UydwC2;ZdDDC-k z=6{z`U2aB*Dyc&BwN~CbNC^8<2TP5HA)x(?bYCVwi zLFJhb?r}DpMm~38G|~k8SB+^DGd`fojtN2NYYgD-wOWZuJPtqfbcUp)4oDdQLLl@XM0Bf1N|*M;UYFy?}XtqhNu?`NJ204W~Df zJ|HrP9p(=qrWX0Rv?74}L5tEpR<>0COz(u^GWiRr4|4i(ZcA>qmcBPPnSWGDZgAfh z^>Fb@NHf{u?`fyvZ<@5Nw&EH(`y{%B-jnQ`?Cv#y^)v+73nPPA)Vegtb{r%nhItWJ zo)>3|`1^R}NmUUr{h=<|&F8=ogbu1v!93U{Vpjywnk$8_2&H`5U)k7ZXr|>m#l3}Y zpXN)C;%vB&d%hHD(nG02Rtxjl-{sz7+^O$(%Nu?RD_fxX&iv;ZulSIk%Y@<}3}39Z z9l=P7^(2u4@hv9`V#^Pa#=_NGuj@+T+U(l5O+K0{d<<=?0S$!G{8Z%$(0+!JhQU z;QPz(Xz6@!bGE!IO-4h4|4Spgp7}p5mN{+kH=LUCLF+Ot1tdjrcK}st48KhC?x0o* z5xE*_&eI;HO`1g-)85ODm#&*qgwM)A8v9EBF4w4Av0&3f zFQE5s!MBYQ5C`t(3NPvqiXK4-bz3x%^Gu7MRD=bfiexUF# zWTNYOg|p;f`s#55?)@t=Vg| z38PxXg$6)=XLyUg2ok^i;E|T0HX9?`GQF`9PN5j&VD$+Wn2mzQTmTCxj3kOl;p4Z-RJt4lB=Ycq5Gxy-vtZD0=f z*3J%wN5kFETia5s_&kJO#=lIZU_@jbR}m442tAv`@rTZgaYZ9-xK6rPsX5=Sz;^+f zm3!aIc;PxsALi#3SU)=OZuwqKX;V33f4~O92xRkV0@Buzwfn37V8l4x5}jaS*=Uta zh`ZYw<-9#{uh$zUiRU2M2ZWk=vUJZ9F4E#qweMh@KHRZvk*g7>ISN?$b!uUvT}A3Y zM&9%cjX8Goor;h%xw7}@b>*m?D zsEpQ6U&L*ux!wPPH(`KdxE=HSJv?|f#{y4f@raV}(T>PJp7N&>#3({joI>T3m?V5;X z@OoAcFrvYYR=wP2?`c5dTG}HEt~u?d92dECD(F62up|$jWY}x+YN%o~e5)9wl;`^IbbUIit?G`D3r$DRB&8v1$#Z zqM=etO98cAZhqa!l$@jAefzDWMtA7Dijxn>pFQ{XW&=z$CR{4U6@T6h@@y(oul#jR zw+y$@YS54o=TFjEA~n-CHpvM8&Xc13xZ}U38zA|YhHjbp)Q1r6%ZIyZC2XL#vRXDT zEI4@kOLx6wKb_Fevp@fMupJsUGqB;XW>$tZ!OS3%BR`L82RP3{G%G#XY@^G{GcQil z+2bni);;{l<{Ty zi#1*R>>pF^a{Qsw%oHa$!ren{CMPR1eF=DYXsT!9HV`bI$tzEOXzwy|n3A$TLhjQjHS>LZH8fuxP;I^&9Ffd>S?D(tep+EROhi#EA?v=nQS$ zZ4AF-U2$ojWmY=GV^2;kdJ8MJ)DeyA|+CtG53 zam9}4q$`{1Cw?0dy^NXEvZvzw?QQe@B%|fwOdm9i~*yEPV?y{dTQg~ zuTap$RL%7_qG#{=X2?FeZeyZzoj!a5pjL6P8@4l+Afox zKi%+vCZYWOo|f_9Kn|`z?nE(`{!n%_=Srbn!Rq1)uw*GD?d-mTnS0=wXx_5|j^ce^ zkFrm6n$g~cMG0p`DgQ{UabM5=M+_!%OoR;EPrQ5_5RDw~r%A|Tgz0Iuw5R-%6Xt7# zf0A;QGc96|%HChlc4g|(zx(K{2dF@FbYoS1Z>e7Nu|rCv32~YMfT*Q5jR$jr=3D3f zuv&i>>ljib(rDjrxiP8n+2GlM)6~J5={K0B!qt|?!76ua?tsp0h8bBvs-l}!zBJ~f z7lblQmIg%(TmuYqwCiWbN~6#CFP;T89ljq5_GQ`tLtsvclY#qHTe`2tsHQ&| zT?%3N&fcN2VwJtVg#Kjl&w^$zWy@|zoW%%CF&mXEYCtk+KMTGQ+keVp!6+h}n9ko) z(;P+UW#q|V{4JniDp*ra?VCHeE1&DIR@siMCqKcG z52Mtd<;u74@I-7jzoP0vV|AJBmjOYSY0m(GB=$(_mY4zgnGsreQ|jG}+`|xd>+u9- zXM|ex3Trz$Kk<}3MC9?*`iZA_O$l8;+cv9{r^0=JFaH}U1CcSDDApS_*K-*!LDlV{ z3PV=gneSMVequWEJfmgPXs>!@HK23i>EsZ5p9IQeicsc6DfQ)vqgAr{!{EkStLAer z9WJ%9iY+rexHTbmwj{o$t?h=dz(R(-`MmcTzj}H<{dgRDH*|VUc5Paj5{1;jm7Qk> zok6*;WcXgTI_6vhe3;rZLeb5vW*2Qec?_t*aEO94f`)YG?7}poY~XftV^iXbD1J^R zx(5LNb(ri=f;daS6M&=^sidAJK#)X?(U6eI^p;)fWaoovJk7ejW?C#Ce+_UVFV5Hb z2)DWhkN|nR9YqwDPF#(lLw2tXbYrdoMNbB|%x$vWE(uc-ev)Nk?_h@3!VaKv89_9 zz|Y0TUkP$Sn`t6Snz^e^?e9{uG9z2=jhyR>F=z_%-{Pj}RCY@VC|X6Z40fnWP+@vr zt=b1HHD^`D4A|;RAy9hZC%UfU;=HW))9wj8r}0p-)GiUC!i`z?iVw+m}} zWg2AS3xDXuiq4`#L_d#(xCFMDSh^r?DaFL|Rs@R{_$F>)_Fm2S}EQo*IRC{v3ac)h`F*e(|__l>gk9| zJnXZ5_Q0lkJC5}%%2!)cTs7@KP#rYyuK_Ptqd>H(5?DG_VvH+?@vfQTY^-R!7vCU3 zBXs)UbK6OKML}xOF}*&zB<@(;#>~o4C1tDLN<1 znB!bMA>!#4yIwpTUndVYbHxeQg@)Scp*m|$J^6(YlJ!+GED)8OpVUrLu352T8Icu% z6kR)bQBze##2>R(lG<8X98pymPUvQ`Wp$JBPf%_MqmczOD_JQ7RfeNahP!^io~_XT ztlJkqwP?Udb-Srii2RbPCBWPmw8p1KwMfx-@@KdXKVG}3eRv=nj_ zwN=I3N>{6>m%)L?8^yLT$Kei#gKI!Z1^0tHjNdq2xZXES21EeJ9$Vfipy9{VqO7{Z zSoS?wKnx3R*;b8k+uG+it>UuLUQ#{RE&+c4aq3r>Qc&769|2&BOBfr(8Rc)*h$1`C zdamPHV&x&-e>SwS13i|!k+Q0tCbKul52zYgak>UPl<$p^fViTLZ=d|K z$_@c(tFJyu(^?L6E5=!Gf)&V^kMC1}ZO$4lO&~nYsL(`YE%^#8&KWI}Od9{$^@bn} zmUsJOk&aFAaUu-c-qal{cJX8)8*rh)8~4XxA?)S&t@Ls|wa9i#&$V0oD=T}pZGdaQ zxa;IPF#MK}L!zMd@06skOPGeUT8uNy2%QvPg1H80CvRl}sjFK3D%l8z^i_}DV?6!B z)9a7rRp+f~KX%Cs6(d*vFbD(e3ZmSC6zOOcx#e|At4KYIqz2A-QIYT$! zzDQHjujmy_cXYe`&9!FiyWrKBo*Kx$rqMAX%>Ow$m4_is^mYlas)~u1* z7qK2UGaBX~u*>Jcb84R}HyfkmuQoUJ&VVTG0}6x$ej+}*DiA-C0L!+>xPJ#7(CU2_ zE!J(0`XhS#i9Wz;{`bh31AbhZl&t^yE`0VIFs4&&B9uMA3B<6+ ztNV3`x~Y)}a&9J-`*pD^zn?$xO>x0S8Y8`;N|?<=yJXQaCb>^ua$$b{(bN)9ghXdu zJ=0030ALmgQTpi{7K0N?UI!UPwHykatqEfha<$QW+BYF!8aiHTkQk}5=$)?t#wG1N8ZIk z{*a%h*^Gva1?C?Z^nxa_oT&GJ!2vGeDUZ*B-2?011i zgGmG9bS5(un3q|P+S4W|!V`?b^)y|)B5#}6MX_=UyA;qQpK`zLRKPHmkKwt6g@`-b zlY)Mk*MRP)-@jTs{^73-e^z~LZk?X?LhV<&6GeCh%Tm$J|O)pZnoCvSJ@vVsyRGFEH}4E zUgz-0 zfAx_6X4yB{;U$O}8n{1Fsa_m95i}i?^%g9zZHL^;NP^?z|FFgG5Piw*EkJy5d8SMT zno=vR(dju&{TQSPnVe`VgkFuQRlS89``KN-D`(6e^0bfT!BB~-IL$cg{4f}7h6{P| zoc0<}n<NXHg!vCK7lz|HEQJ<&_=+ zd;bG6|2~6)l6&i-d8s7@PP3y2dAIiK!eS5z1Huk~QCr+9Cq;n~E9QD)s)&AW$!3GdQ z-}Bb{yLWcZFwY(a{YbG7zIyv4?ao$W;YSTVLROvcJg3A#Y=EdAhj84i(w;E0i<2Sx zdjhMCxub=-1FiaZz6g;G8o0!n$^^^>%)X;~f7*9%OiG`tZ(-1#A_cw_)!EqL&=Dz^ z=vlpF`3DFVd{&uBVxeB%uDzy4hZ{LFy9Us9QpiXJC{74;%s_;ErMf-9H-yvN6L|w~ z3_1-H_%)@(YpeMz);YUi#hlS*XGN21=)pK}6Nn(-?jQOPC9QhD`q^5ZSFA$QHCgAg zq0bep^qi8O-8%WaG+HT_(8Pv-PT83}~d+71nW9+QM*nzM}s+ z8($Ud11&f*^eL`X2d>jZOWw2kBQc&^>Eb0h2v6)Oci+1+baf5LrXCgk_$2L1eSDta zYwPNCHc5jWZifk@UKukwQPe%3SF9EW>SQVE9JHFc=Gp&y0z3B~6WBk}XVFP}NdH8L z#HIA3ajq=nqqZ4kt%(+`5N?Bel?$6X&m}y?Z^u2MYbB66wX+#NU_q;dInyk_2Dn*% zt4N8=pqwK8EAZU!rLr;Q9kxgBq$&g59!4SzCVrX;myd9zUOMk2hCaY8p?sI*9P;X2 z&rw5)$*;4Fpx;1l>1S{hO?>BF+;?tqh%;@Q3Ys63*pPrhN17x{SPe{&}&Dm(;f1L|XGwQpGb zCB3*3lHIdv(AFNv-;%e?Fq$=NzAhU00&o>zeJb00Tf1z{SrgiVKHq=JtBr6`5;rfV~{4HhYq%r&Ms9BG=1-*4=mzm#V=^$#&;QXkTrHnuDPPgboR2 zT;y1A50yYuALJ>@aKq_)>Lo6vK4cs1a&VoV+IX}77Qhxw zN!viQ<21g`VnZb5swf#}@y_`z`?!}_H7vVCiofQ&Mx^YS2?SrM*5^ALKqa33>9d4I z`c_gpsi;notmMC*pgAjvQA#$V_+3C_gNDZAxUtk2P({FMKYe#0#=fW3d)Zo%N5|vk z0pHR?t+xawEH~m*7;k2vRgw=X(Y^Y06QTTA9gJ|L3pdT_NToT0vCYGklV|mDIL)}( zt!sd8Bvne^7=NgXZfP1oH}!$(APfgrBbFV9Yn+*($Gf?ytOs4cxL-J=TIk6^Y8wYk z%}uSnHydLrg)WIv?#J6_4VdK1N03*TXIW|_SOzq>Cyco<=hlmK{jYiJ`V(S#tR{!0 z!7&@mmdV5XR$i1kC)97<5)KY}jg2j@0lgfjUt~gmKrAp;h~$J$;&zl!oXNYV2WgZa zk{09j%5{Q++g!;c$H8|jc)f<}lM6T1oVjCEZ)4(7HM5rkMUqIdyIV(Ev&0%N@wtJ1 z?tybE3&z+l`A1?ff1Jo7LTs}J_l@jFEyt+mxp6aTT4W7gK%{IxOj0^RqjC*km*%fu)R_?2TOZmsh!zB(1BdMhBkS5ck! z$Y}CN>^a}tEq$V*u=PGevbVTlI0sJbr{LA+b`S+VsftHZxdzf^ZMk#a+Wfspe#u)R zD)>R1Xi1On6ZYE)cPywe>ws&u$+qlL7E6eVj`n?9gz+5glQ#=Gto1GPWP!>v?@{S_ z*ar?@Lw|7bPPSWJs$qosvISK~0t;P_wOBCTo^Q(Po@VgXF`>DWUto4n z$!9n;%^(dWL}Cu&i&zfpwls*R{*mZis<~-vv1+T&`=mAUv^a7>igvh4p&GSgvs#zo zG-;|@arNOE;8LNg>e6}pD_Zcad?dtTZOl@irjJc|O6+@cyH3$J?I;9c)!9k6%u@}) z8PVz}ljoY==ZeWP9XRXLRN}x}D!(68LBbrI9Wh z+EOABcpy}JRopd=1*39$W}W4sToQUSgU=#*fgRa_YRd!j$?XOH6;(y0hZ*{vHoz~x zRPGd@#~duS!CY8bbT+Uvj#rP;S&y zT8GKT%V1a5Aeq#G!o|E$r=ioW_PzCUtifQUD*NC`SdT^x{Hid-LsU9MRr}oPyZQL# z>F;|x))TXpAsMjo-zuZphbYE1=%-KlMd$XIlSoD*8=qeu7x@V#?F)IG>SR_g=-M zWG9^UoL_?m`)~N)2kR|%}ULfxg)$HsJ@z2zSqEyyf zK@|lwYM8-GAf^~!kzu}#AwY?A*9V*r*aK}qhHqB-KhN*@(SQHhEw;H-DNN(Vdq3(H zGLX|~KGJ09Fw8kDnQeT)Nxa8Q|2|9z$MJy&2nW z!9aY^!PnGSWMe#5(K!L;oDXjs47(+PRX}pn1qdOb(Z9!3@v*1pr*2?{3q0yQUT?eD zos&w1vL;IkFlnzyIV5`Bgx7fyV0{#0E+y@pT{03CdBuVym@?SdvEuT(%F}U-6^arDlzsNU@#5wDj5Tix(C6A0012 zc=a>&ODyL)2=3gaD4xHz%4+M{`g%{5W7ZiKBDZbk5chr6a@ibCN0t6PrLj&|aL{+D zEwHv&&7&58mz~t^hoj{YWp6}(6xX<~uuWHqikVDG%l4ferVemvJ+m2oFmjKmg|Jfq z%^e-)8U`=JpNj`$oFIf>844fETWt#qKml21Xp+Os{j&?Iv-5nXuh6NQBQ9NWXXv97 z0ZD$ZL*+WcwmVuJo#)=!RVBGaq3{0%8@QkZ#v_^r|HcN1zyHPtxqo4UZry@(suHe1 z)8Pi9*h@8t)~u=!gl|gO2>GEHI$PwPsAd+YO0S}AfM3eH-W)TGM-IRJZY*s(l{u*F z1e3%Otn8|>zihW!QzIKiVQeo4xOm!UeaX#hE}dYRGGCj06=;0;qz!hxIiv{s(g^c> z-P$Y13lAJyf@|d#8%^s&vi|(mtE^Z3&_H$;gMJn?-RmDNBa(aOj#cc(Qul56xGOnx zx03O?YJWVZqrB3*#q)edMf%B9W1=Fp$m4LaYL8;`!YF|osYTRZz7zvUhyXV;!r-41 z#ZCMx9i0Lrss(PiXVOiIKywaP4zL+%x{&G$&1(Qf)wI7C8a-MeRbZ;qFo zed=|0*%HB$Xmo@3>4P1RNa$E;I}lkL3u1NvrCXw9;J!IrXF-gvpK)4;>}A%kG~TXs zeyJY6_m7f5%-mT$Y9Jk5kDq^_`jrNE&L8>6kqTci>sC^SNgsR02J&%I`8=eRRhX=f zgRV_V^bPl4YU}|p#5JI6HS!`W5o;vM#vP?BQl>J~TSOc+`(sk2kKg4UlhLd4;)w@4 zwwnJ0n5j_n;ErJ1KDd1;f~Vk_DGdgh z)IWuSnK}f5ngmwdZrFbsU|{X9s&IU`32qKmCV}zpFk-9~D!;#4aNt(S)JvgnQ$Bjm zQ6|9^wnzn%%;Mu%=B0;|%DvCw#Y$lTxBmrgRHGTwbocEado(B0UVRGX!9*h^dfKdx z*kT4_8Y^=;*v;vv>vFE-{G0L~fe^ZIHAUI|v^%xFwdt_`3Z;O|=Y+rgPeB0zULcrU z0A#^UtCFA+uK{C@1+Lj;u~g0(!PD-+lv+F}$hX59^B}oN1wgVGUdoZ{esLZNd!8Q) zKaZ?A-1nvQ;Pa85e{yzycfh6lxHK^}HHM#*N;0pgLuB1!Ka4t53?sCjS@6hGnRl<( zvTy%YCdzHx^9(A*@P()y`J^317!WKq7S5>aZ+px#`0AZjjImHC(L?Z%m^nrf^~ z%}9;;9yDSe=`1g*_7k6<{U}8(LhG_X%tl4^q)q|59T~(o(Qdm@v zRm`Z=7_pLl!jlPU?JcPW5~mwl>-h#(CCb6UYoJJZ6bAgVlW(rB*hOx;3ZDB*vP&}M zv1Yn*U&wd+)bShcPxLhfv!x5k7^f7E-m1#9;DuGuJ*%{}srLESlcKeonwMYBY55b# zzB=)kmCo_4(U7}d185)=MHn(&r(m0#J&VA|oFm5O*cZkj-)-G%YP?_l8;A2Rd=AkT zH#~F!qW>AAfiRh+PL6Nab9M|ZE6Mar9jnl%yt$*e@P}S_ZIJKAg+Gys2!2I{zXi@5 zU@6NWx~S7eXjUibj7R$eu|k{UF%MD$*T?R;x$gf(UkpUGsiW)!E%8x9ZmQdQkl zC+46H;BEI_i|#t2hLBD8c2M@r$(tGO!OzN&tl7T`9lp(YvTeCcy(l=InSVznN@gmQ zebgSfo==6Z853# z$fbbtnHo7Tye#!I7wt?Fkmli`zhu)C*fC<9|5&HV{QdSf+23OULi-a4AYFhNg6Vyp zH1txirFv;)FFUbiquaaEMlT4(u++Ux9`OCo{rk1SRn!mvLA^`!f7*42l7KTHwo36- z6qN<0w}+(}4vJIe_P(kuv0b5W9^v<@2ZDV@qL`tEGAX0lcW&trxXd=F;qg&40(!uT zX!FqMt-0{5_b6^@n~;F{hIppEF$RgQjd<`V6}H6tNDEUX1QNw!nkPelUIXZI&O9eS z{k_M64uY;3Rn!XY~3d zKXSyyba5i?F~eg-uT))fft)TxGa;9A{j1EXYU=B&EJK$PxN*z=_D-p3yAN)PpQJ?b z)pf7;dLQSb2(32g%OhrV9sP9$DQHK0pN0{_gW-Sd?>9xE-{mg;DLZqKIX6sRdo@Bh$FWZ&d5bLjc_sUOlDM{7hg+qo^Qpv^Uf6(kQ z;iV^d;S-F$UBcCC?eg32RmK3nV-+inj`xyrBHuNHlb(OD2YWLNf$wvCD0u<9XROj1 z2S5Seg>hl!(Tc7RfvSf%4)o{jH@kTpojxp?qxYq>-!^Z}Bum<8vNnt}R3PkT&L5Xyle>kXq+rYONGqTcB<=M-CMy92yih6nE1 zYV95?j40(<#M%#4cHTspy~S~1f>wJ%i6*OMY{aMOs7n)s!Nh?I_@GI`s+^~woW1kw ze-Y1r2d%YEA*?oPya!0=2BK}ZJ``>I)yo(O8Ty<$uT4ceppfQT>KMn*(Nb!#liq7Txm5W=h=1BI|+wNBs@6#n(Jjr7bz5(AMX5n*7O>8Afz! zL9Q2(N!9i@OF!##jy3gA@Ma6%OiGZdsw#;heocN~_GG(DEy|W}qFNS+NAb+XiCFh_ zJ`Q+^+saE*(+N`MY-{R?!ba`qqX7CJC;H)A&zqC*-p*be}*o@Ys70`s2b#S-WHpN;RqPm>26&UgugpNFd(+J^bqT9f0ac!S52z zJ1TdGwtEKqRvW)2(Eh~esju#m4AiPBoSRquPzt|&T3ay4!}jN7?H+Cc%nZ@C8;tQ? z%ok|O@lY1eXIay4Q(TYWR@wU{`F+gW&No@!KkOJwjOz{Wl zNZ^XP_fGnnBX$FFWsVC&Qor;su0e-6qzy&Z{ejLt@uJdQd;G?HRF!;%cZaok z-bRRIqyJ)Y2_bh;)14BS#7ZldiQOcKs$U?DXu=Kl4HpFD%L|pH09yH zAHTEzG%5}nrb@jEjckuBTScqvr!upaiF5@w+4i^H|r6rkMOcO^e z9y1-)y&~4DD_X$Anwm4MN{T;g;e;*pdUu6peg54Z!T^>73e<@)IxI>QYlom*^pNQ1 zqG`d+O-g_%tQ^zsF9<@EzUdyEV=J*C zmz8@y?+MfXIFnkr5-d}XS`~iOaj^f+tB$UJ7dQOF=6fS82a8XozNR@O2rvTHwh>r#;&@Hrx$< z`+#G$AC?$YmVAoe%IRFY(1}_O$U6$@tgNxD&2>b4lZ z{E8Blg-{FcB!?(YhB9I08<^ST5(yW(Y5#m!KhovPv(;sn;Dd_x)osjaBY@-qpss8Z zXe5N;GyKTiAo)aTm8S3ln^97}m4_LZw1f zCU6Ypq7ZK+wX|ji85$nA`f{4~BC4+Go9UTgv-0}4t88V4Fx1H!%R7j0H4WyY#%Fc$ zg29NnIm+#281^PommOXE`rmy^0h&AM8bFEPGHT1x_ze}Z6a|9a9=Y82T{S6Z54sm+37KXot1vmN1 zWq;GWZD(4;>nA(8ps4&ezbo}w^qPn@T8& ztL%c~W4E5C_A@@VS)NZ}GEwKx127UGVU3`~s&>gW3T4Tg8DONCeSZR6JfmnS@#pH2 z^}u4<+H>UW9gPv6c_lmTF0m%y`v8_M?#A(bG(ttK$Ch>4qf^LbmU*I&cc#ok%{1~o z^$7Ls5TYesflm7sUz$u$$7qRDYjXI7Ts2z0p8+@3DHoyVH(fne79}dqSh;f{T@U;8 zD^RamGehVDhm4o#y%aY28#(e&5F*~UivKm*GwkQ9O{JL09g6)^$l^%1X_#c z9ga$IpE>c1+gyXTU5RVmR||<#%7hrPndD{Sh~w|-bdPHJAm#4c64Bg*p(>%{ogD8V zQgbgMkHlB>maWuhAR~HAoh^RZo4?~f*k|nXNGUA1p~ji-X=nB?UmU${p2EIHk7H%F zI@raNsf;Z!QgD;I#sjuOGx++cUiowK*HW2rAK+6@noj!xkgia1+)oKWQ#3+scR4@H zr*+^%^P7v0#%4KSNc`)0Jm#}yK&t^Ubp-)!z1$pOt{)p0S4mxxIB(uQ9d)*O>w1i6jzt;A}h33X+gGYC>N$VZ_Jk`&bK zdRXIe5q_gue@D)}kxmK-GwkP)1EwDxIAwx~uGXSn9#VBsbdWfqmewcZWj7C!7Ux1f zaD1Qk><+2RRTaYHh8zA(aW7*njNtQa;sX5$0`wIqYVbw#>j<)*uF9#h8?0xlp29bPeA^ z9v*C@9T`tM0f6OhEYzJ_hcCT4Ehv<);^DdfCAD%x>BV}S3pqd zBGP+_^d=zE0t6x;y$J{i2$9};u*QeibG+$*C)&vI3$#A&0HSrxnZjg&$I;5aRKRx`_`|(ZCQ_)(^+`KYgOMN z*e#R%1YBd6=aMT4rWoHj2#=l!9?eu)$Fnm{>{)lku)t!0$sY_h9u#lUcnu&EZ{j)q`Ujr4w zyAJcT9FP={YKu1&o5%y<6^JZE*|pzaDUs%CW^#}{wOUB zLqXCnD^(qJAr|CO>U>gLF>_*6SMhU%g}i)_lcu7;`|bzVt`6#}*}n+t`3A>mw9u4c zR?-s}DrM$fvwG&Hnw#o1URLZglvd&SNt{z#?rPKvheUM4@NV@v{THvfl~?(eU4Uf#d< zxO~%6A72H$UZ@-h!R}8Q;imTridaI>t$gjs2o-dGGO$~#L4_U93gOHt6U+dzE(_0} zTTSe1}+kCH}{Cgb21)s-fgM}FBC5ZR{~gCOX% z=ZI_x&d1RjPP9>@ql#i*)cx@_Td1h2utA2?-5@FxGteE^df1P&L>N_863uIWeu%Zh*#^^5sy47U4mB<|O zuh!^!E^BV)j;b$%(j{>Uroy}3P~kiFR{D~?_wEK9SBEJ!tn8kitFS#24Y?AVfa&t4 z*H{e}FLKwJpJvS2$FXg5kT`RZkPx>8_Oo+@;SF$0)qT~3Va}kmWTn?0Bh2$aSn|Ae zUcNQRY(|0T-aea6M?8TV4Ou9Cerf@$*?6e)c48Ajzc3gz3LaDmVnpA`i{iAqWz&0C zn7Z60myBr1zgOta=4xp~X@&jpp)f#nyfxI2Cg<9j*i z{3!P{Bi;8AJXicYZ)*oS`*ukJ2u=~*iVaoq*nF*a0CKLqQ)3FP?$x5BUX)D|>2#J> z$v#ePurA1P4i(oXBHd%_QKyI1Gr7eF;&p9~tl$@%0dp8ig zhnr-nH)>CENfwa7H!tWrCVljAV{7uBE)eQt=&g}QeM!y?6V?&wMO&PLP=My!*TB-J zX-e_Y>}q`+s6qTAK!43m4UO#6j#}VNs`^bH9cb(MhG=F_$W=fn=Guapj1j>x5&O}! zj4-uMSuPLXWV0jQ5y-`Mz)63BJFSM{-xU{{`OdXum4b$iSz1%3scPA8nvfbSL)0IW z?W5#PAKrG|UR8l=$IIWuR^zh(pJEpqc*BClKxRT@37!(! zTWY8osoG0k5x}0{9HYIL%)2183%odZSk*vw>F{-bT`R5uo`%jC`47>4go1U~mET6& z5S{v$yr(l3km|$mm=%h>~611PJd& zP-nRF+R(5-(}BVqBlUc%{qJ%=3IEeEtD1wOVQ+6jYCjP>J8=;@>p{ z7-Mi87j%MnPHbeX$Hh%dbqqWEq>q~b?&us9nAI1DT2e)^Gnv+uY%fx&cbCO+U(vs{ zmqgmb8H4ARX*wn-!>(uxkQ~&F8Z^V2*yUPRuVSm48zeHu3@6lsGIMSpBqtYDnZ=`Y z*$V7PRusrD1SYO1p$wFy^NR|(zK0rqr7jW#d{a_n5i4GP(hpaJ-e>1;s4T?3H@sfm z4}T9PxzXsT*T+rCWaVD?Y(e81Pd0q^8{_rnx~~Ku-%vi*Q~9o5%_5!?h=&957zD$w zmf|o4o~YUWE6R3Rt14@Vh+s;seN#ucILf9C>HUdUJ8c6qB$lG5dqnZKMUaWk_#1?7 zv=%pu3A-9ykOHFx^F*a}C(dp9^WUPyV%j+`7%dDjjJFbnQMojv(yE29%k66uJBp2v zUZ>+M1O;#%Wr!QdwdW7rRHT^K2qLGcreK}z*nl z<+}nJHo%za7}~~`E5tC&wcA+NWNK$(9slfI3Dc6{6V_ysfVJTNZ2Ty^Ddqisz1nug zn}fUKJK)F+&;W(XW6kG^dfzaL@#;4WfsoIs_(RwMl0Y_*QaC#w&(ib-DU^GBN=4yK-v+U|O8xTLt0TJJHoWI%) zH1O6Tq2GkiciOQOW53h@66GsA?`1&GuL3Q|=@4nqG88VLiPd2ClE*vk69

Fbwd9 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 **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 Search Tree/). 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. +The interesting bits are in the `balance()` method which is called after inserting or deleting a node. ## See also From 7050669ebf695f1f5b029812fffbff38b83540e8 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 20 Dec 2016 02:02:10 -0800 Subject: [PATCH 0038/1039] Modified the queue's peek property name to front per naming design guidelines. Computed properties should not imply action. Also checks out on Knuth's Fundamental Algorithms book page 241 where front and rear is the choice for his wording. --- Queue/Queue.playground/Contents.swift | 4 ++-- Queue/Queue.playground/timeline.xctimeline | 6 ------ Queue/README.markdown | 10 +++------- 3 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 Queue/Queue.playground/timeline.xctimeline diff --git a/Queue/Queue.playground/Contents.swift b/Queue/Queue.playground/Contents.swift index a8be21b08..a90fa647e 100644 --- a/Queue/Queue.playground/Contents.swift +++ b/Queue/Queue.playground/Contents.swift @@ -34,7 +34,7 @@ public struct Queue { } } - public var peek: T? { + public var front: T? { return array.first } } @@ -56,7 +56,7 @@ queueOfNames.dequeue() // Return the first element in the queue. // Returns "Lisa" since "Carl" was dequeued on the previous line. -queueOfNames.peek +queueOfNames.front // Check to see if the queue is empty. // Returns "false" since the queue still has elements in it. diff --git a/Queue/Queue.playground/timeline.xctimeline b/Queue/Queue.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Queue/Queue.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Queue/README.markdown b/Queue/README.markdown index f7779aa69..25d6205f8 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -68,7 +68,7 @@ public struct Queue { } } - public func peek() -> T? { + public var front: T? { return array.first } } @@ -166,12 +166,8 @@ public struct Queue { return element } - public func peek() -> T? { - if isEmpty { - return nil - } else { - return array[head] - } + public var front: T? { + return array.first } } ``` From 6a66252ad17ae92b068d8e27356b54a526bb7865 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 20 Dec 2016 02:11:41 -0800 Subject: [PATCH 0039/1039] Updated the peek function of the stack to a computed property instead. This change is inspired by the Swift naming conventions guide and Knuth's fundamental algorithms book page 242 where he states the element at the top of the stack may be denoted by top(A) where A is the stack. --- Stack/README.markdown | 6 +++--- Stack/Stack.playground/Contents.swift | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Stack/README.markdown b/Stack/README.markdown index 9d157f290..a79e2c261 100644 --- a/Stack/README.markdown +++ b/Stack/README.markdown @@ -38,7 +38,7 @@ 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 peek: +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 { @@ -60,8 +60,8 @@ public struct Stack { return array.popLast() } - public func peek() -> T? { - return array.last + public var top: T? { + return array.last } } ``` diff --git a/Stack/Stack.playground/Contents.swift b/Stack/Stack.playground/Contents.swift index f086ca817..1eb705f20 100644 --- a/Stack/Stack.playground/Contents.swift +++ b/Stack/Stack.playground/Contents.swift @@ -30,7 +30,7 @@ public struct Stack { return array.popLast() } - public func peek() -> T? { + public var top: T? { return array.last } } @@ -49,7 +49,7 @@ stackOfNames.pop() // Look at the first element from the stack. // Returns "Wade" since "Mike" was popped on the previous line. -stackOfNames.peek() +stackOfNames.top // Check to see if the stack is empty. // Returns "false" since the stack still has elements in it. From bfeac916bedcaba9555f49f982d96a1e84ce157a Mon Sep 17 00:00:00 2001 From: Anton Date: Tue, 20 Dec 2016 23:40:39 +0100 Subject: [PATCH 0040/1039] Add rotation steps description; --- AVL Tree/README.markdown | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 22ea99f53..bcbbbabbc 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -43,13 +43,32 @@ The difference between the heights of the left and right subtrees is called the 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. -Example of balancing the unbalanced tree using rotation: +Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation : ![Rotation](Images/Rotation.jpg) -Insertion never needs more than 2 rotations. Removal might require up to *log(n)* rotations. +Let's dig into rotation algorithm in detail using the terminology: +* *Root* - the parent not 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 + +The steps of rotation on the example image could be described by following: +* Select the *Pivot* as `D` and hence the *Root* as `F`; +* Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; +* Assign the *Root* as a new *RotationSubtree* for the *Pivot*; +* 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 From 45b5619710d40c5602cc3f70b2e5fdb3300e22ac Mon Sep 17 00:00:00 2001 From: Antonio081014 Date: Tue, 20 Dec 2016 16:40:49 -0800 Subject: [PATCH 0041/1039] Add missing link for Trie in README. --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 7ac170a65..5c769688a 100644 --- a/README.markdown +++ b/README.markdown @@ -156,7 +156,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap -- Trie +- [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. ### Hashing From 09b74c41364723dbb9b3752765913b13dcb1c6b7 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sat, 26 Nov 2016 17:58:21 -0500 Subject: [PATCH 0042/1039] Mathimatical explination --- Rootish Array Stack/README.md | 90 ++++++++++++++++-- .../images/RootishArrayStackExample2.png | Bin 0 -> 81023 bytes 2 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 Rootish Array Stack/images/RootishArrayStackExample2.png diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 842439a0c..285f39b14 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -2,18 +2,92 @@ 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) - +![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 a swift array does in terms of wasted space. -![Rootish Array Stack Intro](/images/RootishArrayStackExample.png) +![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). -### How indices map: -| Subscript index | Indices of Blocks| -| :------------- | :------------- | -| `[0]` | `blocks[0][0]` | +## The Math +The data structure is based on Gauss's summation technique: +``` +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..._ -## A Mathematical Explanation +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 of units. _5 rows and 6 columns_. + +We could calculate sum just as we would an area! Lets also express width and hight in terms of `n`: +``` +area of a rectangle = height * width = n * (n + 1) +``` +But 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 and just divide our area by 2! +``` +area of only x = n * (n + 1) / 2 +``` +And voila! We have an interesting new way to arrange our data! + +## Get/Set with Speed +Next we want to find an efficient way to access 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 +``` + +More difficult is determining which `block` an index points to. The number of elements that have indices less than or equal to the the requested `index` is: `index + 1` elements. The number of elements in blocks `0...block` is `(block + 1) * (block + 2) / 2`. Therefore, `block` is the smaller integer such that: +``` +(block + 1) * (block + 2) / 2 >= index + 1 +``` +This can be rewritten as: +``` +(block)^2 + (3 * block) - (2 * index) >= 0 +``` +Using the quadratic formula we can 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 but going back to our inequality, we want the smallest block such that `b => (-3 + √(9 + 8 * index)) / 2`. So we take the ceiling of the result: +``` +block = ⌈(-3 + √(9 + 8 * index)) / 2⌉ +``` + +Now we can figure out that `rootishArrayStack[12]` would point to the block at index `4` and at inner block index `2`. +![Rootish Array Stack Intro](images/RootishArrayStackExample2.png) + +# The Code + +To get the `capacity` of the structure we can use the equation we figured out above: +```swift +var capacity: Int { + return blocks.count * (blocks.count + 1) / 2 +} +``` +Since Swift arrays check `count` in `O(1)` time, this capacity lookup is also `O(1)`. + +To solve the problem of which block holds the block holds the element we are looking for we need diff --git a/Rootish Array Stack/images/RootishArrayStackExample2.png b/Rootish Array Stack/images/RootishArrayStackExample2.png new file mode 100644 index 0000000000000000000000000000000000000000..d032833bc99931702053554e2292d5da988ec419 GIT binary patch literal 81023 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

OSm`O{(p!p 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%0D$((KAk9=Fu|_{$`E=rTF#k_=NFSNA3H+*y;BG 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 literal 0 HcmV?d00001 From df6e54a0c0eadb4edba616430f247edb54b60d32 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sun, 27 Nov 2016 22:32:12 -0500 Subject: [PATCH 0043/1039] Added 'Code' segment --- Rootish Array Stack/README.md | 41 +++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 285f39b14..3f154629f 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -10,8 +10,9 @@ A resizable array holds references to blocks (arrays of fixed size). A block's c Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). -## The Math -The data structure is based on Gauss's summation technique: +## Gauss's Summation Trick + +This data structure is based on Gauss's summation technique: ``` sum from 1...n = n * (n + 1) / 2 ``` @@ -51,10 +52,10 @@ But we only want to calculate the amount of `x`s, not the amount of `o`s. Since ``` area of only x = n * (n + 1) / 2 ``` -And voila! We have an interesting new way to arrange our data! +And 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 way to access a random index. For example which block does `rootishArrayStack[12]` point to? To answer this we will need MORE MATH! +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 @@ -81,13 +82,39 @@ Now we can figure out that `rootishArrayStack[12]` would point to the block at i ![Rootish Array Stack Intro](images/RootishArrayStackExample2.png) # The Code +Lets start with instance variables and struct declaration: +```swift +import Darwin + +public struct RootishArrayStack { + fileprivate var blocks = [Array]() + fileprivate var internalCount = 0 + + public init() { } -To get the `capacity` of the structure we can use the equation we figured out above: + 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 variables that gives 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 } ``` -Since Swift arrays check `count` in `O(1)` time, this capacity lookup is also `O(1)`. -To solve the problem of which block holds the block holds the element we are looking for we need +To determine which block an index map to: +```swift +fileprivate static func toBlock(index: Int) -> Int { + let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) + return block +} +``` +This comes straight from the equations derived earlier. As mentioned `sqrt()`, and `ceil()` were imported from `Darwin`. From 1d16285c873b4b7e7d31d6a7de611cdc838ecbc2 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 28 Nov 2016 00:32:17 -0500 Subject: [PATCH 0044/1039] Preventing thrashing --- Rootish Array Stack/README.md | 19 ++++++-- Rootish Array Stack/RootishArrayStack.swift | 53 +++++++++++---------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 3f154629f..f6d55b03a 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -110,11 +110,24 @@ var capacity: Int { } ``` -To determine which block an index map to: +Next lets build what we need to get/set elements: ```swift -fileprivate static func toBlock(index: Int) -> Int { +fileprivate func toBlock(index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } + +public subscript(index: Int) -> T { + get { + let block = toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + return blocks[block][blockIndex]! + } + set(newValue) { + let block = toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + blocks[block][blockIndex] = newValue + } +} ``` -This comes straight from the equations derived earlier. As mentioned `sqrt()`, and `ceil()` were imported from `Darwin`. +`toBlock` is really just wrapping the `block` equation derived earlier. `superscript` lets us have `get/set` access to the structure with the familiar `[index]` syntax. diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index f17f9620e..6cb1cff06 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -21,11 +21,24 @@ public struct RootishArrayStack { return blocks.count * (blocks.count + 1) / 2 } - fileprivate static func toBlock(index: Int) -> Int { + fileprivate func toBlock(index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) return block } + public subscript(index: Int) -> T { + get { + let block = toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + return blocks[block][blockIndex]! + } + set(newValue) { + let block = toBlock(index: index) + let blockIndex = index - block * (block + 1) / 2 + blocks[block][blockIndex] = newValue + } + } + fileprivate mutating func grow() { let newArray = [T?](repeating: nil, count: blocks.count + 1) blocks.append(newArray) @@ -39,21 +52,8 @@ public struct RootishArrayStack { } } - public subscript(index: Int) -> T { - get { - let block = RootishArrayStack.toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - return blocks[block][blockIndex]! - } - set(newValue) { - let block = RootishArrayStack.toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = newValue - } - } - public mutating func insert(element: T, atIndex index: Int) { - if capacity < count + 1 { + if capacity - blocks.count < count + 1 { grow() } internalCount += 1 @@ -70,7 +70,7 @@ public struct RootishArrayStack { } fileprivate mutating func makeNil(atIndex index: Int) { - let block = RootishArrayStack.toBlock(index: index) + let block = toBlock(index: index) let blockIndex = index - block * (block + 1) / 2 blocks[block][blockIndex] = nil } @@ -82,22 +82,22 @@ public struct RootishArrayStack { } internalCount -= 1 makeNil(atIndex: count) - if capacity >= count { + if capacity + blocks.count >= count { shrink() } return element } public var memoryDescription: String { - var s = "{\n" - for i in blocks { - s += "\t[" - for j in i { - s += "\(j), " + var description = "{\n" + for block in blocks { + description += "\t[" + for rawElement in block { + description += "\(rawElement), " } - s += "]\n" + description += "]\n" } - return s + "}" + return description + "}" } } @@ -113,3 +113,8 @@ extension RootishArrayStack: CustomStringConvertible { return s + "]" } } + +var list = RootishArrayStack() +for i in 0...10 { + list.append(element: i) +} From c3d03b9b2d56b17bd66eed450e64b58ef2a469c6 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 28 Nov 2016 22:04:34 -0500 Subject: [PATCH 0045/1039] Finished implementation explination --- Rootish Array Stack/README.md | 69 ++++++++++++++++++++- Rootish Array Stack/RootishArrayStack.swift | 43 ++++++------- 2 files changed, 86 insertions(+), 26 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index f6d55b03a..790eea6da 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -96,6 +96,9 @@ public struct RootishArrayStack { 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?`. @@ -110,7 +113,7 @@ var capacity: Int { } ``` -Next lets build what we need to get/set elements: +Next lets look at we would `get` and `set` elements: ```swift fileprivate func toBlock(index: Int) -> Int { let block = Int(ceil((-3.0 + sqrt(9.0 + 8.0 * Double(index))) / 2)) @@ -130,4 +133,66 @@ public subscript(index: Int) -> T { } } ``` -`toBlock` is really just wrapping the `block` equation derived earlier. `superscript` lets us have `get/set` access to the structure with the familiar `[index]` syntax. +`toBlock(index:)` is really just wrapping the `block` equation derived earlier to return the block that an index maps to. `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 lets look at how we would `growIfNeeded()` and `shrinkIfNeeded()` the structure. +```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 { + var numberOfBlocks = blocks.count + while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + blocks.remove(at: blocks.count - 1) + numberOfBlocks -= 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)` wheres 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). diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 6cb1cff06..4edc58b2f 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -26,6 +26,23 @@ public struct RootishArrayStack { return block } + 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 { + var numberOfBlocks = blocks.count + while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + blocks.remove(at: blocks.count - 1) + numberOfBlocks -= 1 + } + } + } + public subscript(index: Int) -> T { get { let block = toBlock(index: index) @@ -39,23 +56,8 @@ public struct RootishArrayStack { } } - fileprivate mutating func grow() { - let newArray = [T?](repeating: nil, count: blocks.count + 1) - blocks.append(newArray) - } - - fileprivate mutating func shrink() { - var numberOfBlocks = blocks.count - while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { - blocks.remove(at: blocks.count - 1) - numberOfBlocks -= 1 - } - } - public mutating func insert(element: T, atIndex index: Int) { - if capacity - blocks.count < count + 1 { - grow() - } + growIfNeeded() internalCount += 1 var i = count - 1 while i > index { @@ -82,9 +84,7 @@ public struct RootishArrayStack { } internalCount -= 1 makeNil(atIndex: count) - if capacity + blocks.count >= count { - shrink() - } + shrinkIfNeeded() return element } @@ -113,8 +113,3 @@ extension RootishArrayStack: CustomStringConvertible { return s + "]" } } - -var list = RootishArrayStack() -for i in 0...10 { - list.append(element: i) -} From 72c12e92485f49b24c30b61522ae9aff9035cdaf Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 28 Nov 2016 22:32:23 -0500 Subject: [PATCH 0046/1039] Added Gauss' legend Polished example --- Rootish Array Stack/README.md | 36 +++++++++++++++------ Rootish Array Stack/RootishArrayStack.swift | 4 +-- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 790eea6da..5f62cec2c 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -10,9 +10,8 @@ A resizable array holds references to blocks (arrays of fixed size). A block's c Here you can see how insert/remove operations would behave (very similar to how a Swift array handles such operations). -## Gauss's Summation Trick - -This data structure is based on Gauss's summation technique: +## 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 the teacher 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 manual adding up all the number 1 by 1. His formula: ``` sum from 1...n = n * (n + 1) / 2 ``` @@ -42,9 +41,9 @@ 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 of units. _5 rows and 6 columns_. +Here we have `n` rows and `n + 1` columns. _5 rows and 6 columns_. -We could calculate sum just as we would an area! Lets also express width and hight in terms of `n`: +We could calculate sum just as we would an area! Lets also express the width and hight in terms of `n`: ``` area of a rectangle = height * width = n * (n + 1) ``` @@ -78,10 +77,26 @@ A negative block doesn't make sense so we take the positive root instead. In gen block = ⌈(-3 + √(9 + 8 * index)) / 2⌉ ``` -Now we can figure out that `rootishArrayStack[12]` would point to the block at index `4` and at inner block index `2`. +Now we can figure out that `rootishArrayStack[12]` points to! First lets 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) -# The Code +# Implementation Details Lets start with instance variables and struct declaration: ```swift import Darwin @@ -149,10 +164,8 @@ fileprivate mutating func growIfNeeded() { fileprivate mutating func shrinkIfNeeded() { if capacity + blocks.count >= count { - var numberOfBlocks = blocks.count - while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { blocks.remove(at: blocks.count - 1) - numberOfBlocks -= 1 } } } @@ -196,3 +209,6 @@ fileprivate mutating func makeNil(atIndex index: Int) { ``` To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element we set the value using the `subscript` convenience. `append(element:)` is just a convenience method to add to the end. To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. `makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). > 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)` wheres 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). + +# Runtime Analysis + diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 4edc58b2f..66a681f97 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -35,10 +35,8 @@ public struct RootishArrayStack { fileprivate mutating func shrinkIfNeeded() { if capacity + blocks.count >= count { - var numberOfBlocks = blocks.count - while numberOfBlocks > 0 && (numberOfBlocks - 2) * (numberOfBlocks - 1) / 2 >= count { + while blocks.count > 0 && (blocks.count - 2) * (blocks.count - 1) / 2 >= count { blocks.remove(at: blocks.count - 1) - numberOfBlocks -= 1 } } } From cb673314ee570504f655c3d6d992fe90d3c2425e Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Thu, 8 Dec 2016 22:15:14 -0500 Subject: [PATCH 0047/1039] Added performance explination + cleaned up some implementation details --- Rootish Array Stack/README.md | 27 +++++++++++++-------- Rootish Array Stack/RootishArrayStack.swift | 24 ++++++++++-------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index 5f62cec2c..ee2351d4d 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -102,16 +102,17 @@ Lets start with instance variables and struct declaration: import Darwin public struct RootishArrayStack { - fileprivate var blocks = [Array]() - fileprivate var internalCount = 0 - public init() { } + fileprivate var blocks = [Array]() + fileprivate var internalCount = 0 - var count: Int { - return internalCount - } + public init() { } + + var count: Int { + return internalCount + } - ... + ... } @@ -149,7 +150,7 @@ public subscript(index: Int) -> T { } ``` `toBlock(index:)` is really just wrapping the `block` equation derived earlier to return the block that an index maps to. `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 + 1. determine the block that the index points to 2. determine the inner block index 3. `get`/`set` the value @@ -210,5 +211,11 @@ fileprivate mutating func makeNil(atIndex index: Int) { To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element we set the value using the `subscript` convenience. `append(element:)` is just a convenience method to add to the end. To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. `makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). > 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)` wheres 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). -# Runtime Analysis - +# 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()` and `remove()` operations shift all elements right of the specified index resulting in **O(n)** time. diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 66a681f97..842e34f72 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -21,11 +21,15 @@ public struct RootishArrayStack { return blocks.count * (blocks.count + 1) / 2 } - fileprivate func toBlock(index: Int) -> Int { + 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 + } + fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { let newArray = [T?](repeating: nil, count: blocks.count + 1) @@ -43,14 +47,14 @@ public struct RootishArrayStack { public subscript(index: Int) -> T { get { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - return blocks[block][blockIndex]! + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + return blocks[block][innerBlockIndex]! } set(newValue) { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = newValue + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = newValue } } @@ -70,9 +74,9 @@ public struct RootishArrayStack { } fileprivate mutating func makeNil(atIndex index: Int) { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = nil + 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 { From b8f87bfe07d5268b37ad7e4fb5f2319a94d7d060 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sat, 10 Dec 2016 23:14:15 -0500 Subject: [PATCH 0048/1039] Added performance analysis --- Rootish Array Stack/README.md | 68 ++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index ee2351d4d..c00061082 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -11,7 +11,7 @@ A resizable array holds references to blocks (arrays of fixed size). A block's c 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 the teacher 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 manual adding up all the number 1 by 1. His formula: +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 the teacher 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 ``` @@ -96,6 +96,9 @@ 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 Lets start with instance variables and struct declaration: ```swift @@ -106,10 +109,10 @@ public struct RootishArrayStack { fileprivate var blocks = [Array]() fileprivate var internalCount = 0 - public init() { } + public init() { } - var count: Int { - return internalCount + var count: Int { + return internalCount } ... @@ -131,25 +134,29 @@ var capacity: Int { Next lets look at we would `get` and `set` elements: ```swift -fileprivate func toBlock(index: Int) -> Int { +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 = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - return blocks[block][blockIndex]! + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + return blocks[block][innerBlockIndex]! } set(newValue) { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = newValue + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = newValue } } ``` -`toBlock(index:)` is really just wrapping the `block` equation derived earlier to return the block that an index maps to. `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: +`block(fromIndex:)` and `innerBlockIndex(fromIndex:, fromBlock:)` are wrapping the `block` and `inner block index` equations 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 @@ -157,18 +164,18 @@ public subscript(index: Int) -> T { Next lets look at how we would `growIfNeeded()` and `shrinkIfNeeded()` the structure. ```swift fileprivate mutating func growIfNeeded() { - if capacity - blocks.count < count + 1 { - let newArray = [T?](repeating: nil, count: blocks.count + 1) - blocks.append(newArray) - } + 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 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. @@ -203,9 +210,9 @@ public mutating func remove(atIndex index: Int) -> T { } fileprivate mutating func makeNil(atIndex index: Int) { - let block = toBlock(index: index) - let blockIndex = index - block * (block + 1) / 2 - blocks[block][blockIndex] = nil + let block = self.block(fromIndex: index) + let innerBlockIndex = self.innerBlockIndex(fromIndex: index, fromBlock: block) + blocks[block][innerBlockIndex] = nil } ``` To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element we set the value using the `subscript` convenience. `append(element:)` is just a convenience method to add to the end. To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. `makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). @@ -218,4 +225,15 @@ To `insert(element:, atIndex:)` we move all elements after the `index` to the ri * 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()` and `remove()` operations shift all elements right of the specified index resulting in **O(n)** time. +* 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 cost **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)_ From 0879118bfdffa6ec3d9f426322b3b751e87e6b85 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sat, 10 Dec 2016 23:44:08 -0500 Subject: [PATCH 0049/1039] Marks in swift file --- Rootish Array Stack/RootishArrayStack.swift | 40 +++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 842e34f72..0d2b15c3c 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -1,18 +1,24 @@ // -// main.swift // RootishArrayStack // -// Created by Benjamin Emdon on 2016-11-07. +// 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 } @@ -21,6 +27,8 @@ public struct RootishArrayStack { return blocks.count * (blocks.count + 1) / 2 } + // 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 @@ -30,6 +38,8 @@ public struct RootishArrayStack { 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) @@ -89,20 +99,10 @@ public struct RootishArrayStack { shrinkIfNeeded() return element } - - public var memoryDescription: String { - var description = "{\n" - for block in blocks { - description += "\t[" - for rawElement in block { - description += "\(rawElement), " - } - description += "]\n" - } - return description + "}" - } } +// MARK: - Struct to string + extension RootishArrayStack: CustomStringConvertible { public var description: String { var s = "[" @@ -114,4 +114,16 @@ extension RootishArrayStack: CustomStringConvertible { } return s + "]" } + + public var memoryDescription: String { + var description = "{\n" + for block in blocks { + description += "\t[" + for rawElement in block { + description += "\(rawElement), " + } + description += "]\n" + } + return description + "}" + } } From e5dfe6637980b9f425371c0dbe82dedae1100d3e Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sun, 11 Dec 2016 00:25:58 -0500 Subject: [PATCH 0050/1039] Added isEmpty, first, last --- Rootish Array Stack/RootishArrayStack.swift | 16 ++++++++++++++++ .../contents.xcworkspacedata | 3 +++ 2 files changed, 19 insertions(+) diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 0d2b15c3c..4033d75f6 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -27,6 +27,22 @@ public struct RootishArrayStack { 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 { diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index ac3a79be9..c2ae29f70 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1529,6 +1529,9 @@ + + Date: Sun, 11 Dec 2016 00:32:20 -0500 Subject: [PATCH 0051/1039] Added playground Finished playground --- Rootish Array Stack/README.md | 58 ++--- .../Contents.swift | 219 ++++++++++++++++++ .../contents.xcplayground | 4 + Rootish Array Stack/RootishArrayStack.swift | 35 +-- 4 files changed, 273 insertions(+), 43 deletions(-) create mode 100644 Rootish Array Stack/RootishArrayStack.playground/Contents.swift create mode 100644 Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground diff --git a/Rootish Array Stack/README.md b/Rootish Array Stack/README.md index c00061082..6a45b262a 100644 --- a/Rootish Array Stack/README.md +++ b/Rootish Array Stack/README.md @@ -4,14 +4,14 @@ A *Rootish Array Stack* is an ordered array based structure that minimizes waste ![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 a swift array does in terms of wasted space. +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 the teacher 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: +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 ``` @@ -22,7 +22,7 @@ blocks: [x] [x x] [x x x] [x x x x] [x x x x x] ``` _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_: +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 --|------------- @@ -43,24 +43,24 @@ 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 could calculate sum just as we would an area! Lets also express the width and hight in terms of `n`: +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) ``` -But 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 and just divide our area by 2! +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 ``` -And 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. +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! +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 ``` - -More difficult is determining which `block` an index points to. The number of elements that have indices less than or equal to the the requested `index` is: `index + 1` elements. The number of elements in blocks `0...block` is `(block + 1) * (block + 2) / 2`. Therefore, `block` is the smaller integer such that: +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 ``` @@ -68,16 +68,16 @@ This can be rewritten as: ``` (block)^2 + (3 * block) - (2 * index) >= 0 ``` -Using the quadratic formula we can get: +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 but going back to our inequality, we want the smallest block such that `b => (-3 + √(9 + 8 * index)) / 2`. So we take the ceiling of the result: +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 that `rootishArrayStack[12]` points to! First lets see which block the `12` points to: +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⌉ @@ -93,14 +93,14 @@ 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`. +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)**. +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 -Lets start with instance variables and struct declaration: +Let's start with instance variables and struct declaration: ```swift import Darwin @@ -123,7 +123,7 @@ public struct RootishArrayStack { 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 variables that gives the `internalCount` value. `Darwin` is imported here to provide simple math functions such as `ceil()` and `sqrt()`. +`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 @@ -132,7 +132,7 @@ var capacity: Int { } ``` -Next lets look at we would `get` and `set` elements: +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)) @@ -156,12 +156,13 @@ public subscript(index: Int) -> T { } } ``` -`block(fromIndex:)` and `innerBlockIndex(fromIndex:, fromBlock:)` are wrapping the `block` and `inner block index` equations 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 +`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 lets look at how we would `growIfNeeded()` and `shrinkIfNeeded()` the structure. +Next, let's look at how we would `growIfNeeded()` and `shrinkIfNeeded()`. ```swift fileprivate mutating func growIfNeeded() { if capacity - blocks.count < count + 1 { @@ -179,7 +180,7 @@ fileprivate mutating func shrinkIfNeeded() { } ``` 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. +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 @@ -215,8 +216,11 @@ fileprivate mutating func makeNil(atIndex index: Int) { blocks[block][innerBlockIndex] = nil } ``` -To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element we set the value using the `subscript` convenience. `append(element:)` is just a convenience method to add to the end. To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. `makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). -> 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)` wheres 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). +To `insert(element:, atIndex:)` we move all elements after the `index` to the right by 1. After space has been made for the element, we set the value using the `subscript` convenience method. +`append(element:)` is just a convenience method to `insert` to the end. +To `remove(atIndex:)` we move all the elements after the `index` to the left by 1. After the removed value is covered by it's proceeding value, we set the last value in the structure to `nil`. +`makeNil(atIndex:)` uses the same logic as our `subscript` method but is used to set the root optional at a particular index to `nil` (because setting it's wrapped value to `nil` is something only the user of the data structure should do). +> 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. @@ -228,10 +232,10 @@ To `insert(element:, atIndex:)` we move all elements after the `index` to the ri * 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 cost **O(√n)**. +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)**. +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_ diff --git a/Rootish Array Stack/RootishArrayStack.playground/Contents.swift b/Rootish Array Stack/RootishArrayStack.playground/Contents.swift new file mode 100644 index 000000000..401c773d6 --- /dev/null +++ b/Rootish Array Stack/RootishArrayStack.playground/Contents.swift @@ -0,0 +1,219 @@ +//: Playground - noun: a place where people can play + +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"] diff --git a/Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground b/Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground new file mode 100644 index 000000000..63b6dd8df --- /dev/null +++ b/Rootish Array Stack/RootishArrayStack.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Rootish Array Stack/RootishArrayStack.swift b/Rootish Array Stack/RootishArrayStack.swift index 4033d75f6..af95a4316 100644 --- a/Rootish Array Stack/RootishArrayStack.swift +++ b/Rootish Array Stack/RootishArrayStack.swift @@ -115,31 +115,34 @@ public struct RootishArrayStack { shrinkIfNeeded() return element } -} - -// MARK: - Struct to string -extension RootishArrayStack: CustomStringConvertible { - public var description: String { - var s = "[" - for index in 0.. Date: Sun, 18 Dec 2016 16:57:29 -0500 Subject: [PATCH 0052/1039] Added tests template --- Rootish Array Stack/Tests/Info.plist | 24 ++ .../Tests/RootishArrayStack.swift | 148 ++++++++++ .../Tests/RootishArrayStackTests.swift | 251 +++++++++++++++++ .../Tests/Tests.xcodeproj/project.pbxproj | 264 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 90 ++++++ 6 files changed, 784 insertions(+) create mode 100644 Rootish Array Stack/Tests/Info.plist create mode 100644 Rootish Array Stack/Tests/RootishArrayStack.swift create mode 100755 Rootish Array Stack/Tests/RootishArrayStackTests.swift create mode 100644 Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Rootish Array Stack/Tests/Info.plist b/Rootish Array Stack/Tests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/Rootish Array Stack/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Rootish Array Stack/Tests/RootishArrayStack.swift b/Rootish Array Stack/Tests/RootishArrayStack.swift new file mode 100644 index 000000000..af95a4316 --- /dev/null +++ b/Rootish Array Stack/Tests/RootishArrayStack.swift @@ -0,0 +1,148 @@ +// +// 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.. LinkedList { + let list = LinkedList() + for number in numbers { + list.append(number) + } + return list + } + + 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.first!.previous) + XCTAssertNil(list.first!.next) + XCTAssertEqual(list.first!.value, 123) + + XCTAssertNotNil(list.last) + XCTAssertNil(list.last!.previous) + XCTAssertNil(list.last!.next) + XCTAssertEqual(list.last!.value, 123) + + XCTAssertTrue(list.first === list.last) + } + + func testListWithTwoElements() { + let list = LinkedList() + list.append(123) + list.append(456) + + XCTAssertEqual(list.count, 2) + + XCTAssertNotNil(list.first) + XCTAssertEqual(list.first!.value, 123) + + XCTAssertNotNil(list.last) + XCTAssertEqual(list.last!.value, 456) + + XCTAssertTrue(list.first !== list.last) + + XCTAssertNil(list.first!.previous) + XCTAssertTrue(list.first!.next === list.last) + XCTAssertTrue(list.last!.previous === list.first) + 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.first!.value, 123) + + let second = list.first!.next + XCTAssertNotNil(second) + XCTAssertEqual(second!.value, 456) + + XCTAssertNotNil(list.last) + XCTAssertEqual(list.last!.value, 789) + + XCTAssertNil(list.first!.previous) + XCTAssertTrue(list.first!.next === second) + XCTAssertTrue(second!.previous === list.first) + XCTAssertTrue(second!.next === list.last) + XCTAssertTrue(list.last!.previous === second) + XCTAssertNil(list.last!.next) + } + + func testNodeAtIndexInEmptyList() { + let list = LinkedList() + let node = list.node(atIndex: 0) + XCTAssertNil(node) + } + + func testNodeAtIndexInListWithOneElement() { + let list = LinkedList() + list.append(123) + + let node = list.node(atIndex: 0) + XCTAssertNotNil(node) + XCTAssertEqual(node!.value, 123) + XCTAssertTrue(node === list.first) + } + + func testNodeAtIndex() { + let list = buildList() + + let nodeCount = list.count + XCTAssertEqual(nodeCount, numbers.count) + + XCTAssertNil(list.node(atIndex: -1)) + XCTAssertNil(list.node(atIndex: nodeCount)) + + let first = list.node(atIndex: 0) + XCTAssertNotNil(first) + XCTAssertTrue(first === list.first) + XCTAssertEqual(first!.value, numbers[0]) + + let last = list.node(atIndex: nodeCount - 1) + XCTAssertNotNil(last) + XCTAssertTrue(last === list.last) + XCTAssertEqual(last!.value, numbers[nodeCount - 1]) + + for i in 0..() + list.insert(123, atIndex: 0) + + XCTAssertFalse(list.isEmpty) + XCTAssertEqual(list.count, 1) + + let node = list.node(atIndex: 0) + XCTAssertNotNil(node) + XCTAssertEqual(node!.value, 123) + } + + func testInsertAtIndex() { + let list = buildList() + let prev = list.node(atIndex: 2) + let next = list.node(atIndex: 3) + let nodeCount = list.count + + list.insert(444, atIndex: 3) + + let node = list.node(atIndex: 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 testRemoveAtIndexOnListWithOneElement() { + let list = LinkedList() + list.append(123) + + let value = list.remove(atIndex: 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(atIndex: 2) + let next = list.node(atIndex: 3) + let nodeCount = list.count + + list.insert(444, atIndex: 3) + + let value = list.remove(atIndex: 3) + XCTAssertEqual(value, 444) + + let node = list.node(atIndex: 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.first + let last = list.last + let nodeCount = list.count + + list.reverse() + + XCTAssertTrue(first === list.last) + XCTAssertTrue(last === list.first) + XCTAssertEqual(nodeCount, list.count) + } +} diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj b/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..d6fb62c9d --- /dev/null +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,264 @@ +// !$*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 = 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 = ( + 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_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 = 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 */; +} diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..8ef8d8581 --- /dev/null +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f709ee8d52dbef684e02e6350bd5110c2ffb313b Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Sun, 18 Dec 2016 17:31:52 -0500 Subject: [PATCH 0053/1039] added test scheme to travis --- .travis.yml | 1 + .../contents.xcworkspacedata | 7 + .../Tests/RootishArrayStackTests.swift | 492 +++++++++--------- .../Tests/Tests.xcodeproj/project.pbxproj | 9 +- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- .../contents.xcworkspacedata | 29 ++ 6 files changed, 293 insertions(+), 247 deletions(-) create mode 100644 Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/.travis.yml b/.travis.yml index 45f0d4beb..695c702c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ script: # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Rootish\ Array\ Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests diff --git a/Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata b/Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Rootish Array Stack/RootishArrayStack.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Rootish Array Stack/Tests/RootishArrayStackTests.swift b/Rootish Array Stack/Tests/RootishArrayStackTests.swift index 7fa420cb2..8292f3d30 100755 --- a/Rootish Array Stack/Tests/RootishArrayStackTests.swift +++ b/Rootish Array Stack/Tests/RootishArrayStackTests.swift @@ -1,251 +1,255 @@ import XCTest class RootishArrayStackTests: XCTestCase { - let numbers = [8, 2, 10, 9, 7, 5] - - fileprivate func buildList() -> LinkedList { - let list = LinkedList() - for number in numbers { - list.append(number) - } +// let randomNumbers = [8, 2, 10, 9, 7, 5] + + func buildList(withNumbers numbers: [Int]? = nil) -> RootishArrayStack { + var list = RootishArrayStack() + if let numbers = numbers { + for number in numbers { + list.append(element: number) + } + } return list } - 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.first!.previous) - XCTAssertNil(list.first!.next) - XCTAssertEqual(list.first!.value, 123) - - XCTAssertNotNil(list.last) - XCTAssertNil(list.last!.previous) - XCTAssertNil(list.last!.next) - XCTAssertEqual(list.last!.value, 123) - - XCTAssertTrue(list.first === list.last) - } - - func testListWithTwoElements() { - let list = LinkedList() - list.append(123) - list.append(456) - - XCTAssertEqual(list.count, 2) - - XCTAssertNotNil(list.first) - XCTAssertEqual(list.first!.value, 123) - - XCTAssertNotNil(list.last) - XCTAssertEqual(list.last!.value, 456) - - XCTAssertTrue(list.first !== list.last) - - XCTAssertNil(list.first!.previous) - XCTAssertTrue(list.first!.next === list.last) - XCTAssertTrue(list.last!.previous === list.first) - 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.first!.value, 123) - - let second = list.first!.next - XCTAssertNotNil(second) - XCTAssertEqual(second!.value, 456) - - XCTAssertNotNil(list.last) - XCTAssertEqual(list.last!.value, 789) - - XCTAssertNil(list.first!.previous) - XCTAssertTrue(list.first!.next === second) - XCTAssertTrue(second!.previous === list.first) - XCTAssertTrue(second!.next === list.last) - XCTAssertTrue(list.last!.previous === second) - XCTAssertNil(list.last!.next) - } - - func testNodeAtIndexInEmptyList() { - let list = LinkedList() - let node = list.node(atIndex: 0) - XCTAssertNil(node) - } - - func testNodeAtIndexInListWithOneElement() { - let list = LinkedList() - list.append(123) - - let node = list.node(atIndex: 0) - XCTAssertNotNil(node) - XCTAssertEqual(node!.value, 123) - XCTAssertTrue(node === list.first) - } - - func testNodeAtIndex() { - let list = buildList() - - let nodeCount = list.count - XCTAssertEqual(nodeCount, numbers.count) - - XCTAssertNil(list.node(atIndex: -1)) - XCTAssertNil(list.node(atIndex: nodeCount)) - - let first = list.node(atIndex: 0) - XCTAssertNotNil(first) - XCTAssertTrue(first === list.first) - XCTAssertEqual(first!.value, numbers[0]) - - let last = list.node(atIndex: nodeCount - 1) - XCTAssertNotNil(last) - XCTAssertTrue(last === list.last) - XCTAssertEqual(last!.value, numbers[nodeCount - 1]) - - for i in 0..() - list.insert(123, atIndex: 0) - - XCTAssertFalse(list.isEmpty) - XCTAssertEqual(list.count, 1) - - let node = list.node(atIndex: 0) - XCTAssertNotNil(node) - XCTAssertEqual(node!.value, 123) - } - - func testInsertAtIndex() { - let list = buildList() - let prev = list.node(atIndex: 2) - let next = list.node(atIndex: 3) - let nodeCount = list.count - - list.insert(444, atIndex: 3) - - let node = list.node(atIndex: 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 testRemoveAtIndexOnListWithOneElement() { - let list = LinkedList() - list.append(123) - - let value = list.remove(atIndex: 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(atIndex: 2) - let next = list.node(atIndex: 3) - let nodeCount = list.count - - list.insert(444, atIndex: 3) - - let value = list.remove(atIndex: 3) - XCTAssertEqual(value, 444) - - let node = list.node(atIndex: 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.first - let last = list.last - let nodeCount = list.count - - list.reverse() - - XCTAssertTrue(first === list.last) - XCTAssertTrue(last === list.first) - XCTAssertEqual(nodeCount, list.count) - } + func testEmptyList() { + let list = buildList() + XCTAssertTrue(list.isEmpty) + XCTAssertEqual(list.count, 0) + XCTAssertEqual(list.capacity, 0) + XCTAssertNil(list.first) + XCTAssertNil(list.last) + } + + func testListWithOneElement() { + let list = buildList(withNumbers: [1]) + XCTAssertFalse(list.isEmpty) + XCTAssertEqual(list.count, 1) + XCTAssertEqual(list.capacity, 1) + XCTAssertEqual(list.first, 1) + XCTAssertEqual(list.last, 1) + XCTAssertEqual(list.first, list.last) + } + + func testListWithTwoElements() { + let list = buildList(withNumbers: [1, 2]) + XCTAssertFalse(list.isEmpty) + XCTAssertEqual(list.count, 2) + XCTAssertEqual(list.capacity, 3) + XCTAssertEqual(list.first, 1) + XCTAssertEqual(list.last, 2) + XCTAssertNotEqual(list.first, list.last) + } + +// +// func testListWithTwoElements() { +// var list = RootishArrayStack() +// list.append(123) +// list.append(456) +// +// XCTAssertEqual(list.count, 2) +// +// XCTAssertNotNil(list.first) +// XCTAssertEqual(list.first!.value, 123) +// +// XCTAssertNotNil(list.last) +// XCTAssertEqual(list.last!.value, 456) +// +// XCTAssertTrue(list.first !== list.last) +// +// XCTAssertNil(list.first!.previous) +// XCTAssertTrue(list.first!.next === list.last) +// XCTAssertTrue(list.last!.previous === list.first) +// XCTAssertNil(list.last!.next) +// } +// +// func testListWithThreeElements() { +// var list = RootishArrayStack() +// list.append(123) +// list.append(456) +// list.append(789) +// +// XCTAssertEqual(list.count, 3) +// +// XCTAssertNotNil(list.first) +// XCTAssertEqual(list.first!.value, 123) +// +// let second = list.first!.next +// XCTAssertNotNil(second) +// XCTAssertEqual(second!.value, 456) +// +// XCTAssertNotNil(list.last) +// XCTAssertEqual(list.last!.value, 789) +// +// XCTAssertNil(list.first!.previous) +// XCTAssertTrue(list.first!.next === second) +// XCTAssertTrue(second!.previous === list.first) +// XCTAssertTrue(second!.next === list.last) +// XCTAssertTrue(list.last!.previous === second) +// XCTAssertNil(list.last!.next) +// } +// +// func testNodeAtIndexInEmptyList() { +// var list = RootishArrayStack() +// let node = list.node(atIndex: 0) +// XCTAssertNil(node) +// } +// +// func testNodeAtIndexInListWithOneElement() { +// let list = RootishArrayStack() +// list.append(123) +// +// let node = list.node(atIndex: 0) +// XCTAssertNotNil(node) +// XCTAssertEqual(node!.value, 123) +// XCTAssertTrue(node === list.first) +// } +// +// func testNodeAtIndex() { +// let list = buildList() +// +// let nodeCount = list.count +// XCTAssertEqual(nodeCount, numbers.count) +// +// XCTAssertNil(list.node(atIndex: -1)) +// XCTAssertNil(list.node(atIndex: nodeCount)) +// +// let first = list.node(atIndex: 0) +// XCTAssertNotNil(first) +// XCTAssertTrue(first === list.first) +// XCTAssertEqual(first!.value, numbers[0]) +// +// let last = list.node(atIndex: nodeCount - 1) +// XCTAssertNotNil(last) +// XCTAssertTrue(last === list.last) +// XCTAssertEqual(last!.value, numbers[nodeCount - 1]) +// +// for i in 0..() +// list.insert(123, atIndex: 0) +// +// XCTAssertFalse(list.isEmpty) +// XCTAssertEqual(list.count, 1) +// +// let node = list.node(atIndex: 0) +// XCTAssertNotNil(node) +// XCTAssertEqual(node!.value, 123) +// } +// +// func testInsertAtIndex() { +// let list = buildList() +// let prev = list.node(atIndex: 2) +// let next = list.node(atIndex: 3) +// let nodeCount = list.count +// +// list.insert(444, atIndex: 3) +// +// let node = list.node(atIndex: 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 testRemoveAtIndexOnListWithOneElement() { +// let list = LinkedList() +// list.append(123) +// +// let value = list.remove(atIndex: 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(atIndex: 2) +// let next = list.node(atIndex: 3) +// let nodeCount = list.count +// +// list.insert(444, atIndex: 3) +// +// let value = list.remove(atIndex: 3) +// XCTAssertEqual(value, 444) +// +// let node = list.node(atIndex: 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.first +// let last = list.last +// let nodeCount = list.count +// +// list.reverse() +// +// XCTAssertTrue(first === list.last) +// XCTAssertTrue(last === list.first) +// XCTAssertEqual(nodeCount, list.count) +// } } diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj b/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj index d6fb62c9d..cdfd35f71 100644 --- a/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/project.pbxproj @@ -83,12 +83,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0800; + LastSwiftMigration = 0820; }; }; }; @@ -146,8 +146,10 @@ 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 = "-"; @@ -190,8 +192,10 @@ 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 = "-"; @@ -210,6 +214,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; diff --git a/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Rootish Array Stack/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ + + + + + + + + + + + + + + + + + + From 3a44c0b3c948f43856f0135167934d6ccc6c3077 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Mon, 19 Dec 2016 11:27:18 -0500 Subject: [PATCH 0054/1039] Added tests --- .../Tests/RootishArrayStackTests.swift | 382 ++++++++---------- .../contents.xcworkspacedata | 4 +- 2 files changed, 170 insertions(+), 216 deletions(-) diff --git a/Rootish Array Stack/Tests/RootishArrayStackTests.swift b/Rootish Array Stack/Tests/RootishArrayStackTests.swift index 8292f3d30..f73857d0f 100755 --- a/Rootish Array Stack/Tests/RootishArrayStackTests.swift +++ b/Rootish Array Stack/Tests/RootishArrayStackTests.swift @@ -1,10 +1,22 @@ import XCTest +fileprivate extension RootishArrayStack { + func equal(toArray array: Array) -> Bool{ + for index in 0.. RootishArrayStack { + private func buildList(withNumbers numbers: [Int]? = nil) -> RootishArrayStack { var list = RootishArrayStack() + if let numbers = numbers { for number in numbers { list.append(element: number) @@ -14,242 +26,184 @@ class RootishArrayStackTests: XCTestCase { } 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 list = buildList(withNumbers: [1]) + 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 list = buildList(withNumbers: [1, 2]) + 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 testListWithTwoElements() { -// var list = RootishArrayStack() -// list.append(123) -// list.append(456) -// -// XCTAssertEqual(list.count, 2) -// -// XCTAssertNotNil(list.first) -// XCTAssertEqual(list.first!.value, 123) -// -// XCTAssertNotNil(list.last) -// XCTAssertEqual(list.last!.value, 456) -// -// XCTAssertTrue(list.first !== list.last) -// -// XCTAssertNil(list.first!.previous) -// XCTAssertTrue(list.first!.next === list.last) -// XCTAssertTrue(list.last!.previous === list.first) -// XCTAssertNil(list.last!.next) -// } -// -// func testListWithThreeElements() { -// var list = RootishArrayStack() -// list.append(123) -// list.append(456) -// list.append(789) -// -// XCTAssertEqual(list.count, 3) -// -// XCTAssertNotNil(list.first) -// XCTAssertEqual(list.first!.value, 123) -// -// let second = list.first!.next -// XCTAssertNotNil(second) -// XCTAssertEqual(second!.value, 456) -// -// XCTAssertNotNil(list.last) -// XCTAssertEqual(list.last!.value, 789) -// -// XCTAssertNil(list.first!.previous) -// XCTAssertTrue(list.first!.next === second) -// XCTAssertTrue(second!.previous === list.first) -// XCTAssertTrue(second!.next === list.last) -// XCTAssertTrue(list.last!.previous === second) -// XCTAssertNil(list.last!.next) -// } -// -// func testNodeAtIndexInEmptyList() { -// var list = RootishArrayStack() -// let node = list.node(atIndex: 0) -// XCTAssertNil(node) -// } -// -// func testNodeAtIndexInListWithOneElement() { -// let list = RootishArrayStack() -// list.append(123) -// -// let node = list.node(atIndex: 0) -// XCTAssertNotNil(node) -// XCTAssertEqual(node!.value, 123) -// XCTAssertTrue(node === list.first) -// } -// -// func testNodeAtIndex() { -// let list = buildList() -// -// let nodeCount = list.count -// XCTAssertEqual(nodeCount, numbers.count) -// -// XCTAssertNil(list.node(atIndex: -1)) -// XCTAssertNil(list.node(atIndex: nodeCount)) -// -// let first = list.node(atIndex: 0) -// XCTAssertNotNil(first) -// XCTAssertTrue(first === list.first) -// XCTAssertEqual(first!.value, numbers[0]) -// -// let last = list.node(atIndex: nodeCount - 1) -// XCTAssertNotNil(last) -// XCTAssertTrue(last === list.last) -// XCTAssertEqual(last!.value, numbers[nodeCount - 1]) -// -// for i in 0..() -// list.insert(123, atIndex: 0) -// -// XCTAssertFalse(list.isEmpty) -// XCTAssertEqual(list.count, 1) -// -// let node = list.node(atIndex: 0) -// XCTAssertNotNil(node) -// XCTAssertEqual(node!.value, 123) -// } -// -// func testInsertAtIndex() { -// let list = buildList() -// let prev = list.node(atIndex: 2) -// let next = list.node(atIndex: 3) -// let nodeCount = list.count -// -// list.insert(444, atIndex: 3) -// -// let node = list.node(atIndex: 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 testRemoveAtIndexOnListWithOneElement() { -// let list = LinkedList() -// list.append(123) -// -// let value = list.remove(atIndex: 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(atIndex: 2) -// let next = list.node(atIndex: 3) -// let nodeCount = list.count -// -// list.insert(444, atIndex: 3) -// -// let value = list.remove(atIndex: 3) -// XCTAssertEqual(value, 444) -// -// let node = list.node(atIndex: 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.first -// let last = list.last -// let nodeCount = list.count -// -// list.reverse() -// -// XCTAssertTrue(first === list.last) -// XCTAssertTrue(last === list.first) -// XCTAssertEqual(nodeCount, list.count) -// } + 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)) + } } diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 2cea625d1..194c0ae79 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1543,10 +1543,10 @@ location = "group:Info.plist"> + location = "group:RootishArrayStackTests.swift"> + location = "group:RootishArrayStack.swift"> From 3b5a508c8d16bbbfbff3ea5b1028b286464d22d5 Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Tue, 20 Dec 2016 20:46:30 -0500 Subject: [PATCH 0055/1039] Added Rootish Array Stack to Readme --- README.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.markdown b/README.markdown index 4c812b0f3..d4637f7c0 100644 --- a/README.markdown +++ b/README.markdown @@ -130,6 +130,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Bit Set](Bit Set/). A fixed-size sequence of *n* bits. - [Fixed Size Array](Fixed Size Array/). 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 Array/). An array that is always sorted. +- [Rootish Array Stack](Rootish Array Stack/). A space and time efficient variation on Swift arrays. ### Queues @@ -205,6 +206,7 @@ The following books are available for free online: - [Algorithms, Etc.](http://jeffe.cs.illinois.edu/teaching/algorithms/) by Erickson - [Algorithms + Data Structures = Programs](http://www.ethoberon.ethz.ch/WirthPubl/AD.pdf) by Wirth - Algorithms and Data Structures: The Basic Toolbox by Mehlhorn and Sanders +- [Open Data Structures](http://opendatastructures.org) by Pat Morin - [Wikibooks: Algorithms and Implementations](https://en.wikibooks.org/wiki/Algorithm_Implementation) Other algorithm repositories: From 0ffeb21dc6ec1e2a2146a43800b3c058c403a435 Mon Sep 17 00:00:00 2001 From: Stefan Cimander Date: Wed, 21 Dec 2016 18:20:18 +0100 Subject: [PATCH 0056/1039] Fix typo in ReadMe --- Trie/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 172ff4750..7caa927a7 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -36,7 +36,7 @@ func contains(word: String) -> Bool { // 3 while currentIndex < characters.count, - let child = currentNode.children[character[currentIndex]] { + let child = currentNode.children[characters[currentIndex]] { currentNode = child currentIndex += 1 From 22675cf8d18407a6618909a0d3bb916dbe69762f Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:03:18 +0100 Subject: [PATCH 0057/1039] Add new images; --- AVL Tree/Images/Rotation.jpg | Bin 35153 -> 0 bytes AVL Tree/Images/RotationStep0.jpg | Bin 0 -> 22802 bytes AVL Tree/Images/RotationStep1.jpg | Bin 0 -> 18406 bytes AVL Tree/Images/RotationStep2.jpg | Bin 0 -> 18836 bytes AVL Tree/Images/RotationStep3.jpg | Bin 0 -> 18108 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 AVL Tree/Images/Rotation.jpg create mode 100644 AVL Tree/Images/RotationStep0.jpg create mode 100644 AVL Tree/Images/RotationStep1.jpg create mode 100644 AVL Tree/Images/RotationStep2.jpg create mode 100644 AVL Tree/Images/RotationStep3.jpg diff --git a/AVL Tree/Images/Rotation.jpg b/AVL Tree/Images/Rotation.jpg deleted file mode 100644 index 94a55df4e3268d5e9f8ed5b63a443beb9d6dda6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35153 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

Fbwd9 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 literal 0 HcmV?d00001 diff --git a/AVL Tree/Images/RotationStep1.jpg b/AVL Tree/Images/RotationStep1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dbfcc04d60e0e87a37ae6d730d4141103e91bcab GIT binary patch literal 18406 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 literal 0 HcmV?d00001 diff --git a/AVL Tree/Images/RotationStep2.jpg b/AVL Tree/Images/RotationStep2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..df194a73889e33fca6d9d4ccfbb50eb97022864e GIT binary patch literal 18836 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 literal 0 HcmV?d00001 diff --git a/AVL Tree/Images/RotationStep3.jpg b/AVL Tree/Images/RotationStep3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ae67f4d746250063a37830f3ffafcbc1e00378a9 GIT binary patch literal 18108 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 literal 0 HcmV?d00001 From 5cc12cd45f6a386788d9cb98065953c448130e19 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:08:24 +0100 Subject: [PATCH 0058/1039] Update images; --- AVL Tree/Images/RotationStep0.jpg | Bin 22802 -> 9159 bytes AVL Tree/Images/RotationStep1.jpg | Bin 18406 -> 8046 bytes AVL Tree/Images/RotationStep2.jpg | Bin 18836 -> 8277 bytes AVL Tree/Images/RotationStep3.jpg | Bin 18108 -> 7430 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/AVL Tree/Images/RotationStep0.jpg b/AVL Tree/Images/RotationStep0.jpg index 156b18062e84cd5bd05a5557c80404ee6aa9636f..99b69d3e0f58e0faf7d98ecd0a0daf30e2e48640 100644 GIT binary patch delta 8428 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 WpZCcByi4ZzU1G{1urQsc&HWdo$nTl} literal 22802 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 diff --git a/AVL Tree/Images/RotationStep1.jpg b/AVL Tree/Images/RotationStep1.jpg index dbfcc04d60e0e87a37ae6d730d4141103e91bcab..670fa0832039799d8b90d8e530a1de409bef4871 100644 GIT binary patch delta 7288 zcmZ9QXE@t^`1WH}Yg1cEYuBvSC?c^(-HNvMtWm3|z5P_Jn#GNl60@xusa?ASF>4o5 zLTJ@ajEIJK+%KNvdH(+w=lA_}9mn}S&+GF$gJKW*#)JvfSWE??27y2nmwKCNuSE@d z3u>&ZFrWk&F3=zbDhd!KD-|mU20HgU|J=Ru71lTx1NcZg5FCkoxQKo(v`-!))VJ63 z&|NafFW|H7&+$sneF`H@g+PF5@x09V5qqn%d^@XV%Osrp0_4d|6wlikzW~u(A*$h8 z`k`{T#0-cszM;Pb9VkFOEw8+DT*!k&rKZ&y-Un?PnM+%*HcG!_zF_Hc_RFWgUtCer-&K8t4tSJ;CM@?G6ohOtANjC$* zc%1>K7K-1Z9;}Pppz|eKA^ApzwR~|_+)2i6CuyE?xP?6uzN!h)#IZin)(c^Kmu(;D%erJVWQ&!q_-U)pHss?jGrI9%F zqVZH?l!{$MACSL}@Galu+^ZW35O$Q$G7yUVVxwLzfB5AV1s&BOe&CG3ffjm?_?;EN zYhn4xh4%_E3(K78^nCaIp&M{NhLdd8Wn;xVDERGrjb0BMOY`mYbL5v64ywpw;HH7r zwXetHH$tnoRH6&9X)w!V?k2A!POP}ho>jhh)=zqQAbr@q)Jy#U^#af7_9z5C^Y1U6 z$kqVd$l5q^9@Yfq3H0*L;D*p_^!2kRlhKmI zV7o`X=qN>U@9IvF+FhK)lBK;iMX0EmR4aP;&mU`LXO}ERmmsH)rXzj>*91y**v(yO z*iF@G=>B^y1-_WbzQfN6h|50`NMxrtWbXBH!2<&qpd<&jCh)RhgE8m?w^ASyYe-IvT+OGt z>3J0Vt*W-a0TN)j!-rTDiv>L4%wBCyr+%Sph8@!i9QM>LD$f?Hc=X8!nkRnQGYRSs zS^bXwP=twg3F6`X8B`9@^UJ)r+J-QKp#y`}5|Yr$kvn-jX8M%#2iODkZ;R%rp;*>v z?Y4Xb6`PKBMTmcORJV?(-UI75bmFBk|5vc=8+42S#MD3?46%uxg;Ug?Ie!Yhq89bo zY+A;p@oTzG#9I?XhDwGW(Oi*avjhXyXYNb6f+HQZI^jVlefxsKpURLAIfy*7?0&^-+pI?(;2o? zD18lRBuiR^&gg&o{2e6I7vnW_MoYR%{%&#ikM}Awhwb+55(7RvY=q>HEOab_u&9&& zl-`i}&8pxi<8=c{;YXaNHt2$_(S0cD4|6QUZx#F+$~N5*wxXtsv6yUfXWROIFx&TL zjNz5UAo3IJE#wC8R@E4k>FnM#nept-L^KDm$@R#7ffzn4Ngwt>KT9`(qFxQlp03uT zP94veG_;--B~zD!C@H1Wn)(-a&$K;WbBd+dP51~DK1H?G&2c7+y8xjODSwa9qjQQG ztMp!yc0!Np0EsQ6XHq97L^xxCMxl zpUea<_EaqCgI30z18XRis`LWQ()G2uO{b#2w;#hOjMm;I2;B26^U$tTSQqNcsgxtDWtOFuG&bxuzPr4&(3h#-I$)M36nhmA`gHSEEMuUy zi&NJ#yju^Ph4{Fy15v;zuRL6emIk4AeNuSXO~sYrt|4_A zj*)GsBF;BarmP;%Sp&E}mGAafEl9#X8$U6dzfQC;ypcJ^J3>#Z%frB=L0fVq2CTzw zLVGbqCX1IQgZ`7`Ao=c@Vcse{!LfC6r@N_X*M3ueiSHrvuk+f!j-$y_j;DUQNr%Rw zOoPtBbbU0?R);&pm^5cX7jC&Qk|I$T*ZeW+`Nz)wv84*2T_1){7jYSXDtBDWa2-dr z`qu-4DasL0%T~|- z^F)U?Vjf6jll=97^^MjGJ?q0l7!rP^gZVPbuj3xRCdr~btZnn4+;bxMnh!B=kX{6Z z2;-efU#DiuTQIb>Sxc~hvsgZb1e3}wo%@*D?w8q>H5pY99<1z*Ga+K4GcE#aUnbgK zwjHa3TW)>9ZYMt>WGGq?{Y1jxe!R6!*sMmrJdo*PDjf0q?|X~U?xqe?B<|r_->0(O ze5Q&D&s^`Hw$_+$f4InP3~bvG+wV-@P?tPuTM>XTFLlX z2Sx?mb7~;*-r`G zO<)~oe4R@=7cr&MJ$Ss&;I3H2h1*R`XvA?csw_*of7{8tsdG*f$Zl#~;p!50Ec#3A zwoh-e_y=`U9d?R!40{(-s13Hp_Oa5GVOWP zDYc&_pCF84Z8U^G!EgX3He{_%E``6~q^Me-PwyOAUerJs0Xo5?p4|sE0T1FJ^O6&D13gU-d!bK`OZ&knMVuo(w~ch20T4aC8(}PN^>DI zuAD^^U*Z=Bz}yfHp9Czk!V0w(eI=`%L5sYsTsp3@$n9 z!=ia}iNkz=_h>DFa_A7TY)zt0^&UngyLGIS0AO7kGh|H86{H^mhklpI;3# z$6uk-)ms4P#`AppWJ{EA(%PP#U42t0A_)2%3DuycnmzXBTh&8lBu*}D{|I+Tg-F-* zbM&GD*p&!ermilp3HL+GZDWRCgn`mMFid2&GYO(j#YpLy1nztGYJ~Dn$Qutu6D#eV z`wT;rf?2fwlBlQWd4T}6>jlVd*N3!vz@lX70gNyXv8P zduU!xyoZPPIWB~5W21|oTRvT#l=2R273QC*3Y$_sN{>w&q(dXC|}G#1Xub zA@TaE8yBZF<9SgNwjd6vTj6Z~2j?GJQSuCYd+#k? zhK2&YIwbYbL_0@oFtf*xd~Iz)(RxAq`zU9{1)*vFDhz)POZ$7!U9WGKvxbr}D-m%1 zp=`0_W64fi<*f-r(Gjf+P)uDf?HAy<+S5xM^*j8nY;e4F#xN|Rdp-ZO==`#?qH@_y zbwK~=7ARF9=fHR8yn6BMZdV?`3a@ouMAEc!#U1LuXiJFiR{YHt>LF#8`vWU?DBAZX zCR;SR0ii}r!?pLoI07vjjd`sK;+x<3c)KMVNbh;OscVjV`_T(eJSYa<2q>BNNEkfQ z038C!-SxoEFFdl(B(xoicy)B{^(2>!D*Pn4+ube z0eS{cuuwApVio$h_pd?zYDsgd4yD@Ym}IrdfO3{cxvEf_AtarHy$*!CjZ0Y@NQd^X z!jmoh(T>#Qxv3q555N+BZI!d2ZhkNwvn&->129I9TR#yHZNOvtmb^^y&8;6{1+LJ~ zlhRH9#&O7cxO(4EoE(Z(f0wxd%3)i{wAdB#vH2ro7BT+|%6cZ$g!g&(Ir1T~zqtRr z1-qniY+Scg+Stt5^~C%~Fk*;OyE#_zJ*9f#Iw&(X%9+d#0KKrkoYk=X`3n%;ajH}D zOZdgie`d>kO_dC)0;1e17K|!A?}>DFw#jFWNK$L-@H~5VpF*8S7)KL{g?a8L&KN>Is=+1fLQANeV;{Mo4cBVS(D% z*2f!$hD7$Ff86<^{*l&c|LJelY&h+iI0j8x<;Zv~U%86sN>q>|6hi;bcihvE|7TFN zCGVPA%?z6)Lt0kfmPQY?8Sqj-67Lg)h=a4qq?cg9v}5eD(Zj4weDra$u91T=5<`Mj zK>vM{stx3AvnLXi?jCT>Ngei>-yP1YFs9J`-nPWpGduS@w0$KNddX&}uwF+n$91sh zhQQUEuLf@>pQiMHd5`vAakl04BG9r93EwY3Nc{}gsx3AtV3F50tscE9b$!NjwpWBYsCVKOJMS(6mYWj>K>_!o=2znl+u^Pz28g#^43YPcsm`|6x*|T+avY(&F0B5R9qzjU zo8Nz&kUtEx%gYXLL`H}LPl7~rK8}9Rs8KSUuR#FQxXrEcl1~VEq6VIA5!-^SQ9_y6 zsHL{JSC5mzRf6od0*4+ z#0bD%Hs`jerwl6C`KwMupP=W=+qtMo?|=}cuQ!hn;~D6dKD}?9QZ=T_cm8DIlCD3d}mH*B>p}YO`c;GeB4|DM_%oE`E@&tT~BBHbyw7BG2=* zKzjx*|2`$|d38h$yQzukVaRSg`xJSk2x2)~cqJup`tyPHl1bwV#n7n603iA2?Xy@f zm!jDmY!E|gIfq0ziyk-XLCT})>YylLOi@gEa{NX`AVCGJ;lHhwMavTVA_#mey}qw(`=C#eDLRH{R#X;d?u zq1zKke?zRoqLQQeL`&8r0k08n*hAcwr{dfj;OVAcLC)7agHEx40X$1q45Yh_$>4mo zzBPgHU3Jm9O*zNz8Z}!r1uZRg6tiG;Rh78wx`0mPG#YC?Y+ zdXx#jk7{@nq-t{Ww6u9Je>KL;q+s1>+kB&;u2B5`PltuPll+i0J)d1*ZNQg%TX!a- zP1E?-cZ zf_i}6rBLzOG)p<`Uk=4PEJ&82X*%SzRYqF%W}ip=Zf3b&Q>tNg^NR-5Zv4TvhOd53 z&;V%4zlW&s+B}kCsJ~k}z#%zaV|4xLZXh>Z%>u*K+akc?U9`3?_ch_nhfnWMcb#Wm zmJijcf$n--O>K^341Z%@-am(OOa0lsHwYsxb19+V0RdSe{~DN;xJ@XZ%zg;(=c=wH6wJ}+3XIJXW>6NgG;2b51x#hYqflTErVS|6%sn)?@@~8kE z4)N0U2N?i`hNB+fgA@HY8$SHhe(BcM-o!}G@bh2DS!;_gZwe4j_@c{e@F9|omHj;>imqC3`0_7pgrm#UyYT#|ScqJiyFKrZCS?V0 zD9T~RMd?RIFx66-mNNrR(8#ZAMZDENLo!w_1_Z^Gc3E~3xAF9=$tm4vuHL#$6_pi3 zgnNs3rN@so(n&JTX30kHd^7UhtyGsGLGdLAWAqXlW1|=0Dmcb4D4ec+D<>zxEGIz& zp!UDItgqecP4GJ{ zX~s=iqg#g>np@ji8vaJ*-p*p|-Z>2=ApCG4u@FAoiB<+ufO_irk)0x&mGpDR^koj| znYdJm^^^NUYF?H952w+IXLsr`0kDfX@-&pfgV4=(rc+Ix3SXA-QBW=Dl+_f=X`Fn% z;m$QQ4#F7G+dWvLnJv*BjF)>!a*Uq0Hr~l8|D$xG!huTqFzfRycaPr6T&aGtn#Hhk zD<$@4LLN=hoLnNS>5g@-;ybOfvdU$Y(f6S1t31_ z*GweiV9A)eyyR~8eY9jhjHOE~G|vKuNfewA#5E`S7TbNx2yzZ(_}jiLMVO{J{B_`D z_K0ba>iVIhw^r6k(Lj)L&E8&g;+XFTuQnUxi%ff~Wo@&Z*dg{h{jWD)<+!>+Qdu-EP6aGjG*i>=a3Jxj$cx&y+1my52yw{HY0#qS}0XQucrs*-2#gXfSqe96rIrch{=D*;bc1U>0D~0{U z6CRs=24c2VBhdP|XE7i``n=)N{YKtCCE3twub#&}-HjVNoA?MUI0;H0YG{n#NFWP( z`VnLA|DJtp*gCCXTxYXjtEW`JP$gYm`s23Q8q`TH=wRMkp@REkMCPNvmL$nl<8)Ud z0=H;@|6WnDCBR?sq=n76!gJzODL2cd`i&9K;P4kA;Dw0Yi{S@f#8BjG^BTB3tZx$F zRtULzBpG3;fMM#rmtvz@DV(r10MoCj6~eF`>F=?LPzaf*>8(V^<6%e`-H|tV?O_8` zH?}dZt1`lyJ9%kOBsepR2K{k3$9Ev*V;o#{LE^m8uf|j#-!E-TGSTuhMXAweq+0z@uU9+;<# zVevzy=!Z-cf*5VUN%1M^iLjD+wlZsf6uYAysaLS*X5HZA+qF!0Lz2rG^`z-dV*F?0 zmF+2z7mNjM>oJwE_xYIy`_ChH;Y?;+-Ho{!e}H+$;_!0&GzAx+taq#XCr;!*3KGw! z$S^#t44Ub;9IzY4(4qs+v+T7N4q|Vl6+9Ei_1B~(+ z@zIQlz4^9>_WCZlTL*;ogs+_)Ujsz?XLgFIgzMS*#OcbezBDz{drKa~9QX)uU4Re{ z=kKaET}X`-hlzdgM6&Wk$BS-WGJUlYFVdz0_)u5&6PA6Y&g0s%l;<5uvfd}%nUa+0 z)su$tw}q7-N6*8l1KBOR#Fp%c0w-l?V)B$18}|z{F;_2-0U&wV!-U}MV5;=D$6*|E z#@RxKb|{gt7ob1h>fovnOrw1Xo^ECnXs}NSz)Ft9OXN45cMz=kYeTOa2HYJu(FoU1 zs_sig{d$%Jz7xLDYn;H@O%J&zntL*}h5k_T;^c4b#}|}iQBikHg-5FnN_WlD#piw{ j3+vDQGPS26(E>v?f53Z6M~H?`*?Jbu literal 18406 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 diff --git a/AVL Tree/Images/RotationStep2.jpg b/AVL Tree/Images/RotationStep2.jpg index df194a73889e33fca6d9d4ccfbb50eb97022864e..9d1ab5b8e6e65d0b7fac22c72226242d6e7e2a29 100644 GIT binary patch delta 7538 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 literal 18836 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 diff --git a/AVL Tree/Images/RotationStep3.jpg b/AVL Tree/Images/RotationStep3.jpg index ae67f4d746250063a37830f3ffafcbc1e00378a9..50cedf0c39651abfa38991c499ba5ba136e09c8b 100644 GIT binary patch delta 6740 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 From 2f8f348816ee0b9ef8bf52a23cc60883a7486e79 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:13:05 +0100 Subject: [PATCH 0059/1039] Update readme; --- AVL Tree/README.markdown | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index bcbbbabbc..9deea5649 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -45,20 +45,21 @@ If after an insertion or deletion the balance factor becomes greater than 1, the ## 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. -Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation : -![Rotation](Images/Rotation.jpg) +Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: +![Rotation0](Images/RotationStep0.jpg) -Let's dig into rotation algorithm in detail using the terminology: +For the rotation we're using the terminology: * *Root* - the parent not 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 +![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) + The steps of rotation on the example image could be described by following: -* Select the *Pivot* as `D` and hence the *Root* as `F`; -* Assign the *RotationSubtree* as a new *OppositeSubtree* for the *Root*; -* Assign the *Root* as a new *RotationSubtree* for the *Pivot*; -* Check the final result +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: ``` From 341c504c3508ef0ffd3dd111c06e4eb128106d46 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:14:46 +0100 Subject: [PATCH 0060/1039] Update readme; --- AVL Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 9deea5649..25073f260 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -45,7 +45,7 @@ If after an insertion or deletion the balance factor becomes greater than 1, the ## 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. -Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: +Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: From 047de8fdfe7221aaca2d0ad3a39be58ed5e11f25 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:20:47 +0100 Subject: [PATCH 0061/1039] Update readme; --- AVL Tree/Images/RotationStep0.jpg | Bin 9159 -> 22246 bytes AVL Tree/Images/RotationStep1.jpg | Bin 8046 -> 18235 bytes AVL Tree/Images/RotationStep2.jpg | Bin 8277 -> 18777 bytes AVL Tree/Images/RotationStep3.jpg | Bin 7430 -> 18265 bytes AVL Tree/README.markdown | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) diff --git a/AVL Tree/Images/RotationStep0.jpg b/AVL Tree/Images/RotationStep0.jpg index 99b69d3e0f58e0faf7d98ecd0a0daf30e2e48640..f61f8804ad0b12f66f87c45105315436f5ed30a9 100644 GIT binary patch literal 22246 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 CWqJ4j delta 8410 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 W6SwN}G7+K#nPb82RbGfv3o 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 UUi+Wt$^Sf4K8UF|)9;v2$>8 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 diff --git a/AVL Tree/Images/RotationStep2.jpg b/AVL Tree/Images/RotationStep2.jpg index 9d1ab5b8e6e65d0b7fac22c72226242d6e7e2a29..64c0af8622988f3bfbc4967344012eaba5379a12 100644 GIT binary patch literal 18777 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 X%fCkL#lDgaX&ejdN;jaq{QsK(NVo;U delta 7547 zcmZ{IWn9zW-~LcSrID^FDJ@FJ2GU;yM5HB@94RHu2T{7=3kWD3(h_5oAYIZ(jNB;c z4RDMaH@|b<0IwvlM1eTFEy)V*rE2D!S20T?4NC}a?ZCF>-} z)#Jl!l6^1)YU-u!mXZ%B)3tOHxY0~WGaxlp{VJ}u^lFRxS2ZLO zkGKXAFI_csz^*|^^PdFqs}jN!zd!>#3^UdL9e=1ac>+)bf3$$P*ktc(?vth2@b_N$HOK@a8e|@cf;Z+C zJDz*DoJIqZgO)2=lOjttDVv%d?zYdY$QcExHG)p7W^TJ}WUP7O@i4lNt{5zpK^I;|PTjcg6<%b(a^@s5I7+)jYqs$t9bwy0Z}=jEne@U)5X2G71h9+!cgUfsgbjFIYDS@5HIZ3q9S zB0mZjEHb=!#INQ!LdTd#0?E2Z0(J1fg(iL&#aZS-{}f*j3}fAr*<@BEoQWA(KRGrJ zKGvpqiQo`bCSKh?0mng!z1`!?`oko@8l4A9W1vxQuna9fX`(kHkmxxz(bae1ZY&9l z>>oy-n!Wh)s(P?W_jRKN?}gybX$TiS(4+dbUw04WX+q#2qkJyipX~yR9&STYNjRfi zAoKAtnPY+$AoG^=w$FtvMsME$weS1fN>q#;=9^_-Q1LT;>-mC@jR1IA)AHa+K+?e7 zE>Xx=kQmQwkL6Q*?W*(P0$aBw!;Cv*&>0mg-xM;-RfmK$mkV|(*Kx7+a8&w zE!ihpztt@JxB9>^5%H&JU|aj;f1h=L?0SMgcvKJr`d?7c*HQv2n1}q%C91x(`Q}He z7;IoTC2HHylwcnC`Gqz`8AT^wI&X|&gchy6<5D`;a9g!nfX`{qVWgbvv=kGPkWJa! zpShuW`XZX=sK9jnPBB7UGt<_ZsEejQ?Cx0>Fc-PXms{<$44Llf*Ps3iV9{)?yP1X< zwIK`1f@tL!A!EO3&2QzSAkm&s=fO*|i#vo-<0pSyQPd2tcLnmb*euY2LW5$EkwDyn zTGktKZR#Wx*DuQZTDN#!GU}Tnvv+|qkAef;-=Lor*jaagiV+Ca<lk?5Qc50mzMMRfFU7r{}Rm<^$4OmMKpba zVy6;uI9t@nQ zAk?Jt$M31LTzB2Wf@8M6_#&^?KIBYcHMg`eJjKS{dL=%N5s#}W6*B2mGvntI zx-U27l|6gDFmUE}w1q3hC$mhtR(juzN>GO|V&Ai+v78BLLLf}iNBOxAhK1|PbDoP> zX5YtY;-U$JBE5^oI`2j$PM(kV_lED(O_j~dov!b=e- z^|U+mo&d``^F7I$&3%R$++laPzdiUEM(M3;`?lR4>(H4?gE#0w86gi1mlw>S0dd+O2;qtib>>h zA_2IVh%dYFN0@ES(g4JwM;HrzAhkNwKBz>(01WR!q%iK0qJ?!>#wxov5*?oM*->cw zu~Wmj`*>q*_T&-PVRABc778k5vV77|@QqKAT~Gc$$_fn-o?L2YpmHOunT~N~F_YG39_mrYdVEv^Ht+BCkU*NP9^*sfZE)?F<*z|RK%_dRu{7AF z^hfW=QgN#$6q&$lJN8EWZyv>c%x%;;Yz31;_}vm-8YijNJqD?VOE^o}eBem?^lN5Z zy(ru`N$cGu3$It4y9S00XMoSOmUO55BS%lrT3{^Bk8(Z8doy<6?n2?E+FdjFKoSkc zydu}(yawS+6Z(5-RTSfZWf4ruYYorx@iy0*xkx&pjels9RNiTr9e;&(=aRNjUxP^K zFuKtfVn~?T>kJ6sMxw66F^%mVFQ!la$K@0-mh{&{qHYX$TMiINut z(wAipHalaaeu@3iJM9nWgE;XS-v(ONMp82C4URR%v!>L6uziLa7CwXPaBK*q_M3kbZY$Y2qv(0Wre4wDk`q4jc zN6x6sex*lL#C_G9{2F9IY6B@>_bvW?8We<8U8Zl4#TdoDvzcBeaJ)R=+Z?%bF*E-7 z8l=S?&F&BNu_H?WD$k6vb8^VHab?CMSDUj0DC>I?*R0VJ;NN930f@HzPT= z3jaM3DyMJ8uKa&u6j^G}OS~+~Jto=Aa%B*bQMIj>`+UY5N3$|FutxFr-w2AtP@V`i zKRW<)mo`FZ6HKyv8G^@_@2pS<8CP@{;~lyXN81_ags>xX3w#)wrgaTLCQ_6{M5nlVdQ~pm}X=_+*ED$E_mjEyeWi?=Sa9aL@$)t&%9?aZ@Zmi`XK*<#1i@5`?>`!7_M-`Jh(_3kQ^S( zQ>aO!zWC0xcZlad?156>MCud;ZnPEoVA*hKPey<@b){u*nI*$i^=AFAj3gqCpI2jp zj|RPwCiQf>e;*xHWcC%$pNMtUM6){dS`nM!yLA!iLmDvGgT2y)t@&kh&GE$rordI1 z6~QNTMHM!lDMk1HWGCidgP`$12qj_O3hvumGp~nB!h%1w(;_qX;A_rR79={IqDAnS z`F>q;-a6U8!g>Z)H>2A<4RxkICzHN9zXt6Zkw#um{WmSz1QOF*IzGY=sR-j{l$D4T zOiXaef>9$vh3DwcEc&VUctO~tmb);`>rXFCC;3%L<^i=}aVznlcUVru8koi`WYmh< zZKHnrZxdvya))utCCf6#q@O2h?ZCpK4*sLY2jbEVQ6|3q`>!h-N~1q9a$4dKfvNwDhJ_Seo^99Ec6swat?t{lIQ{@#hgZ zOWkI~G<$Wd&z+XK7QcmlpXZ`SO%-Y5Ts-*Tpz2-7l-w<73|Vx)J^caW%vKg*JQoRW z(2H{c?4glaAI%rGGjMV@*39{bQ1&_sG68#<^Mi17VvIo}4(l5&$u^LU zm=|7zrP~5^IGo4eUr!CQ>EpzbZ~r$%-t5nam=%TASLQEF5qP^`vAue9dMe>k;;77X=IQo4_2|gC(vLt*7=cn$yH#1&VM@bKfKp3-#9tH^0{SI~bd)xetL zn(^cq`94gLD7N?S(XJI8cwF>v4Vw?<6qnHKO9L@~T^FwH=Nr_8oO%3Rsg&&P;hRnQ)LgR5M=Qt+ z6hmUPL>UUp6e%f=`wBUqYkR6J@qB;}0c6}&teU11qKHrF*-`E!HUvI!3Sr%RYCh%C zi6-Qu!DJ)!Vj)Aca5nN!Vs=3Tp@M^46}>VqDz>@>3||S}a)jkRn^2<<6-vU6C0;UM zrn)EnD*BOCjmf2bofM}p?@YG_&&?{d)}r*4?G->e&iGi1$u_Y(OMJFv=1mv|{_wOk zXSVOX>ndIvtNX??I|3#NBJy2}9d<{mpqI+Bdjcvg->2Gn9BbrlA5)Gm{EQULc&P!e z;RnkPJb%+x6t6@g#vC&J9s!~G?SKzN)i79EWXlpdeXc=wa3$&c?`$Ai534TMSc02v zqnp<4TixeVd#ot<@!Exc&JN&U8p7e&&uGD5PeU=gNuU!?Jsk?g2Y z1Xg2z>_XO0qwjpSJMiMlY}XjGKV-V2zm24-{nqa;-_6n0b38vkLUj!iG+7}UB#Llu z#=|i&;HY$52Q36V+QJ{-Fwi!_ZG2~_haEb1Xb_P#1hh(s4Q&Ml^2xpODO0ZM$qEFk z=v%@tAJM#sUiU~d_k_I0Ko+-&wU+vSH?_@M{aMK?9Js^A_1KeBWOzMgB)5IIQ{Sl5 z1JLW=1cCsi2tCm;*NhLd(iN>^)FX?8%j~l4$rViKCqfKN$+%#)EamGt>2Zg>D z5|__@U%LCd-!wtgLHaW7(wC^T*NkL(U0YjY`p~gaL&l376S#SWX@@`Y>BUG-a#9}CP=UZJD}yP(cjUr$ zmu_y$7D6$Va*~j}J}pN14T3WAI&lv;3=s7yJDvGPIHhh4s zurZ26ER-j$IK$~ITXi~D;!7;>$)z%|ieCSP{;}_VIQ=AHI7h+c_gB(b@2T=5v!xde zt3-ppl>3DKe6|mBw$1sShW4R|D`F4~pwVFN|0nk4RHaX_Trj^uxTr{Vp`(3_5(}p^ ziKz)^{)Y!KXJFJ=LjT@{V(w2Mo=JVOYd*X*!snu~w>saE^g%<@*LD*)aEFPOAt|w; zJo>G0pK9Fg^MoyCIN4@J+jl9GPHj1 zd-Y*yQbH9vTBx+HP<71_xKa59n-306^BJdE zzVUARz*?U>^RD`IV#_nVjZx!;eJ!crV=L`hGE6_}AQn^cQ_iaUkUEp6aq1!MSv|+( z*hAip93z5&eR7r-8~$tbp~Z%^BfY*F=zjuG0|D1FH{xIO%>;05AxRRq5P+v+vD(uWFv+4j{n0 z@C2!<&U}|AS@(_1RQpx(HON7}qOYS4Q&pWN6w1+%k@5Uke5p6Jiyb#?I~(fR9iB#R(UZz?hzf_$j=@!YaMJzFWLk@ncO${-Md;7xQ&q)1?-=|3n&Mwz} z_ogbM@gMl(czYcTCj8>OhpG8s2h0#aegXaeVBbf2FxHnWs(x^2X@ye~5-Wy(Q7Z}F)X_PllkE@uEavwlV;v9jm!(>wnRq#X2vu2QgQ4$&{tPN; zy`IAx(-=4C;S_InOhMbi;fM&SoSlQ6=V$M6-_=>QN`mNU>A&3SzgMXN3_-~oa*>5f z?O2ZfFa_~KM@!ZjxU8frq~B`VR(dA!{q3bf6&nf+mySpK>Z4}QM4>S8P!I%D&~EYr zzl$YD#l&_XnYwDX<>XeiYa9`-Ww4pGi_;j4`I5QD)pk(k!#LYPu18B&ddMZ@in&Ih z9oGoO08fJI!?d&r!!#g5nb`Brt`eh=nAwB`KnpWwL9ESV+;Cinv%OEHj8qe~J@aKb09&bT0ef4eozh+|(Unni~zCB}_qxV7LytOSMYE zWWchho1}d953y(bX$=!DTaHYFW1tlsa*Kb~NPg$54}^<l;A5JdokARq@`2Dz>#t&z5_$6xsCYqD1Pn zcwPAsO<@X04^2L-+m2jt;_ssoT{ZJt-7EJ(#77u5Yf!csnlU(mpp`}w)1mS0Q#y8m z`&y2*EU%7umIinAFfLepBCZ&Vh!Tc4Tac?yN(iufONSrSY$hr`WoMG=pFNF~IsAf7 zg)uP!K3>u&^=xo2I0o_%e~2b#x?8kjiTCPuyezJQ$3?8XXo~Z`Z(*syC7D+11+0n4I zw~Y-%gQFnie%gB2tq1~_lLtObX7jg!cJq{^Uak53YYpjaiVBg+f*AqBHOO0WpQAZf z$ztZxz~q@@3B#g+4* zc3|T3TC$_|h3zHrg#H73c)8x{?j#6shSDHk!zLpR%I%fu7f&2{lBqGZ?6cFJ0QI!- z@y(-&d2#8XGgalFPML7##S(C-9!M#;Mbw^Owx6SpM7%Xn*a?|Fz3IE|D~y3aVpS ziQ;&%PPv3Q=m7DtGYK)>W@eHB9pYnR=3_eO0Z9SRJk0c0`|C2`hv^VA%VAbFc8(*Q zzzL1KphHZ|%!gQ*4KXd`}`EO(azyC(rKhebp&~=D~g_(uz z4_!=$!u}A>$8z|@8CHHnTedqv$7IevVn2Q$4gp{0Lx+G@#SAnSfCQi&WVU# z4uG5db%#TTSb#4F>tWWvANz0b9Lxf2DR_VbaWOLi%*4zG0)rTBnE4Vg(KhwT0f=}d zFiHp6k4hBPs$5WNOn%tk{V*W2uu45542h73EyjCi$(=XzaL@k22FfWVE-{XPiQNma zwBzo5c%oGS*Rp6mrIfG~Q>|xQDTCL?+x!g*87Jxsy3tHIpDws|>53p5xGP))pDxA; z#u%S9eH4rGJODlRMS4qklN0DD8j|X-zTr^iCn+;VyAysGALBLdUSLluh~0Tn6f<*e z@{V@Qcid)cvaENC*`zT}Y;%}xCAK$^qJwlGDqt2|+`Axk;GT9QVe6^-sf|FIQ|+6& z%XMi*S&<|h_O9$FL9RUut?eMlu=hGM^&$Mw0Vp~h@p<2L!-{&r*~Q>#`JiUiWHYHs zyGc9iJ4bbZyGfeh%G}5O5d1@e>+(%`wsosHC@azpRFMQ`hsBGWa-Xp8K3zq<`<{n5hl8bt?_Zt zzvxV~Itrv8B0=*dRrXmDEgdPfl{CvShK65GWZm!mYV4!x22TIG@;yQrKee}}EH`Ct zTz?XuNqZM1ZjT3ZAAs%#^260{(XK71sHlJs;oFT4mY@UapOFIxe^!MPqfhibb6oqZRIhJ;^2-e*< zCo&F4c#xFPPGW&a>Fxf(aV%P+B0t(cB=~r|&$w^OYR*^dX)%wMVoV)?8r3(>P)!+M z49-w|4YCPXE*Q4kRqg|c^(ibMz_#X`i{0qpwKD@OY5gini&rzVeekkoRW)yrR%k6m zAEX|+!3lkhgI^*3GMf{LvGhM1sYCu{@u8{drQiks^hN9Zxxo5QaTUbuGw+yHp0U@4 zQ6&&x>`}y>UP8lIe^(RsXdG(mYGj!#%S@%a8PC4tLDw#<4m+*KYUXvO=99T#dV9o zy|vysKXk1py@T8|ce1Xnp4anvS&I^GYPzj+Z~T0+wtMjTPX(i?6zxC;hdarV!Eues z=O@LD(1$p>z?S+RuA`+V{MY3)oNlo;$KW`PbD2DY&B6v{l3Twkl}s=rVu z;Ykaa(DS8w!o4Rj?)Vs7<6dmrVZt#GC2fKG6rnn>#;fJgDSw(qsdLZe$3v8oehYSpik?#L#{G2OVh zemHc8>Gz6ycLC)jBpSSMhX6@1;3SQfs=cMec5CZc4lzFYJq##Po}t$JHiHdswy9GC ztqIn`z6T&qw;tEV=aQu4R1Ot=F|v?lJ76;o?tHW^AJSe%dbx z7fWd(qNey34?us0RXtyAN$BsXmKk#$*31oSz>J{?<{LG)pWRu^QatQnwr&gx-Le1a z-KhpBpjvESyEfT~l2_>pi|ue#k9bU+aUFjPOm+|CK2GIlj%4asU#dU7&*De5BO=R1wxl*-l4= zH#KulsD1dW&FMccwj{Hp~dvUMB@iYNlDdN^vfr) zg+F$GQ$cT&b~F3%vbbuRMHlr($Kn z*D&J6q+vW??$59`4aa=)oO6m#v! z=H{8r1CWV347IqmF?IlA`A#XAe?z?k>$jw|6ASu9doi&;NvfikAD*f#gv3jG1HHYkPWcG1xRu*lw0rpZVhSCtLa~3E3|NfqSHc^+e+SPL%wyxw7Z9Hf6p33= zpwzyW%gnCCWUNUON$^?MFN^2AhMeTGGjKmJtre35SBc*mAMFd@B`~Paj^} z;*2zzv-CZ(^E>*Z*-|wOzphTo?I{pPdhu{lVi!30C{yN9%Lb>KmM7R_3`00sYEDwHW4wl`QFL&0Iu*Kn1)-2jrEeD&s^YkUZ z3aptqDEuDDai*Nr_nIuY;GtGL^)}-pS`Se4{#)_5kbKl@xDh&Lsh`14eA+fu2SX^S zy{WICRP~g$uAH4QJkneF``+a#!8I{lC;GE#FcZ}>YX>!eNx&1$17neV7$2lCV-zh! zsV8X@4nT2w!IS=##srD`_$!Us>w+u(AZ69!wCF;9mUIJ=7fH;I_FaevparQ%Xcd^c z6(yB8W#2Fr%jB3bOjf`6`rp0leK||ayfosu zLk&C^$_%I;Ddg>IWPCKarJx6Jjd_1*Klz*-wgBP2q|+38?la{2yCmdituSp{rQTO{ zWeH!3i*^MQwvmr9B4|Ozu;igS${QloxrxO382R2f#IGlcRBL`GQ&{yG_E>a=k#be- zd8O4VcFEd{hmYI-%Pw^=_Fu_G+uA}{uT*To;kLu&G#g57wF4!ryXBlh#Ox);jcE33 z(ucnEaMklx6#eu%aa~ZFm&X|OWh)Nc7@NvC1)I4}FE{|*(Y4f%fQ*(x)p=q4Hul-w z2BI&Klb1G*$@=9KBX^EArCm0ag64lc&L4zvqrW}?1#T5wcX21EcXI4IdAVr!GL(T} z2kWL~{d%P?^|x1v=7n+E&z?i+jK^>tO31wRlYGuGgcw|Xq>83bpbH*usvT>f*v;YQ z1eVi!g^v_rnA6SmGA>HWQZFz*xiZo7-;TH4I<=)|zlh;y$HwVFs_U#OSN$a|Og0nJ zW^k8p(eppy&R5@N`5hGF<+Wdvpv3&^0MuJhD}a4Mb1#EmqbI}fJRs)wI5zfV=j0`Y z;&J&x6Q>m1MzN7^%+K)^Z(mTC|5Biz{JHw`=qCfmN}(PI<)nAC5LLGq!buZYEV(LV zN8F3AX?Uq{0P@`#vb>t}G zJV!Gm&Pu~-tk5Yn#NT3O)o%)z8#m4Z0ZP9$rIhLc>sngC#_iz`f&OP6{Ro#C`y*_8dWPIF)trH@20P=wFeuZB|(~FVrLvHvE z4Bu8Lx;ijO3=>PUk+CTkZ1(13xys9uXxGdc&VED~dnng?9qEn5Ep_9C+f2iWVG9ar zL4Wi_Rw5ft6U^b4F8ld5*Rc(p|0g#!%d6hf@)MX@InyBVW1CMAJ*YgS4`e!nV85YG zn9-M7P-`Quik<@$+=ynomRJ464s^EFcrGtOYD+p>N`>jgk4tVZ<>FtmvyEK0|A~mF zTEZRZ>6*FLvEb(F9&NN(%S*LjWP;W+wWgQ%wojY+(~JWOT1VBLpH<#}KUU+MTn$wz zsYYbVR#ix_E1MXKM=KrjQ!0!)4}?*MM4>JWhYN+e5c8pw5_stydqAUv-A@%=GnSOv z(p?9UYfNg&yDa$eOYnDf#g0$J9JDIkn6gXXg3H z4H~?iuX#!QipGQ`Cstzj02Ffo(hzO@=2HEJepXPn@s8jAWGZ1+c?m)~{7p+V^0~Es z?@&+T@iWH4s@vwW&nhaIP#T8eiIU9A@=1{JUg^gpUWhJ8l-}KX3xJ7n9 zuK9iRD$9q)G>-&hu9RW{Pg&{c^U^6#ZYfXFer!!SI%Qq$m0ZNSBCvkqHSJ8H@E z&2MU|&hOag1=C})&gQ?~Mc*b?6zuvvV&jB3@uejYUimAe6!#V;oJ{(gA9*nT&ngeC zK>0y+wjxNytxzu@u#O-~BFPTw(VlCXvh48HXYyJAFCN+wn|;2vIWsMb<(5~=2j#iT z{HpicZcE)Af#hi+Yw`Wy#JHA%4S!Nbk3AZRRgcx<(97o=k;a-Ww$|Q3SvA~o_&y;Z zC;cv3dWJQXrgH!ypX$#Atj^C$aw>qOfu3YQsIJI%GHQbd92PmV=l$wu6xh%Q^(7bk zb!)Mp>zuze*_<-4prS6jl-QlGn{O@Tld)KJ-vxhW>dm*a6{OXqv~=N4C6`z?UDUu0<#ZQSZwu>A(53?Dsv+Wf?h+BA+)c&GJ{sq@tc} zP-LyK!0*h8R*}YetMf8VjP)haf9x&}ah{D?+f(RuNBKvgfu%7m9mo^Q8@9EI? z=XMpEjKbH?a3!N0Y%-H#X450>t>pXkEQA@NO3!xTB>!TMfzo7&kmF>1 zknjnQ)(^NSQ(-wn|0Bl!0kIx@CIxDd7ydu3qVU7X#9~;gX)AFnZsP=ItdTu`?&suB z%`A~OnHB@$Y44SnSIs7f#g~fGZtglMVD^Tv(`6hNMedCdW*33S?b2{f_Ou| z(1-W;2k>-m$btiKhS^Z0M&DleBNkRMXq7sJ+Lk(KaE1>_WZc4Gr2l4M(yd}@nD zAyT&IbjKNq(l}MVA|bQNZKE(T(}=t069U!YXMN#^>8L8S4D6G26h`cvxq$@Dp|%L;TN zWN6oOrq#Vh7Fz^EMKzz#JkiE&zWMP*)&GZw=OaOpni`AdG?qkhl+Ery?;`gtb)2!fZfKtNH6Kj7SfVwVJ(2E!d3_)&+F;%b?SxGg*&f-Jq z(@Phs*8Yd0@`QQk3fG2>;vIJcC}E7xLaqti_L@8&(Xa` zrS)cJIc>M+g@!Mi9Wxm*3JI`yxv^*(|DEajejGo-ujIOIU3|KAJRd|S+&L#&C zz1Mq*8*M^_m7f!h{&uTY_B}fEWur1^PWwkG-|;{f5VvZ{r3xj!ZvK82i)a0!>W`*- z5GRqHS2Z~+dxv5>@t_%FFCJxFLDJS+=-YnUPE-Bx#)P#^b_yHUgMEpMk`AP6i&9;w zkLCmcH8iuR9UqK6;xl*OiQam%C1Dgll%Xs8OTp7+=<%ahuS9=uT>${qWJHHf`+{#v zU>}y*T(4MJk<7^FJhRN|Eu#2t75Zz5ag@Jx^e*O3wJ5bm3|vnjp`-T<+_tRcU9Tzp z==?bIDoH$L;@4LH){HxYdu~pHYjd+zisOr1t(wf%g3;vm9_`a=L#?XuGBG#pj?|?+GZg1F zHG=2?2DRS)F~(0SmUAA%@9gX=+VnC^u#&KW=&111kwp1t_?J1D8FI>bWCq{u*Hf2o z`$Qa+(FOwWP8GBW{5s_f5Mom)5aQCJ{=zIQ)_U~CrvV-3s(V&?^^O-6lJm8Bo%C!E zB@I69N(X7~pBT62HY*z_-f}N|^{TLVq6VP?mrf-E9&Pj!a2)zLW4t8~^{DLvaprm; zCk)fg5c-hMZQ3jPoYzPf`yga{@a=NgfAW02fC8sH0z6_4az3F&aFg^;Wx)=-jNzETHvLU#{AfTiic0y?wxmk#`BQ= z;sE4@Vr2{>kAey8#Mz$xzUp%4feP4T2nL5sX|4Qrn0mD+QYK2&*W&378`&876!y#$ zDd!+X9%*iNn-^`)n$Lrj-7c=Va#C*`fCf--GXRfwx^(~=Jy~Y$!B&IpGJ4JP8`*pS z!o)K)5p&z4WUvnI`b!;8_B#b-sP9V*j&7dhdOv{ZN!^?~lAku&-^m7jqZ@c;JbQE~vNfD0n=XFG$Z&RlN%ri#V6_w3+Nb zHaBA>_mxNWL0f$w_dBjwm41P-xb8l+UhQD2)9#rfJ3I4M=+9g9Qj8ah4KWTrD%6RP zd;fk^)Bo(InteBp{^dlID`H2=?jq0~WzN$jxH!ok_esAn`3YCh2{z8+$ zgqr}ZR~yzU@6>fK3PlAJwlP0-vF^+sZm)D_Jal$g%T^v5FUeuQ4yD*nje#MgC zwSw#SHh745@>pgNVbJ3}Q8CFwoHJ4z($eU!ZI?Z%%YBu-@YySN|E(HD_a-gu@-7I$ z2Mo8<@onxKM)$r#ZT0z-(XoCVmaz|qqx;1^eK7-NJY|dG(EPA~rKnJm82lcN2@9oc|O}^1N!Rq zO$Q)_+XR(n!NzT{3;>%SfH(|PXcF|;^&MnFi_20hvaxaK+Rc#$U3%A&#b}@cHxw!Z z9ugt^_UPg*PcAW2{M|&2V~18+pv&aPdrj#EE2!Zd+B`j@CYu~hFEo&4;DX8x#9Pet*ydNn z(t_SD3)x$h``JD;MV1fA*`}qbwI{c&hJHM=54Q0+ZfgwsS6$%u7V$<5knsXWK_blH zvleZMd(j~uHE1{Ml3lxh?9ON=xF3KC@xuj_s8@xGzTz`Jah`Vu?|ilYuKzQhkUQY?bcV)om#1Mh0%qdVM5o+eC5;6e!dh1h(8nL1A>jH7|jrc zS#)Sm@kpTr+(DhjIjAU6+EB0?Uui4mu|vJh;PkYWcPM}=20 zx>n$;%_)Iu!W8|6a_6J6YO?T_l7nPYO#fU?dnv5L5fe z^#_aA0*s*pknpY(mXCIV$XXQ4E zMzE4i104Mw<2+@pqa`4gC_B#)14%dl@t5RuclQPVdNZare?upwHC&41=$mGSdiPB6 zL;Bp*{l<_uQmo`ORTYaQ|3O>@uY4<6~9)%VZdj`C8`%KGtnvf!cvvQvk_56iV}2B2QwR6a_< z;*H(5avjq}eM8UD%eC)<0UC5vB)D2mbBm$#M^AuaS-e_+WZ%}jP$Dg)Xc;1c@$L-t zB-s;+)8{CjZvz!@42~N&sh8UC88}H?RhrZ~FT*i9w{jzYmI<_9-^t)1qPn-(SMr&N zT6uxRJ~^6IH?;({(yDHfCnuL>6NHOw1o-$aRXmDfRjEdC(en-TU@GKnie(Ahl_;G* zhohNuPb4pd+qZMW;S8^7(=dM+_37jm>;=Go09ha*u>Y2TflzKFg^LYb=PirY%?82eiG0m4BQ&vA;ntCfT?a@MS9u3LU z=+SYh!MvU|igb?}WS z0Q62%7}aokv!@}Y<>ANg>CX8+%sZ0rcKyAt5XspgsI@7ZuV1H4etmOx*6BTNYr?7f zar06|8B3NN=z=B@OVcpjC{3*eaB7QHjQ7f)nCZ;xNR))e&&b@5vv{!gOaY-^fIFLZ z3`J0kZxo9}l3$Rd051sQ^eLklp)oG#B4;VaX3FRoE36$JECP+Ru58HgvfnfDVeV|i z<3y12C9bC@FkZ-M>z=e*G_7~hbAckTzE8{Yn?`7+EK?10`5~Uwg(w|dQf!5R^TbzobcPCo$*+fpI7gZ zV5EWRiQDZddYLii-E>o;_aaXe!hoha%s5Lsg=P#7>lyiFhh_-)d{enc8U!Fvt79=K zKCjpkj6Lp&n1Lj#0SNRD4Eh%odNBO&nicf|p~0BO*Fn~|D!U1o6eK@fo8a%b9MC)# z!fi39^1DxintK+=3uLEmnoKO(B0H~v=kvQRTR|2k9~Jh?9(LG$nQPH3M+D{nzMZJp zjK$s^W?PmBkL^7GC7_up0>pk7N@K zzbvXA^bmiPlHH9yJ-pFoMUc2ObA2q(#yl|0TiKeW?BTilCJqkPWpegQGVkfFVBg^l z>ege-;gF2xHUn8wb>e)1xhh;=k-1`^;s6w~Luz9l!MGPZnKM97XkuoV$+2TI)|6xt zztW9!<#C}zeC)heq^^+(OW8~9#=h6fW?5thkXMY-p~$U&B-xmLKPJ7_2C`oZOXS8; z(@bK0f3x5uhF>i^t|8CV&*>JW#JBr`&e64y*GJ>F(M>|Plm3n{wGQgeTRajdLssq^=K4N4C4aLoQQwg2z}Fnw;I<}fuWX! zv72`X>4mP~4`McKW8?Nq-yweu?p@k3dth)rwI4fgMtXUTRuAZb6w$Y21~z{En$aZ7 z!p$i#G;{7k+0;2QvA6M6&Xbn9Z#|Phu2Mwqy*5)4!cHd3d$s{&u4ls*hnU1S7$1Pv ze-k%n7`!eQ^o$m_1n1s9p5Ng3_If-d@kv;c#b8#-C{8YYlYE;e6UtS?bh`qFsl%-A zxl=W1D%PynGEAJFX~nEn6(!d-?~rvBG^|+j$9e(>dsT-ii*#mlbBfZjy&xqiUBm!d z46tNA$hav8(Z)Jq^4j#NT91A2?siF%=!M`^t}83Du0zM7+{QKgQ&e7dgNV42>iWa! z7xoxwe-}w6NcP+bFZyG!FNaRGt1daN+>uP`2`A zz`K0U`?L#hC9DDy3QO!kOAryU4;BK2`~-2XxgIf=iLC>6>@tQE#p#zSD)h|{Md>K3 z{32UZl)Y)k#y_qU(Hw_0%NE_L4U#qdnh4p^Tx1nJ2MGp3ccDFFzJDW+DvuZuZJQIL zh>;Y#5ho|AP1cgNt;ef>V4~c?=z1P<+-n7HSHvpgW{VpVz58;mBb(SZUg3{4#-T@u zi}UVZS04^l9{awUf2K7>WkVU~!NzY~G=0wTv8lAuly<0{`p{kIPE(ZLvH8;VL8=~N zsKuiN++oe)gXWE1-u$3r^;~Pz8GYa5eU>J_^$ETDPoF=B%jJ;EH>x*pM?@6!n@TG$ zcL4bS7G9WiN+BwXS#oz9yuL>DM|{RKmd3Y1=C`5{im8xsJ&w>O$Irej#5fP{EX^|w zBZWg^=lGfAjE5JuZYRAz={GvUlk24Y;X9ZQIiCw=*_66QvR}u9hZCjx9;RC;Otu}7 z8Cz%xzh17B^5WRKP!Bol7Ggq5fiuo|s|x!yb-}8+6Sba7QEcuFoedTF*imayE(n1^PISdw9?4o!MJg0XqS6pk~>*X<)4BLsorIf)d?~-SJ*tfOkbB1^k zu0-WC)wq+5==lotJhT8exHmg(4WUPpTXG_0wY+KeYx(g>>BGyg^tC|V8_o4kUKv7< z+n_iuN?H?mD2lP2GaCUj3)&kuR59Xufnutal`ypMsk`eQ5)H}XieyAig87kQBXX8= z_};P8cu0gH^l$@5AXKzp+)se-;*kng5a=FA0#uPxQ~TB@$EB~n>RZ33x3Acc-mjMa zFEi1YCuN;h*gkb`i04|%sQ*jh za(rkORRkud=QRB2Sy-fvwHOSW|L0i zbM3QE2KVKfvy9IgO6yhjd|C}>5v5Ey5m6f=RMwdSVfY!$6k44oUwhNvvTHvnxtvmZ zxzV-&d>Ngg?bu*breI~T`?D?NC+^3r-6#aZ5P{oL!bp`JIe`GW_hf&l21B5`s_T4V zd@@u$TPA;1I9R!(@?^Klp(-X8`@)-{(EF+S6n~ON2SfyZxR7>@;!x=Xof9VsywZuu zEt`Iy&Y9~wu6N(0yUbI1KP8s6{RrkqoriN7N|p@5W9A%lIEDp^K;?bx~hi##gDP2XN&{ z8LDY_>Z4Tm@-?k0>x>Fm-{yH#L#6LCadW{`j}bp^@u(u_*=aM3X6g1#nVRq@`FnXmhtYka@)rS^{PJir<;l5L2#q> zMm!aa=tXdhp-&)2bUwEzWLEl}S-F{Re$QIOAr%b&#jb>P%%agKq->bu_ykuc<902P2M|&ji;28G&St>w!IrGa8=i)vF&)yUYww3-6HB^7U|D0329tdFBpU6%vEJSd1k@2Jb z!2#$QbXU8}Re1y+L~zmQ%NI>68QYC83#@io^qGG1KG`EV;k>=wjYrBIrV0GsYNNXiA#mdMWjWZzx)fQtIippZuyx9sq3GtlxI59dF4>+Rl*q zeTtMgBVwLE@FPhuN94r&?9G zANHrmp?PQ~;|RV%6rNJl)1tCIUZtm5GPk0S~PX5SzdqeIJ)SU1$TlZ>D z#k0Uned}yZ3@2lx;N4xtJ}EBL?p7k6%VMD4mac0|2+XtMgaGDn7W zdpJrWyy-*O^@i*nHbQd`mI>}j6ig&p6TGVZQLqO+H}9>A1{8TMn4R)3wIL0N9ewls z@v4rv=#DaNl<4{#><+wCJ-G5n5f$8>nvxn>zC2lGol!#R8@&+NXz63~%2cq{BYl-q z6qNYDH$oOZB~z~ilmoVc=X274auXV85`Eeg@ym`9zX%b8C9GbXSj=!}X&4*crx#pl ztZ!l)Jpp->`FjO;`4i8UF`&kR$9n||MZ{lyXcgk_H`5AJ$@-A6Qox9ylFzPw`F^y^ z7V;*T>GvKm@7naYfj~+i@N07)n2)9kAZ;A_G|o4aP^AOVIy}_}`WzE& z@>cQej{)iPo&B!>hlF@3^=rx!*^^X-uV?G-9X2>I?F(Q>i0x6TZB|gEZ(>|wvciWn zj#vHPzn9A*OoR{VJF8g)B|Mp<(st~3zRjaV2ATz$@a0tcM`rQi?jM@l*mX~m^@3tw z;PitIKvWp2%Q~qsG<#%8Ps^9Qis_*{Ap$g!m>)TF!RCB&nWAQOZGE3i42L4EGVi!v zS^R{HJi7d8zv$NtSwE4%i^Z{#lPHFs+bc~5nvEoZCq~657t}=iHaFPl!Q-Rk?*$In z62#M~rPB2Xb(#XQfoDU6gc$re7T5-b5@t9|%`>`NG?PnaQumk2+c#<@-$^;rIp3Zx zOi%&=o%z=oxho#-O})tYf@BXox}mez*X$~TiQCBmA6=fB3XMaq<-a9sOYe8+Lw8PL z^uc#enmz{mNKKC|>@E$K-l9ydbx&>QKkEkuwLdz71qLRHr z{04D~Ahliz4c96tp?OkL-%#A0bB@){SfpQ*@38}Zt>w;)2r-r&RHcS>H_O9j3+4{@3mxcrgU@qG#SGHfH7O58KM=z=MqVV(>@axO-&;j6`3+ zPF3#=A-n*~Wx$CT$v;d)CL_)nH*BkDC5!#581n;r)Hw~w89SZL@_B(9$oPTR(&CC^xgf`T!6W1Qfr~KqH9L4z!%qZmcN9x<@NLr7Uet zt0^a%$GX8c+div@%%4N&LSey_lg_aY6y_qhRPFCwsW^ltu{73SM#4pI(m!CAO=@@R zt>c_?+PBNlowKiB|2uzx{#>U}jGRG&G*L-H1#RO%F~wAGzD&#WUD)@@fa-HQ1{m)# zwYwXScH-=pJrNI)othpx>K$s{^Yo>GGMXL<* zxCLnsp=1EMrG|*_@we{4v*>vfe{}*CM9D}3H>L6oEY`M`IG3kY`mjlh&&B*)BA2pt z;mP~u?azS{jc+Z!_Q_x15aRSK4@H$HDwZ~kPX<$rza4-`IC`+r2cx8s-p0 z8L0}`97axAS*Zt@@4ni%2j=A=q91UJy8g)JNP*Bg+Fy&>*MydM_dNKeo^H`CoC~1$ zY98j!&G4-;?N(V?54Zd+KSJA~zbk}@FowbP1zlp@tykMg)l+e(1$~87KoRWD7E1k5 z1j!!_-thp60EM-lIbu8iN6Q3L+QYY3CJi)Oh`Y4X;xm*)6LdoZ;99w8YSuO}PX?`A zlzMZ%k7EOp4=fS8o|+=5N`Hl%FF+ngoTdndHB1K6W!ER|`J!DpP)i8|3Ri-ClBnZ5 zhYc?r!WjO_XJ3PW8Dkg_uu{Vofkms+3*hc5ou!m|tDMfIq(emAq~5cSJAFzxrP-qG z*%DgLCZylTEx*KPZg0ZhP*20$$-#i+`T(JvzMgJ1EaujZ`q5>aW=sic_1TQ&1GS;u z?XG$ki>%tgb3<~Yhn-b2ttt#I3;%|a@6g|1=CdIZ;Q68lG#`34LfVg;B-MwI%r+lC zcRo1pQuoyf+4{gn&GnyKSD%QzPd{B~t$#nU*;j6}h{#6%_NOM-4I7hVzdl3_fJ>3k zwKXuEIW?K?UP&Mm#DxTBI5f77izBDdFQMW0 zO@sJQs#{>7Ai7=;T4_p^VodihyscH7MvK!PL`Y~jwA_Q|srPB6^}3gQ`#kS7r;Vj+DzPh}I1*rYBOE+1K z;C+~4_?;I3V1|zMLK>{sMc9dfJ%bVv3qS-TaAOQ^TiS;!NH}MCLwH-WRrps(rO}Zn z*>TmP9MV)`u6J<6hl^mFG88N2B=rgda064awd#qSK-JG5H}I56X2f4^pzx+lauVPM za-~H3*Zlm+=_9$iGI@T%?#uec8$f-8ViaiA=g=;^fa;1E{)PB*06JnYOVB;P zi;;w-2NlA!FS*S$y4?REJacJ=DWo}0#o6@=t8`<6LoSobr#5>)1MyHa%b`UR^95pX9FPdGo?GAeD7o-$^ZsTSbY%6$>GJ?Jtq5D<({fz+OKBoDcA3#+! z7$+KtQzYCT*K_ffj9Vzc5bFTpxX7Tck+l1O2_D{^l2DEeIrjS2j@9o7;BWf%U{j{ zqzP~I=dq}U+Rsf+op$cXzFAXesvKkbk1D8(LS-m6AZWM(1P%3}*+=V1djPjQk#5md zi>Zv@Zpc=D#lEqS_9Ww@^^r6cT}hAv`rKrjJ@qnUP6>UC;(Z4Nm!X)4A{V?DB2Bc$ z^lWQz{2I{0ujo@dFHQ-moO%O$=340CIMXj{8qUkw9KCBxy^WY&T&PJ_#2JXgIU_bS zOj<6&^RD%22MxMcICp(_Gi!)Y%(iymeGbiS{W|lrNnqc}nXNl8)_|1)o|lj!gmp_O z%TG?@JdS2l9XH=bZaF{)t32yNUyPOiHHp$(TZDAlGe1={a=%0F*p^9NONzH~!_s>c}B zamHag)W!coiq=1f-dO*G6y0-wpP=;zDLQLWu?mwG1?}Z1Cl7rV9M+#0s|xBV$@>~r z@!A6bZkfiXIwe&A4H!!k9dBGqjfK?p+@}SQim%?uupq+Uxj5eXsFUYpf9l+ZrqBhC z{J@5H*bJ7>S~hGIfUDo2hp)$Ur8dK^e$fx?&zF1Ulg~Z;qG`k4`Gbkpa8rki|H6?e zp$w)tHMcCU4vST!C-zZjLA`fJ;8B`ns!hhN)-m^-#cSg~fMQ;qYTCBzYS^|6tzs{` z9((T-M)@VXIFqYB0498%yD)~9u>#E8gibXk-rytzXYTGRkow|WAlFKLonDStviKv1 zw*F+%O@@b%c1q=YqeF)NJhT5;j&H|gdIK#kbH z7v29ZSp2gj97t{GG)T%&7Kt-|QXBrPGm)k?WBxzTQOGf|x_rPtWpgCG$INFzh}K$} zQnx6Ue^PTZS=?TN6Kb6j?9soM;@q1D`tRD~pWCnkL9#jl#qN_eCqm3B@GtRgGLvm? ztdGAPBPStve(^{Jy2Gv6=N~1yf2&?Q-DXTk<)&aRe;`gJ22&&Lt=f$wdaJ)%>hZr> zMTtMk%>J5W-@T3OR0R^dmb#WjH2L9k*F#l@eTJJd11uvKZr8$Oez($I?V&I}uX%C| zxEOulI(r~rY`viV2+!RHxu>HG;SO^`#)LYt@0C@1fXrH z>zUNctHZFw#nkRVZc6Em1~LC#AWzzywa)~UUz zx@hfkg$XvNsS+(>E86a}-h{ZFacZz(>#+Op%#asFgDT7zfYhU_fl^pDxYnQKr&DcW zvZ?i$KLPy;IR<@~562L-{q|k|ZTlSqwy zWSJ4N3^UoLF!S_#-uHRWbKXC$^SS@J&wcLevt8G8G80BG)$Sxvn|B;I0RRBgKLn(? z8J_?GfZFOJ%VQuHg8*Avhwl6*Sf_gop=YZ49X)CtHE13Ei--jePR{wk{`t&9Kzk!zUs%pFTl09f2?EtzIn~> z1XFQ~uPsSFV?mKpD9^=}nmWv!$iya5?q~MWCe|+?qkpJ=o%3qmQ~9*^Us-p+C_`Pm zCnS=UmQIq;|2{y+>k{6SrF~Vv_}$!lOA>n*5aIzZ9U7UID?NIR2GtiwP8_mRien7V z-WmZ(s#;euGj>f)jV?`h-YO7&YplOZuYBobpBemTY-JdsA7Cv-wZ{ zH((6#8=ZbOKOXqsP+lG(uuMa3D^NVdq%B=(St^IYZ@!Go`73peVz6?;6Vc z$4R5kzgOFBk1C*+#VCO;x(qF2IcppWsdRCha=KihI+yQuF)*l{eCiV32AUcC)yw4i zc4_)E<|oH-L7*6|fr#4xeW=#`?I&>Q))TcL*WIv8NGf?-_N|1k-%p#)tOp-Yc=Np- zCpvtls_#9ZZBeSaL+A7-4!!aYEt=c$TRRMZx2w&x8>rsin3{nclyzM zKEs0JhVS~k5G{=OoNP(azeagR?ifFmTMSe~So+kyD$s)8>hl60V->|D{N?1hildo? zy3yy4(hWt?8q^mu{M>VOBwJo*_-7yA52%D2&EtwS4KGVF_3iJ=$r}dsZi@+OJ!5(q z6+b5spY-Z=f#PNYSesGmFAl-b&%h6}=wj59nbZq1S}toM_N$X=0<&(MS^5zoCI&b7 zcCvS>5@7!B(r)10Il1qKA~a*G7OL#`T}~ceS~j<~N;+Y6LW?uuCR;E1^Gb6(#QLG3 zcdDs|si%v;t!-YQ)Ll^0Eg#!a*0-Q{{@kD_?|E&# zwf~Rr|8NgueE%QH-!(RZ(RkM8=7-5=$7))5OG{ZS&x!I3nM7+)X=YpM_u!^u1P1q#h<8LI4(nhDfKw08=trnBc?~Wt7 zpO~u1$ZxSati{@BKi9N@R>Cdcr~dvuFti!&X%kw@v|V3K5ns2QtU|j`9D4+4dI$Ee zDv_$!1Y7ZyE9jtXgc!$01~m&yaFRA2dX}Pdf&uX0{J?)1tiA`v(q*SsCj!&te(9a9 zZ}p%LO-_b=H>X{4ddS87_>?Jd&;2A_90enW#{A`p2~4zxjs!o1;-UKxM@=vEzSbbz zvM2z!HT4=O;K<|Ar8aaXU7hS{kP)P_yY&(ofWQxCNVQctA*hnq;~HJ?rv>X^)_qS@ zAJaDIC2jv#JRYDTF}Y$pIElO0X=i#uAJBq(>-qjPMCdFkWqtWNU+ZFpQy4FUaB90A zyF5_+`DK6YZk0AIi&D_#E)+7Q(rPK0<~oJT^#J{rIcLPEQ99-8+h#Q4^K*PAkLnJ7u)lnGAAZIM^F(i+ zV7yqFad7caBZm}P7obKawN`(c+UFzmRXh%s`t(@^e^}jzvH9A60ie2_A&$__igdJj znT&4jitf5_R+xRA^Q(aO`NOSSK9H9aY%vxY1=-YsmWGfdb`@;FNv)I*?TYI#E)WeP zrqC=5RYtr53#VL-9(B;>=WilK0xN-^S-a+wIj>h;4Lsy(`vJ6(28y*0tg{NEqAq2mbleRB>QA@*ExC0CKgfthygN6j-o9 z^ufnBlXPoO;eAFcNDVdhZ}qRYRc(?T^_T2QUoDObeW$VZ;<#V|VAP`XScpFZ`1DY$ za-*_#)89 z+&AUOyUi8h_%%{6O$SNH?Tbi?8q&KHmG7U$r6*Bfa5SI!coBojow{Ox__em8^FLD< z{O?22ht=lDDi6bq(oU)Ix}iY9Z$s}Eu@F)3hqsNDk4Lk03We6}A}p(RT5=@(p(ToO zi;nbl%~YO+@I0Pa2H=BxIwvw7NBgc$Pzy<^b4_7h%}Uqltxqa?x};K{plH>$-1o{U z^Zd*}s>!wUgAq8H$fLjsc_? zAl)Y)>KmRHpV+$5lqtpv)_yQ4m|j0UQsDQ0w;;yoe<~>bo*+<1ohKg;t3;WTkTI>d zC>W*>sI|i{w?ne-3yNo^@NHKn4fV*#!nIf%8qam!d0||efaxEN)S+fQkCdU=+EE+g zH#0|U@C%O;;+zEPczvIVsq|1v^J+9W^03U|GMzFkw0MxTZbuuZs!h$Ha(dRH0wpne zZaHGAh~j8XNadpH7j>R{8%$@@7LGkDCOcB1hueFp!fPP&-E**TACf4%cRcE+xz-)R z0?*dW@Hy}w^~nt2?m!UqOo=;v1TM9oyj3BKMb^S+2AjQ=MZZ|=U*!w3N=!rg`MkZX z%j~)d%G?fcy&cb?bWxjWQHBYsLEPd&>(`Eja66&mc7H!iX!B;4AvlUe-KxA?dDF{> z@G(!`oWJmPY6e;7HwI(Au}w8VODM`wY?IWbcHV!L8`X)6!y?p8qjwu@kl$43-mc-P zMUUa4A$hF!7HkGeen5Ww+5bkNN5<)N@Lp9e9fF$aL8#?YK;oPJbW)XId4kk{9Rrxo zMNbxwc-qH{c08OE29Vh5wUCnVR%@bN;1@(%o`%k99Di5q4Y5NM zE7EUi3ZGMxbv-k4`lJlm%$P0wM2XvH5wicmh1lE!>t2WKz%EIH_xTFdEtg^7Gjh8-BoO>bTZn~DNDHJUzUvvARuNQW6!&<*uWy4xSKK+*4cpgto zy8=3JEKMe44rcq+7lk=461?!mX4VHNQ&z=_cv3%O; z+6ec6UvS+F;;i^+_g|rAxDz;KEY;S^$6X?5f7ZlQD&q#gdRtkdKazzq*#olOm1d&` z$oP%!o=v>=!L#xrvl~Q4(^3MUHm44(iCM_n~!3n$~#NX||yNebn;H6NNCTByEBhc2aV zIMsXE<(V8OVbSxp!V_z(9!u$KmOm$sQWb5&7J_oAr+s?2lFl?yxo2cry>S_ZNuqDT z`>Ywq{>odmm2LOaK@Q~ucf>qbyM{kqg2EHK%YDuk)9f0lF|K`NIJZpHX_8*@dT!o` zK>6IXRPk&}El+s4$~IGr~0e)=)W@YL8= zZO+Sgdau>lj(Vpu=PuCaxzmOiz#Y`#@3l|m*w5l7^AA=*z51*w|4_nQ!hNaPH$N?* z0zI9JSS3MCz4HS;KC;mlWXE|pX<5e9Don_hD9V!ZOT>50JPdKMIhVg=hULOV|UKQBMI$0rzCKJAMS`6t7mGJ7dw zP|iR~jy;Hn27BEvGc6Y!C2OyrW?q`z=-2%Y*YKIv8^|}wdJr2b_A0|m1-kgJTNqxT z<#aV854F#vAam@J*(O}nxj&Ao?w?)^Y0#)5ti0S!!&{uX^L2ptwxeT77u4p!(LYoC z2{)36JZba6<<#n4+tmfapN^1uN#WmS#h<<|(#pVooS*UtKicG|xRvujvl3T=^6hS} zd{%)(UxjP|G?pjL*{S87dn)0PC3>X~5%Ez`kZtN3(p_w0%sxbFZo9lh|{RoM7lpkB! z)~<;|9d*B7sdt0~3@db8)H2!T(eX^PPXNjt``Mtd1527nPcw>B5$9j>%P|l9;*=lj zKBE=!Qd;b$*0-w+V6I5P_x9DlxmNb3ppYEjCsrxM5~sTGq0LdAdXNGQQIg9+Q=D^* z(rNUJe{6gc_1Rgv)7M!x`n!{mOPps$ai?FJ+_cJ@EV6mo-DcYkcRsb}TJYI5KI5W( zJ^m{8vEt+}!`Ciyi{?bU?cvx<5-`D|A^Fag6ByScHihMYJYVkxQ2KajmysTl#^s=Y<%6uh2^5i3Td91DCMxPfcE@ z^B-T#iB;8R079Y@!e&uyb@(9iVvn7#CX~OoUTGP7>9b&!_-Cs5Mh2`0j5E||q9PMQ z7(m?L4+;Hla`oapZt@ry52#RwX$n8VMhG9nUPp4-%d3ml>es(!VLh{Jy;v2aibhhr zdgjC%L8VIVKXdHQxtWKQmuJ2{uj$s5kA0;1)WxA_;LjDJp-=Fn5o?j^y?HLE{r$xh z%$y9hh{U!$zB6MzY5J?;K8Mw%J?65ea_i%x*|e3t#6aJhR0a@J3)(*AlsQy+1VOYQ zUPbAKMwld5&%Lowa(sk%^3LO#sHMW7*{>VMa>Y{>-zJAafOrexPK%;)&{*2W(B{F# zn4d3d@xZ5OzVt3u%RBux+ZXBQfKx}gyGbr0^L*%sBpdjj{^31|iSJ~)ecqW>x;>kI zIQ|N4jXY7KBg2LU5j3NKxl^>j3OCxkO+E7_6jlMf<_7i3q>qg0_K|KIZiL;rkxE2Q z1-GK-spfW6o<4N~gv1k#wk}2G&v)avwWXvtM~x^MKQl%CR!mgvWnou~qAe6NJb6{l zn=Y3dO*lO64>DNUlcmM~6MJ-aOR2Bb<%lph=?NWGevq`-Bb?^E7Q5%j70ua;vGl_F z@s``_rLAa+oGZ5wA56*^xG4~7m`qVmh8j?1x*QB4l-Kmg+z%dRdQYxot0`r%JHl#y8ZlZNYkx1aQ{ksZzus9% z9!(VJ{ie;$A!zrXNTmE>03r`SMrT=b$mMD^FQE_r-Bi6()7Ub0 zXy~%!GJJYD*l^17g1VRdd%_JdpG4zRB>R6-Gxu5haSEn|N= z$R~MD-(=+FkdUxwny?NN3wxh)Tsn!Tn+Ie;+kRjCe&`W^PYBOko*;?IH#FBZUb;LS zc%M_{;~nRX`~<#sXv_H_m@QxB1bAC)=R*JqNCpBxDk z`lKP1P>_CT@)|pOd^ciZo+z`CMzQ*0jJMyJ=b{D8=}Q?7duOhNGS|;c&#;Rvftlu> zr=w*p zPrAUNBEHUj15BVBj8z?8C$ZEE5PsZ6^2K)yJ-JX*-w-e1=TvgehcA4nu*||S{_pMk zz1;H-Os0a@jxTK`PI?jDdsGGXz?i0M+AjJoNfJH$fbDd7klV$)_It3UH|13FiyaGJ ztivBKooO_jCO|1$q~{clEc)Hae0WurCO42+~YtA?uxnX0~f7iqTPRJjG=im*aLx0=8uFl(?0Z&z>m z+anv2IUS5w4$qGXz2yIX;)BgC=UjjEX__)+WdZrT5(=Sg;w|LbTCnuJM>%m-YFlc{ z9P*7#O-HI+}uUfo3{8l z-TUk#=w@_3Lv#4t<6lW=F!(_1(1ezB5JD5)ccqP2xw$x9T9<6T8vnVN@T2T_Mz+%^ zxybf%+=J5YQ{76vk)^*PP9_lFoSy8aOV(n#x&{@Z=Loa^afg8$CZLo!jGRUnz)oF*#>%1xE@$EU7Q+J`c`i= zXbWvXvbKP}+}woaf*T5l1> z4$X@#2o-&`6JRD?VItiYlI6%9rZ2(VcA#YG8yXhdyHro&SRggS2#{V!5jRN&@Jwc5 zwEQj7Fyuknn4)vk`o*>q@@kKIo21lNk9zQUmED}MUm`HJh<$@xK1hV_Jv&h|BmmQkg zTQr`2wAKnq(nL2FunUIk^F0W@mL5@kwy1jkSGHL$@ko5q2=B#9aO%pW^y$gpKWk#Y zW5;~g-qfPUfE!&yd~7vOWbGsSc0|gap0TDbt?acwzxTsza+%rsfV*eGYR;l1&Q>!{ zafS{Sm90hmJPcd_+0mwy+5VVAq=#@pv1?Sjm{H%)Q)%N-Tv$0^;Foa$FlYpPW6eN2 z9KDJZKzmT7vXao&LPwak;+eMB@b^h2ZvK$>c(b`ZysekEy1YWWhvc&i7nOG|*>wv% znA~G9?-UF?BR9IDqE(6b$iMO-Vgl=X9xTKXE6;>0hFyFBxv09WA;0u8{m+{NMCA8* z2?pRPWotp%?{?>NMbzs(k?^8&m_|^P0+_91EP~`a=*n?-f@hN+=Tdk&)~UG8x6-s> zYSxW5s_J?`Yu)H(qWx-S@Vh~4p`uoMdF-j>i)zr7#BB+s(v{Gq_LvXKKcL){D`z@$ z#V2pjK2vkLJFCz(5kVWONIvW%1D#Xxb9g1Y-&jjYcR#Gw5K`;Zl1-R9r5{&=JmQ$Z ZrTz0g{|0}NexITek-JSBdjT@0{|kD3fj|HN diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 25073f260..9254ffedf 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -56,7 +56,7 @@ For the rotation we're using the terminology: ![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) -The steps of rotation on the example image could be described by following: +The steps of rotation on the example image 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 From 3f30747694400904d889588aec00133dcfef45b0 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Wed, 21 Dec 2016 23:25:58 +0100 Subject: [PATCH 0062/1039] Update readme; --- AVL Tree/Images/RotationStep1.jpg | Bin 18235 -> 13059 bytes AVL Tree/Images/RotationStep2.jpg | Bin 18777 -> 13357 bytes AVL Tree/Images/RotationStep3.jpg | Bin 18265 -> 12998 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/AVL Tree/Images/RotationStep1.jpg b/AVL Tree/Images/RotationStep1.jpg index 70e314df7cbe8336ae8e8d59533eca8639752f7e..953d35929abff2d5c63ad168710748dffbd4079c 100644 GIT binary patch delta 12153 zcmY*h15C6FM5NJ6-L_uO;VJwNvRn>A~_v-k5pWw)f#L_L3F$x2^92cidoKs0AH|JM07 zJ!qbWzNW;O7Pxqd0kP20fM_q$T?9cu)Z9}L3`&ym+WAdZgwKF4pk3S=PC+alKBVD2 z2Pl^Z=k|2tCN{~GXVPphsOgcMV*@+2=VPHDAHpS-MG9{ zgm;infU8aWe^r@nWiQ$$u7^n5W_dF#75O}YxIP6~jHTNNyYU#0KRz+1KgszIyck|fz8PeJvkplB^=vZ6=!Ep2tD)Kk#IIyY6}yVIPWtiLc(?;ocF z>qM!0>#Dz%?z_Hpqnn1TBth_2ka#fuzWE%~nRG}{?;z%#pE>~Zdg$=xn$|Uilyy`` zP8;}&fBV$4%Wp&nmJ1TTl4WeRTxf zmma7#WF)Q`^0}V;}N|Oz}SJtTc@2PC9U%AsIHALkgSb8 z15QDfiM>)4^j2n)r=WzG8ke9|+kiB;tES(Kbo(0MkAu$M0;8Yf1baom6Mp4;G0ob` zsXGNTxK@VZhtRpr*JAGJ@BM`@y2h@J2*eC@BGb5QLP9x4zYgaADf|Ao-tGtW+6nR$ z^n4j$BgO7@yjE+0Bpwd(C@yTGxT{-dc0E4=tOJ|X3$kBNL5SGokmCdE?i+pSy-I~2 zo6-jM1Vi0U(6UtFKfJGpKd&x|+vte2e#cL2!bMWIoPY;umU)_d{L{R#mcIsBhFN_b$-<(qEp#ek)))aI|{j($a=W{ow4wf6_v^ zuEw5oJhoERpIuny^G6+t2PDBFd5n(ugP_umfat$r2vVR;UA5lHCc?DEp&j*ikneza z+}G)>fY0w{XLBGS+g~?)X((PQ3kezIFZzzmH22F=d-nK1md2`)61tvm&FYdf0aLzUZmp2eu<#vq$A zAHZD{F&{oEy%{iA(c_}|eQbk>KLvToI)}mcEWVG!&p%i&_Im98WZ!Wyr~#`f(fqyX zR=R$10-cOPw_Y3FP~iTBKFK9#R=i;pN;t@4q9YG94&YQw#X7WFLZtbumdu2 zpco}{kk}D6H#i6WBrZlv6(*dTTQaZj?(TIVCY4WAPsqD4mG+yI4P7_`+z;q@prb;u zBV8m*_N{@Vbi{!RFm<^2m|xd73ERIaJV!_v%TVp6L{jtOA}b`L@C*&Z|xcJ$K4`ufvifju^L4*4}eQ;h}7L zf-rM8yY`|tcPnV4JuL+;Ogh5v&-cCN;T zZ!`Vp#dr*Cb%vl9|ER5D4RJGNq}M&R!s4rl*k#9yhzqI+_92FnU&VgQ{;naI6gX_Y-@Nh;l5rlIAUY)%l{)rcQIeY?$cv-oNI`8#MP zg+$(Q^DWLEYH#^4j-#c3m0BvzH2ey+kEp{wu40nUk(9KeO*p^FdMbI*tMrqtJ?}W;xY+(jz**d(`?o&{$dIyA0f9(_$g=V3s zV?VuIx_LSA6l6M4iK_y*uLwHbd0SX*>wJDh3|0E)d$A2h@gcNZK7Q!}$#UhB-Ku)G zr-88e?J>`#_5J-7ta!pXVOI`;#u-5YJcQS(BAe`~{sshPwExG9PG!AV&w=h`CROI#!bMuQzjwS2i7 zDwc$h@rVRJRz`F8T(e9uw*H{;utHdF%awU=&Y?ze>7qM;5mg}cJ}Hcl(P0a{2g2?S5#E22JgyAdJ9?f2xJFK1YEYcs3+4M4(eB3L$RKG zfw+#uW9+95lmLO>X0nQa4SWke{ae`4nPYJ5{M7xc&Wc8~T!CpqYs z{95vB!bF~lIYMapzxx)Q!_=k-SDb6LH!+YWRdqf#qj-y-;u*)nw)+zQicwT=&k);DD52+{dMfX6B5 z;++?ii+JFPlg=jT0mZO#7UOXF5U4(B4gl}oF};oTn#=9g(ILG2KrkdCXFMr(-~JpK z1I2#?{A4|`xT{-`L*G7@m@jS3N$J_@X1CNwSQOM0iB$}IbS27{)nr4x2g6q)v2n`lS&R(q|q75HoB`CBX zZ$f;3c0fI{FUi>K#Djm7%WEeBidT!UZN}L+TG@H{jO%skF0p4mx+zYa^vwPj1LMS# zR>&H#a|*&Atxc!FTvkcDGKaEq2H(g1KdD*6zPV?!C~iDhlpGQiq5HZhl(hdN^@BC= zml#Jl1+7AMju3N{8z;3QOe*tpPaDRy!rXc14(8{IJrlgXwKF*>5&A7s?J*0AVrmHk zUAo|)F;kWbrDBfY5_*w$pn6LKeGr%B+y6ZDLBQ$6{~hlCneA&#?foUiFCMLj^Ifr0 zhJs;0BeKin(@TIEpzw~XjwA|{)Wi_A#vie;#rHS6| zW6-p0AaRJ4Ur7Ov`|}?x$2hY!QAY?W(@K0*T6*6Y9$Xpcarsv`fm`!;Tu-jZ_;EJy zEJ;H1)V0x22o_313Yh2;;i+vHSNWu)$lX?1;qK){4;urlRA{)v!ns6s?w{R2i6uZr&1m)Ift4le25G~?0VM7Rv^UScA@Q+D(OkEuP{icU?ySG5hSx^a-*Xz7nW3!5GYPR~YmmI%& zE9@m-z;)>@SmdgjORugZ_x{LEdj33>c1lNXfcgxjG416ab3IUgE;`?(_S(*L79ORk zEcALt+hs_qZ{rB)Dq0*2`>Fln_D*4&OBI^9_4d#&cze9$3w_6r(&WxUZ|~>;LxM@c2u!o+-N$xcL1W2 zEs7)z3tY>OA$*z$y7R+j>cBqMq%lqCYsi-5=umo zBwten39HOO61B*r;aY;z!f@lXM!@GM0*Wes?{2g38WBd$t=x;{cKg9NhvuRxQRGRI z*p5|nV)J5Ef{R4tc?WEJ@cN^>UG%q=%#}d_eFAljH_oB_(ukF$532|2P=JxjOhP}X z7Lp}a62a`ZCCORGpMKh%f|BM6-;Sj?o)O0zTSO6Ya6LN?tmQ0D$}j60-1u2NdO3r| zZ;_whF!KTjJyIh0$V~l5M}Q%CmgY#!JHLcouQ=3I5(liBGk9jKAv*!SAhWT$7ORHH zd1$rnO<8fbiN%G^#GCHG)y7nXn~P9O6630Q*C{9w#fu~$yR@GVLdWI){#vp(%jT%D zj&=HD#8Mh-{rB2RIIJ?6);E$hRFP1$lAnNLC#CKYKb~Y(+=abe1ug|S&%dyROV;a= zf9iMYmm7S5IhJ5tTsX`e)NJD~9>s8XP;QV?u+StOnlb9tAX?zJKP#_OeIjw#e=XEn z%4MN6^YKTGJevqB8hSg}y2;7NbU5U6@_)mL^bZt-V$e*2;H7(^+!c=hh9(6dS?*03W;W;aw{uBZg+s1LmI z^jxrCzU{O1m;TKcTP2#=V4UOQ-|k<2l(o$~T^pIFqcSa$HK{}By1*2)J9zf*y$ozz z8ilTCkrZV*r4lk&mTo)o1eVp%60zs3JfM|hnkFPN#e6Rmc*g8 zK}nVq4dp2zR^KO}2{=zNH8smS6JMUX3(ub)ipWEk>u})nQdYc}-SaNs7a-3kR6>ko zJjLjd*$k~PAy`I#XBod1kn^oUFw#0OQ0(K21H*nuqiPc#-h^*in@$ghlAt|AffswD zsO(jB0n?p(uisB?L~eTp%NA+Jgf$n@aTCmONUfZaxKJ8=-94zf1tBoCUeN6+W4^dq z6Lkg!kX>D#YM$r{Z{uuk@^cTr(0G4x?O=vn&oBZyDb+Fsun-_ZauwDS}c$ID`ti#3(ECzMPYzDwT~KbKuvPS-I{ zod5dn6vW*91+|2TZwDJc3l6 ztc}K98=H+$Q^{Aw9z*ea~2jdgLGd`xS^9#vK4)?*d}c z^;0tuz;mxu2XHE!ALgKyj);+KH5X|q-^8?DihMpXSCZ%Z4FB@)6ZcoCbW(ITPeMQ< z<_;7Qk}+8))RzFIaH(UFIKwZYyc4KP6zws;l)!r-=VwggZ2wky&bTan7LHJi{($zU zcbBNjeNfEQ!c9i=Uuf~DQ3Q@MP=zH86>u$gaD!bqifZ4M8Rz`ol5;rs+fy+Cb1-d3tjKIj_Q&1=vkH|ww!+ZY1=fU-c-H1eshv#4T zRR(C&PPH=*3BW%+%Vr%plEVa{SGWgGL0!2}Y9zSe6m(%j1#${Z{cmWy#^&84t6EpT zRtbU!2N`w;Kx&{pP1H+4*qH1tKzM6>kz{@U4X%Ft(DRnL(%P+$C$pDU145F{J-L`? zESn9Jkvau^)_F8?m$E(@s$KwJ0$=iii;|Y6WuIbsV^XFwuqPV7>9bxF3kIf-Fs<=` zPliM17ZVeq$cm+~&R={&0a=hbWZ#)q^_9)unISMiyWX-dki2@;{(6kgr$$OUnYyM@ zrS6B#uEPrQ{Vy1BgBTYtusd`T)DtK-S586f&ZP35nd#%_*`>FRcmo5iWGp&Zp8EDn zq~7{g#xL=PA+*e2e*Sp-gh^!tG@A$Hd#LAp8aUDaj*QMP&CzM-f}yJq_j*s1)*H7o04CrUo}}%u1i_~Mk(T+Pbh$aze*eBWWO}UecmK97 zd)Y6nuho5Z`t$wIF^uqcqpJ-%=J@XMpb26kpOfJ^sy9W`V^EhyCqeK)Ou8yCu}f@>qmYo_!rL3>Dd0Lt1XT`} z1=nt9LF19h2W9toM6Qhf<~fd5G@3x11Zpi-1c!0=6yR)YSp0!q97Z%)U z^mrO2NvcwF;=Je6s~L2gKGy~<#T45)5wH=^mqUJ({6XTOPjgx{+6x?SnZ#<>gW@HH zx%FK#{yaNUzWh#0ArVH5#YpyD$9XC+@&g8&&O>->Vi3s-FE@Nbxh6bCL{v1Jl*1e< zyR$K0imuB|h2(xU4!EHFySwFb{G}R$q#gxX$~lr^F@=$2T0~J8+jE^{%NNvMJn1+& zIo#Qua9X-&DB{_@yWe<&p|R`&NCZs`ppxOhiAVj7)kM(g^nZ{1=e$*bImp?4!63fm z!}}E}VPnZ~MqgddXI9Vbx)9_?Fz_YU5cxT9hdOW(H*OGV`r73EK|Z@o;;R7Yf^>gS zRBM*n(Y0B{n>|HkXPAEHei)j}j_uHf_nefMr;*s_&;IJkArVSq<)y<#o^gIQ>V(b} z0&fq3cMjf*X4x%n1eyt~hd$&@HxmqV@wHv;!6f$iHb$H7aqAhtZ8=r|87uF(cCFOh-TPc=;qsE=96cCgu|vLKav5Y=cH1MdNyhN@f&5Mn z-r9m>vNB)k+80=}?R=Bq**--vFBikU^!mhYE9IM>mGu^2KsKZmc87m#(Nth;2{P|o z0^`kNceKD*lNAQ`I!^6`Ib6gy{5#lMlwT0oJ1Mblkt1(@sa81hy6MazVTe1a3 zoM79SW7n4!`Bs#av|=f9{K6&Lz1)6)rfsZ>kMP_1`n81I_?K4v&C=(HKoo>mOPDZ% zt;#0cZU@F&?6o3xv({eb+icdI@nffj**X|hx>lGxep>FK z#yR}r;SiVcm7bLDd!3I3%YbXfy3A!)Yb#2AOa^MReDPaLi2l~1uUWT?h=X(0;w8fm z0IzfITRgII1I#wLLkA$yo4HAv;Uh#*KwOdQl$n0)RaRE>{soMW*@?|bCL+co8GqR{#K6(Lkj1lyd z?0S965mT&Y%fk_U$D-yoi)9rE^w{#EVKwNrowhqc8oT@1r|~ts?aPSrM;Y(M&Y$Mh zEXD|?la_X`*^JfWkG?Byfe3RFJ_r4QpO;9JL}ltP{s*mNkH-?;Zm4wlg^KQP~^n5hKFDnWE)^X^wcsNbQGQW?x*1u9e{ zI_YJ^?$d0lgG@3rqgJC&@YU8n;@^qPv+PVbq?dz&Tw=}X>n6%C%K15dM?BT}?j=>^ zJ5VFcG$K>v`qXc?DlE0aSTxysD>dJj6<1+b9oGN$8MKHcZ5(06cSd$;9Cm{|3t+j~ z_P|;)PoQs%4V^@K5QwdKW@DrS!YYsRT!TR|d#ex4y|GEx9-c9}FB0>HFOq+tMDuuP zocBpCIR2=xywT65wI*`fhQxhzOBB(H;2ibzaxCWOBy#I#e2#!6e^1qmX9+hg);XBCgmLleqzev!1cf zpIeuLU-CVXNU0vWOfGP3@Hb>xgt$Gu-f#Zqq<~a|&u#|`wzB%;_g2mFa$<7>8`}Gg zAAMl^QziT5mPF(#Z&#Pf3xr_!Kzs5`B>ZQd24N{`RoIK@NSgX44C~Qhja^#rvwO#o z>o8hn(&rwgRAxiA(z0?~dLgLCQg+3n{CeR@8sF0S*Q8QnQePC>T|N@Z^+NF3(Q8x* zR&as+uu%Y&FFR|!Wkoit_s&adWp8`<1!qqVNR%qjJIiwf0mic=@jrGxsHE(HUKz&Z zv0qE!CjoV+jdvtO94bg{clb1Wl6}A)=de}|gR&Q&iM)!UvX-%{Fm3YdZwvZDfr_pb z*5WLYOk`UWGYRRsx;&S=dU%ABU-8sfbHoD)46V-U<1a2NJ3AV`jO0_DH_F)f*mK_A z>$AnU784-!Hgfd+FVHbB@dL@Xit_m6BP9f%-Nnx0kexu${<>+K_Uh-GileOB+x%}c zoigce$lR)-D^UGciSKI%@U{pLbwq%1XRU+;!}>>S$j9MYAtJTMOO-)?8j0l|a;6`~ zSB(Xk(F01~GJ1FHw!I=-eOLApM7V1RBjKu=o&d~Xa`gdD{zb`yf*iF!{bHAj!!$(L zSp8}BCAk|kcBQj=t&4M;{vvl0$lC7twZP8MO8#7*5jxBY%(!XczWm~CfXW`Z<~2+6e~MSXRra@Ob#s^nA-=qtx;*)n@+tlslWlzbY_ z1b{6_8-3IZBp0mao=E8JDOo=!-h1&w{vpBFyXcKH>uNyH@QhZk&KdWFhT*;L65?>e zgn$v^7g9>Glben(o}$i!IyZKBK1XmBnRsdM0V;y(cJ+HoXs*#ind!M%8~)ND54wxF$)6}tl6S=t|&0v|?m05JC1kzO;`a+i$6l8yQ(DDXgnx5Zayiial1Y){TwRAR`9UIiKvt1MC z46?dIxq5Uf*L2=hLUaKo+wStu9Gy3>BL(j8&fGOT{$6l9^FuYw+H&2|j_(;5b>)=e znAMP#6d6Kax8^_p&5BTni~@kM*Slfq3iB^D;cDdNwQT=3R;&@l0qlLOiz(KuNEE~e4==NKPQ6~uve4)awgryOO8TggZ zyQIJn#sn3YncYm>ONqMv=DH-a7_sV@DqN1+lT1&_50__t-bn6abpXHD2j?M`u7rVC zp%J@TM}{*mu;{u^uZ>y$2s0hr(2Dw@C6YP+$gUGwN0G%duFWJuT#{0%Ng;Neq?V5I zQA1B}1p!oER5;Ht(I!t793a@BOWP|&w|l0~{wwhOIj!O(-tFMjn}ERdgt!C>-qvpG zl&LWhOjgpk0bCzwUx_@gy=|5VBKcDJx~LpdtcabCvtSlmQsC2H;vg7iZkS-)ZzQ8C zRchka|0iqck`$IU(U!zWez?ujm?uWU`Fpvsfyv@s7?;W}#4VJ6dkfQBiczAWg??C1 zgmHtR2k74fR&u8apN-{>-)#;1(&1l8sybF=9f=q9AN-&yY-JQjsWnMR*uT8@Yrevg z^Dmcd22?*HBElp*gPEViIHW&&tk#b<{@pip}qW-4Z19#aKZx38R$9E|G>7f%97YWuXS758vkh*^~k`Gtt8Jv1nw!Jahn)P_z1Y;p%JQ@pVT`v{K^EF_I76Hm$rA= zZvVJ?2{W5_$6I_Dt+M8d$x|dCqjiLXoXLI8+LJgxPeGG}(w4Ti%tw*uXUhAXdD<=TJt?5I7g-7PEgCtotkHys>_ znVyw@vK5`@mhNP9c+*w9HQ|c#(a=b*s3_*p6HV23o7vci@VkM222LXa=lz~5P?SlT zstd=g<>19XC{cY_d5X@wE%=4zmi!qV*F8669^wSR5ivP0>Bbo7vo<2i?jUMQQ ztmLKlSHOS14opLsk@tAEFiS0gm$$~D9@$pc^N)Y?W}iO=xiExPhG_9Lj`;d?h^Lrn z*0kGLrW+s7q9jiep4H(E($*kzjqYm8p*jS$!mrG)&eHLmq3)cjPolysaGU;!^J@x9 zC%;8Q0GvD?*#i+eb35x+HXaOXYtMQWE(YbqF&_JxjJDlkG_x_q>t>z}-n<)?LSnf#myn7srjq1$q>sX+m7D z^vpB7xN+T321e$>BNP0f{3Mv!S!OBeSgC2#n7E61CR*|4XT(^9(4()wxz_UbWe`e` z#Jln`ldNO!K4y$vRKAmR%RWa{5cf3P@za9HgJ7NY@95b<;%fr?PAOTPUDM$GNaA@z#KcgpH!{BB@)7GmIPP4FA~)7b!;g}D&H9~l8=wT8hjujP z-8gv*zY+xh-DtEVG${wjmh3SsRm35|mzU}tL zT6SZ{aSGAJJ>af$x8mEpeTo_L(OZiJok3% zWp7qh$gbOB*EogO)do#LjM4NeE4bh zuJ>j{jim$nE(32&^D*;8bNmPnx>6}`(meH&qP%L(yrl?p79_CcaV>7Xeg}&Fz};ai z{wQFOnNlmyNKdQwS)wFB-(Fo%42ko?OA=j38Tig#AZ>h}6lj8P{Q9`u9(HkvCtoc$ z*j+=lrNhVW$Z`2%ZK|;SXL^C-t;NhjmdfuJKLW=yzYRW&j#p@Ft1*kfs^fSuYS(d;WhZ!t068QDPJ#+JI`&d#PcDhf>KBChZp#jSU$KC zlBm%#OF|HjW3?eGs_1ShF6L7ZV^DTi^Y3^0-L-nG>KJ+h0r zq)f`L4j4ZC`sLLoLVlv(cFXJ}h4AN?q5E~iuWn#OJ;Y6xFYic{%`^=CKp@>v=4^j* zk~*vdpCA|0YKX-1kN?y9!D=s z(ppuvWL$5qmn=G}Rq@rDNXV7^cmSZ+kzPEz$>>#@DEjUd`a;es__iXc?-^PM__hKNz6uD3+KHITzy5eoJb+AN2<(G%Ck?V}ivaLV#*tyE8 zia7?(BkpCyF;3N-eR4k#M?+Ska1bg{B?NP;F`cf}_bU%!z-!Z?;f$|u!s%HAVc6Wxy7 zlP10jOF8EU7rCmbUON1gvx8rQVp!qqq@+HSbha+pJmXj28N`@YD}!{VSO*?%fPB|~ z9ci7h8Y5tt5pc~v+x%w0ovm+sVaYI7JL^cr;IB7BKHd8DYW{iKclVc9oEF0OIoNLu z@z6z|i+-A;4l=T1E0?Q9{~J?X8-^I literal 18235 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 G7XA;SX(ZDC literal 18777 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 X%fCkL#lDgaX&ejdN;jaq{QsK(NVo;U diff --git a/AVL Tree/Images/RotationStep3.jpg b/AVL Tree/Images/RotationStep3.jpg index b2045111352b8ba18af53a3841e6368217beae04..921c0c4bac40c5ce1c0367fa2206b3eb3e0e27b1 100644 GIT binary patch delta 12042 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 Date: Wed, 21 Dec 2016 23:27:41 +0100 Subject: [PATCH 0063/1039] Update README.markdown --- AVL Tree/README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 9254ffedf..eaa4aa3c3 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -57,6 +57,7 @@ For the rotation we're using the terminology: ![Rotation1](Images/RotationStep1.jpg) ![Rotation2](Images/RotationStep2.jpg) ![Rotation3](Images/RotationStep3.jpg) The steps of rotation on the example image 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 From 39ac2ec3c36cf0cdf239d2b9b279258bd0f96dbb Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 21 Dec 2016 23:30:49 +0100 Subject: [PATCH 0064/1039] Update README.markdown --- AVL Tree/README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index eaa4aa3c3..8358fde9c 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -62,6 +62,7 @@ The steps of rotation on the example image could be described by following: 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 From 9ecd211c61cfd4baab2665b10dc7c79547f5ec4b Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 21 Dec 2016 23:31:44 +0100 Subject: [PATCH 0065/1039] Update README.markdown --- AVL Tree/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 8358fde9c..86b631ae8 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -45,7 +45,8 @@ If after an insertion or deletion the balance factor becomes greater than 1, the ## 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. -Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: +Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: + ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: From bd645f33bc3640586c992e6b2c54728b4e50bccb Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 21 Dec 2016 23:33:22 +0100 Subject: [PATCH 0066/1039] Update README.markdown --- AVL Tree/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 86b631ae8..355204587 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -45,8 +45,6 @@ If after an insertion or deletion the balance factor becomes greater than 1, the ## 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. -Example of balancing the unbalanced tree using *Right* (clockwise direction) rotation: - ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: @@ -55,9 +53,11 @@ For the rotation we're using the terminology: * *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 on the example image could be described by following: +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*; From b64df56ea624b77b126cbc64d42ab7d687f05e1e Mon Sep 17 00:00:00 2001 From: BenEmdon Date: Thu, 22 Dec 2016 00:35:37 -0500 Subject: [PATCH 0067/1039] Fixed comment spacing in playground --- .../Contents.swift | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Rootish Array Stack/RootishArrayStack.playground/Contents.swift b/Rootish Array Stack/RootishArrayStack.playground/Contents.swift index 401c773d6..68ec0a53e 100644 --- a/Rootish Array Stack/RootishArrayStack.playground/Contents.swift +++ b/Rootish Array Stack/RootishArrayStack.playground/Contents.swift @@ -144,22 +144,22 @@ extension RootishArrayStack: CustomStringConvertible { } var list = RootishArrayStack() -list.isEmpty // true -list.first // nil -list.last // nil -list.count // 0 -list.capacity // 0 +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.isEmpty // false +list.first // "Hello" +list.last // "hello" +list.count // 1 +list.capacity // 1 list.memoryDescription // { @@ -167,15 +167,15 @@ list.memoryDescription // } list.append(element: "World") -list.isEmpty // false -list.first // "Hello" -list.last // "World" -list.count // 2 -list.capacity // 3 +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[0] // "Hello" +list[1] // "World" +//list[2] // crash! list.memoryDescription @@ -186,15 +186,15 @@ list.memoryDescription list.insert(element: "Swift", atIndex: 1) -list.isEmpty // false -list.first // "Hello" -list.last // "World" -list.count // 3 -list.capacity // 6 +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[0] // "Hello" +list[1] // "Swift" +list[2] // "World" list.memoryDescription // { @@ -203,17 +203,17 @@ list.memoryDescription // [nil, nil, nil] // } -list.remove(atIndex: 2) // "World" -list.isEmpty // false -list.first // "Hello" -list.last // "Swift" -list.count // 2 -list.capacity // 3 +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] // "Hello" +list[1] // "Swift" +//list[2] // crash! list[0] = list[1] list[1] = "is awesome" -list // ["Swift", "is awesome"] +list // ["Swift", "is awesome"] From 3dd067453818046186792746479bdd4986c3ef7b Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:13:39 -0700 Subject: [PATCH 0068/1039] Update palindrome swift file contents --- Palindromes/Palindromes.swift | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index 889ff357e..2760137ca 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -1,17 +1,26 @@ -import Cocoa +import Foundation -public func palindromeCheck(text: String?) -> Bool { - if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() - let length: Int = mutableText.characters.count +func isPalindrome(_ str: String) -> Bool { + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count - if length == 1 || length == 0 { - return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.index(mutableText.endIndex, offsetBy: -1)] { - let range = Range(mutableText.index(mutableText.startIndex, offsetBy: 1).. 1 { + return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } - } - - return false + 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) } From fe93184c3899f0ee6aebc23c453ce14fbddf4db8 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:13:57 -0700 Subject: [PATCH 0069/1039] Update palindrome playground --- .../Palindromes.playground/Contents.swift | 81 ++++++++++++------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index bb666ee9a..e8562a367 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -1,34 +1,61 @@ -import Cocoa +//: Playground - noun: a place where people can play -public func palindromeCheck(text: String?) -> Bool { - if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces).lowercased() - let length: Int = mutableText.characters.count +import Foundation + +/** + Validate that a string is a plaindrome + - parameter str: The string to validate + - returns: `true` if string is plaindrome, `false` if string is not + */ +func isPalindrome(_ str: String) -> Bool { + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count - if length == 1 || length == 0 { - return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.index(mutableText.endIndex, offsetBy: -1)] { - let range = Range(mutableText.index(mutableText.startIndex, offsetBy: 1).. 1 { + return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } - } - - return false + return false } -// Test to check that non-palindromes are handled correctly: -palindromeCheck(text: "owls") - -// Test to check that palindromes are accurately found (regardless of case and whitespace: -palindromeCheck(text: "lol") -palindromeCheck(text: "race car") -palindromeCheck(text: "Race fast Safe car") - -// Test to check that palindromes are found regardless of case: -palindromeCheck(text: "HelloLLEH") +/** + 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) +} -palindromeCheck(text: "moom") +//true +isPalindrome("A man, a plan, a canal, Panama!") +isPalindrome("abbcbba") +isPalindrome("racecar") +isPalindrome("Madam, I'm Adam") +isPalindrome("Madam in Eden, I'm Adam") +isPalindrome("Never odd or even") +isPalindrome("5885") +isPalindrome("5 8 8 5") +isPalindrome("58 85") +isPalindrome("৯৯") +isPalindrome("In girum imus nocte et consumimur igni") -// Test that nil and empty Strings return false: -palindromeCheck(text: "") -palindromeCheck(text: nil) +// false +isPalindrome("\\\\") +isPalindrome("desserts") +isPalindrome("😀😀") +isPalindrome("") +isPalindrome("a") +isPalindrome("power") From 33048487610b59b9c7e09cafb1f33573bda5e252 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:15:07 -0700 Subject: [PATCH 0070/1039] Update the read for palindromes --- Palindromes/README.markdown | 101 ++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 12f868251..fe31cf297 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -1,64 +1,99 @@ # Palindromes -A palindrome is a word or phrase that is spelled the exact same when read forwards or backwards. -For this example puzzle, palindromes will not take case into account, meaning that uppercase and -lowercase text will be treated the same. In addition, spaces will not be considered, allowing -for multi-word phrases to constitute palindromes too. +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 "radar" is spelled the exact same both forwards and backwards, and as a result is a palindrome. -The phrase "race car" is another common palindrome that is spelled the same forwards and backwards. +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, the first and last characters of a String must be compared for equality. -When the first and last characters are the same, they are removed from the String, resulting in a -substring starting with the second character and ending at the second to last character. +To check for palindromes, a strings character are compared starting from the beginning and end and moving inward moving to toward the middle of the string and keep the same distance apart in the comparison index. -In this implementation of a palindrome checker, recursion is used to check each substring of the -original String. +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 palindromeCheck (text: String?) -> Bool { - if let text = text { - let mutableText = text.trimmingCharacters(in: NSCharacterSet.whitespaces()).lowercased() - let length: Int = mutableText.characters.count - - guard length >= 1 else { - return false - } - - if length == 1 { - return true - } else if mutableText[mutableText.startIndex] == mutableText[mutableText.index(mutableText.endIndex, offsetBy: -1)] { - let range = Range(mutableText.index(mutableText.startIndex, offsetBy: 1).. Bool { +let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) +let length = strippedString.characters.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. -This code can be tested in a playground using the following: +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 -palindromeCheck(text: "Race car") +return palindrome(str, left: left + 1, right: right - 1) ``` -Since the phrase "Race car" is a palindrome, this will return true. +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 [Stephen Rutstein](https://github.com/srutstein21)* +*Written by [Joshua Alvarado](https://github.com/https://github.com/lostatseajoshua)* From 0ffeb1fdd0d4568270b4bef42fef73e89fb108d9 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:28:44 -0700 Subject: [PATCH 0071/1039] Update README formatting --- Palindromes/README.markdown | 48 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index fe31cf297..48420f323 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -7,6 +7,7 @@ Algorithms that check for palindromes are a common programming interview questio ## 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?` @@ -14,9 +15,7 @@ The word racecar is a valid palindrome, as it is a word spelled the same when ba ## Algorithm -To check for palindromes, a strings character are compared starting from the beginning and end and moving inward moving to toward the middle of the string and keep the same distance apart in the comparison index. - -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. +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 @@ -24,32 +23,33 @@ 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.characters.count + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count -if length > 1 { -return palindrome(strippedString.lowercased(), left: 0, right: length - 1) -} -return false + 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 -} + if left >= right { + return true + } -let lhs = str[str.index(str.startIndex, offsetBy: left)] -let rhs = str[str.index(str.startIndex, offsetBy: right)] + let lhs = str[str.index(str.startIndex, offsetBy: left)] + let rhs = str[str.index(str.startIndex, offsetBy: right)] -if lhs != rhs { -return false -} + if lhs != rhs { + return false + } -return palindrome(str, left: left + 1, right: right - 1) + return palindrome(str, left: left + 1, right: right - 1) } ``` -This algorithm has a two-step process. +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 @@ -61,7 +61,7 @@ The length of the string is then checked to make sure that the string after bein 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 + 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. @@ -70,7 +70,7 @@ let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { -return false + 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. @@ -82,14 +82,18 @@ 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 +racecar -> left index == right index -> return true``` ## Additional Resources From e4c2889bc3c8b6ba0f9fa47be0b86bb1f5c663d3 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:30:15 -0700 Subject: [PATCH 0072/1039] Fix code snippet from running to the bottom of the page --- Palindromes/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 48420f323..53a48225a 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -93,7 +93,8 @@ racecar -> a == a racecar -> c == c | -racecar -> left index == right index -> return true``` +racecar -> left index == right index -> return true +``` ## Additional Resources From 8c0117dbe7fa5dace9de1492280110f0d6353ea4 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:34:57 -0700 Subject: [PATCH 0073/1039] Fix spacing on list of palindrome examples --- Palindromes/README.markdown | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 53a48225a..85bdfc992 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -8,10 +8,12 @@ Algorithms that check for palindromes are a common programming interview questio 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` +``` +raceCar +r a c e c a r +r?a?c?e?c?a?r? +RACEcar +``` ## Algorithm From 13de04998d7f940c5c98bedb947ccee52fa0fe9d Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:35:38 -0700 Subject: [PATCH 0074/1039] Improved formatting in code and markdown --- Palindromes/README.markdown | 47 +++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 85bdfc992..ede0af39d 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -25,34 +25,34 @@ 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.characters.count +let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) +let length = strippedString.characters.count - if length > 1 { - return palindrome(strippedString.lowercased(), left: 0, right: length - 1) - } - return false +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 - } +if left >= right { +return true +} - let lhs = str[str.index(str.startIndex, offsetBy: left)] - let rhs = str[str.index(str.startIndex, offsetBy: right)] +let lhs = str[str.index(str.startIndex, offsetBy: left)] +let rhs = str[str.index(str.startIndex, offsetBy: right)] - if lhs != rhs { - return false - } +if lhs != rhs { +return false +} - return palindrome(str, left: left + 1, right: right - 1) +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. +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) @@ -60,10 +60,10 @@ let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .reg 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. +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 +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. @@ -72,7 +72,7 @@ let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { - return false +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. @@ -81,20 +81,21 @@ return palindrome(str, left: left + 1, right: right - 1) ``` Step 1: -` race?C ar -> raceCar -> racecar`` + +`race?C ar -> raceCar -> racecar` Step 2: ``` | | racecar -> r == r - | | +| | racecar -> a == a - | | +| | racecar -> c == c - | +| racecar -> left index == right index -> return true ``` From 6a15d37a61310e7fd05c944f6be947605508b8f1 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:37:31 -0700 Subject: [PATCH 0075/1039] Revert "Improved formatting in code and markdown" This reverts commit 13de04998d7f940c5c98bedb947ccee52fa0fe9d. --- Palindromes/README.markdown | 47 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index ede0af39d..85bdfc992 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -25,34 +25,34 @@ 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.characters.count + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.count -if length > 1 { -return palindrome(strippedString.lowercased(), left: 0, right: length - 1) -} -return false + 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 -} + if left >= right { + return true + } -let lhs = str[str.index(str.startIndex, offsetBy: left)] -let rhs = str[str.index(str.startIndex, offsetBy: right)] + let lhs = str[str.index(str.startIndex, offsetBy: left)] + let rhs = str[str.index(str.startIndex, offsetBy: right)] -if lhs != rhs { -return false -} + if lhs != rhs { + return false + } -return palindrome(str, left: left + 1, right: right - 1) + 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. +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) @@ -60,10 +60,10 @@ let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .reg 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. +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 + 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. @@ -72,7 +72,7 @@ let lhs = str[str.index(str.startIndex, offsetBy: left)] let rhs = str[str.index(str.startIndex, offsetBy: right)] if lhs != rhs { -return false + 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. @@ -81,21 +81,20 @@ return palindrome(str, left: left + 1, right: right - 1) ``` Step 1: - -`race?C ar -> raceCar -> racecar` +` race?C ar -> raceCar -> racecar`` Step 2: ``` | | racecar -> r == r -| | + | | racecar -> a == a -| | + | | racecar -> c == c -| + | racecar -> left index == right index -> return true ``` From f8888192086c2a542fc9550441a1cb41b7b51e90 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:37:59 -0700 Subject: [PATCH 0076/1039] Remove extra character --- Palindromes/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index 85bdfc992..bb52678e0 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -81,7 +81,7 @@ return palindrome(str, left: left + 1, right: right - 1) ``` Step 1: -` race?C ar -> raceCar -> racecar`` +`race?C ar -> raceCar -> racecar` Step 2: ``` From 3da3a75413cf64aca60fc98e4987e9a804c12e48 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 11:39:18 -0700 Subject: [PATCH 0077/1039] Improved spacing on code snippet --- Palindromes/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Palindromes/README.markdown b/Palindromes/README.markdown index bb52678e0..18518adbe 100644 --- a/Palindromes/README.markdown +++ b/Palindromes/README.markdown @@ -31,7 +31,8 @@ func isPalindrome(_ str: String) -> Bool { if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } - return false + + return false } private func palindrome(_ str: String, left: Int, right: Int) -> Bool { From 9d4f6ea1204d2a6aa475cdbb2f6e412771b6b83b Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Thu, 22 Dec 2016 16:48:58 -0700 Subject: [PATCH 0078/1039] Add tests for Travis CI --- .travis.yml | 1 + .../Tests/Tests.xcodeproj/project.pbxproj | 413 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + Palindromes/Tests/Tests/AppDelegate.swift | 46 ++ .../AppIcon.appiconset/Contents.json | 68 +++ .../Tests/Base.lproj/LaunchScreen.storyboard | 27 ++ Palindromes/Tests/Tests/Info.plist | 45 ++ Palindromes/Tests/Tests/Palindromes.swift | 26 ++ Palindromes/Tests/TestsTests/Info.plist | 22 + .../Tests/TestsTests/PalindromeTests.swift | 70 +++ 10 files changed, 725 insertions(+) create mode 100644 Palindromes/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Palindromes/Tests/Tests/AppDelegate.swift create mode 100644 Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard create mode 100644 Palindromes/Tests/Tests/Info.plist create mode 100644 Palindromes/Tests/Tests/Palindromes.swift create mode 100644 Palindromes/Tests/TestsTests/Info.plist create mode 100644 Palindromes/Tests/TestsTests/PalindromeTests.swift diff --git a/.travis.yml b/.travis.yml index 17655c21e..f7231cdfe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,3 +40,4 @@ script: - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests +- xcodebuild test -project ./Palindromes/Tests/Tests.xcodeproj -scheme Tests diff --git a/Palindromes/Tests/Tests.xcodeproj/project.pbxproj b/Palindromes/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..63b68d316 --- /dev/null +++ b/Palindromes/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,413 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 94D8AF0F1E0C9AB4007D8806 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */; }; + 94D8AF161E0C9AB4007D8806 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */; }; + 94D8AF191E0C9AB4007D8806 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */; }; + 94D8AF2F1E0C9AE9007D8806 /* Palindromes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */; }; + 94D8AF331E0C9BB2007D8806 /* PalindromeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 94D8AF201E0C9AB4007D8806 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 94D8AF031E0C9AB4007D8806 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 94D8AF0A1E0C9AB4007D8806; + remoteInfo = Tests; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 94D8AF0B1E0C9AB4007D8806 /* Tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tests.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 94D8AF181E0C9AB4007D8806 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 94D8AF1A1E0C9AB4007D8806 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 94D8AF251E0C9AB4007D8806 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palindromes.swift; sourceTree = ""; }; + 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PalindromeTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 94D8AF081E0C9AB4007D8806 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 94D8AF1C1E0C9AB4007D8806 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 94D8AF021E0C9AB4007D8806 = { + isa = PBXGroup; + children = ( + 94D8AF0D1E0C9AB4007D8806 /* Tests */, + 94D8AF221E0C9AB4007D8806 /* TestsTests */, + 94D8AF0C1E0C9AB4007D8806 /* Products */, + ); + sourceTree = ""; + }; + 94D8AF0C1E0C9AB4007D8806 /* Products */ = { + isa = PBXGroup; + children = ( + 94D8AF0B1E0C9AB4007D8806 /* Tests.app */, + 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 94D8AF0D1E0C9AB4007D8806 /* Tests */ = { + isa = PBXGroup; + children = ( + 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */, + 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */, + 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */, + 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */, + 94D8AF1A1E0C9AB4007D8806 /* Info.plist */, + ); + path = Tests; + sourceTree = ""; + }; + 94D8AF221E0C9AB4007D8806 /* TestsTests */ = { + isa = PBXGroup; + children = ( + 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */, + 94D8AF251E0C9AB4007D8806 /* Info.plist */, + ); + path = TestsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 94D8AF0A1E0C9AB4007D8806 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 94D8AF281E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 94D8AF071E0C9AB4007D8806 /* Sources */, + 94D8AF081E0C9AB4007D8806 /* Frameworks */, + 94D8AF091E0C9AB4007D8806 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = 94D8AF0B1E0C9AB4007D8806 /* Tests.app */; + productType = "com.apple.product-type.application"; + }; + 94D8AF1E1E0C9AB4007D8806 /* TestsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 94D8AF2B1E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "TestsTests" */; + buildPhases = ( + 94D8AF1B1E0C9AB4007D8806 /* Sources */, + 94D8AF1C1E0C9AB4007D8806 /* Frameworks */, + 94D8AF1D1E0C9AB4007D8806 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 94D8AF211E0C9AB4007D8806 /* PBXTargetDependency */, + ); + name = TestsTests; + productName = TestsTests; + productReference = 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 94D8AF031E0C9AB4007D8806 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Joshua Alvarado"; + TargetAttributes = { + 94D8AF0A1E0C9AB4007D8806 = { + CreatedOnToolsVersion = 8.2; + ProvisioningStyle = Automatic; + }; + 94D8AF1E1E0C9AB4007D8806 = { + CreatedOnToolsVersion = 8.2; + LastSwiftMigration = 0820; + ProvisioningStyle = Automatic; + TestTargetID = 94D8AF0A1E0C9AB4007D8806; + }; + }; + }; + buildConfigurationList = 94D8AF061E0C9AB4007D8806 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 94D8AF021E0C9AB4007D8806; + productRefGroup = 94D8AF0C1E0C9AB4007D8806 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 94D8AF0A1E0C9AB4007D8806 /* Tests */, + 94D8AF1E1E0C9AB4007D8806 /* TestsTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 94D8AF091E0C9AB4007D8806 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 94D8AF191E0C9AB4007D8806 /* LaunchScreen.storyboard in Resources */, + 94D8AF161E0C9AB4007D8806 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 94D8AF1D1E0C9AB4007D8806 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 94D8AF071E0C9AB4007D8806 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 94D8AF2F1E0C9AE9007D8806 /* Palindromes.swift in Sources */, + 94D8AF0F1E0C9AB4007D8806 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 94D8AF1B1E0C9AB4007D8806 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 94D8AF331E0C9BB2007D8806 /* PalindromeTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 94D8AF211E0C9AB4007D8806 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 94D8AF0A1E0C9AB4007D8806 /* Tests */; + targetProxy = 94D8AF201E0C9AB4007D8806 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 94D8AF181E0C9AB4007D8806 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 94D8AF261E0C9AB4007D8806 /* 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[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; + }; + 94D8AF271E0C9AB4007D8806 /* 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[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; + }; + 94D8AF291E0C9AB4007D8806 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 94D8AF2A1E0C9AB4007D8806 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; + 94D8AF2C1E0C9AB4007D8806 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; + INFOPLIST_FILE = TestsTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.TestsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tests.app/Tests"; + }; + name = Debug; + }; + 94D8AF2D1E0C9AB4007D8806 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; + INFOPLIST_FILE = TestsTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = self.edu.TestsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tests.app/Tests"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 94D8AF061E0C9AB4007D8806 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 94D8AF261E0C9AB4007D8806 /* Debug */, + 94D8AF271E0C9AB4007D8806 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 94D8AF281E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 94D8AF291E0C9AB4007D8806 /* Debug */, + 94D8AF2A1E0C9AB4007D8806 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 94D8AF2B1E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "TestsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 94D8AF2C1E0C9AB4007D8806 /* Debug */, + 94D8AF2D1E0C9AB4007D8806 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 94D8AF031E0C9AB4007D8806 /* Project object */; +} diff --git a/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Palindromes/Tests/Tests/AppDelegate.swift b/Palindromes/Tests/Tests/AppDelegate.swift new file mode 100644 index 000000000..481c72c62 --- /dev/null +++ b/Palindromes/Tests/Tests/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// Tests +// +// Created by Joshua Alvarado on 12/22/16. +// Copyright © 2016 Joshua Alvarado. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + 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:. + } + + +} + diff --git a/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json b/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..36d2c80d8 --- /dev/null +++ b/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "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" : "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard b/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..fdf3f97d1 --- /dev/null +++ b/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Palindromes/Tests/Tests/Info.plist b/Palindromes/Tests/Tests/Info.plist new file mode 100644 index 000000000..f197d509b --- /dev/null +++ b/Palindromes/Tests/Tests/Info.plist @@ -0,0 +1,45 @@ + + + + + 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 + UIMainStoryboardFile + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Palindromes/Tests/Tests/Palindromes.swift b/Palindromes/Tests/Tests/Palindromes.swift new file mode 100644 index 000000000..2760137ca --- /dev/null +++ b/Palindromes/Tests/Tests/Palindromes.swift @@ -0,0 +1,26 @@ +import Foundation + +func isPalindrome(_ str: String) -> Bool { + let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) + let length = strippedString.characters.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) +} diff --git a/Palindromes/Tests/TestsTests/Info.plist b/Palindromes/Tests/TestsTests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Palindromes/Tests/TestsTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Palindromes/Tests/TestsTests/PalindromeTests.swift b/Palindromes/Tests/TestsTests/PalindromeTests.swift new file mode 100644 index 000000000..27d8f88b0 --- /dev/null +++ b/Palindromes/Tests/TestsTests/PalindromeTests.swift @@ -0,0 +1,70 @@ +// +// PalindromeTests.swift +// Tests +// +// Created by Joshua Alvarado on 12/22/16. +// Copyright © 2016 Joshua Alvarado. All rights reserved. +// + +import XCTest +@testable import Tests + +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. + let _ = isPalindrome("abbcbba") + let _ = isPalindrome("asdkfaksjdfasjkdfhaslkjdfakjsdfhakljsdhflkjasdfhkasdjhfklajsdfhkljasdf") + let _ = 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")) + } +} From 4d4b63d47ca048f58d1c0ddb30bc87648f45956c Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Fri, 23 Dec 2016 10:36:05 -0700 Subject: [PATCH 0079/1039] Update test project to run palindrome tests --- .travis.yml | 2 +- .../{Tests/Tests => Test}/Palindromes.swift | 0 .../Test/Test.xcodeproj/project.pbxproj | 273 ++++++++++++ .../contents.xcworkspacedata | 2 +- .../TestsTests => Test/Test}/Info.plist | 0 .../Test/Test.swift} | 9 +- .../Tests/Tests.xcodeproj/project.pbxproj | 413 ------------------ Palindromes/Tests/Tests/AppDelegate.swift | 46 -- .../AppIcon.appiconset/Contents.json | 68 --- .../Tests/Base.lproj/LaunchScreen.storyboard | 27 -- Palindromes/Tests/Tests/Info.plist | 45 -- 11 files changed, 279 insertions(+), 606 deletions(-) rename Palindromes/{Tests/Tests => Test}/Palindromes.swift (100%) create mode 100644 Palindromes/Test/Test.xcodeproj/project.pbxproj rename Palindromes/{Tests/Tests.xcodeproj => Test/Test.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (72%) rename Palindromes/{Tests/TestsTests => Test/Test}/Info.plist (100%) rename Palindromes/{Tests/TestsTests/PalindromeTests.swift => Test/Test/Test.swift} (96%) delete mode 100644 Palindromes/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Palindromes/Tests/Tests/AppDelegate.swift delete mode 100644 Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard delete mode 100644 Palindromes/Tests/Tests/Info.plist diff --git a/.travis.yml b/.travis.yml index f7231cdfe..dc681ccd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,4 +40,4 @@ script: - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests -- xcodebuild test -project ./Palindromes/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Palindromes/Test/Test.xcodeproj -scheme Test diff --git a/Palindromes/Tests/Tests/Palindromes.swift b/Palindromes/Test/Palindromes.swift similarity index 100% rename from Palindromes/Tests/Tests/Palindromes.swift rename to Palindromes/Test/Palindromes.swift diff --git a/Palindromes/Test/Test.xcodeproj/project.pbxproj b/Palindromes/Test/Test.xcodeproj/project.pbxproj new file mode 100644 index 000000000..07aae3e63 --- /dev/null +++ b/Palindromes/Test/Test.xcodeproj/project.pbxproj @@ -0,0 +1,273 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9437D8841E0D960A00A38FB8 /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437D8831E0D960A00A38FB8 /* Test.swift */; }; + 9437D88B1E0D969500A38FB8 /* Palindromes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9437D8791E0D948A00A38FB8 /* Palindromes.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9437D8791E0D948A00A38FB8 /* Palindromes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palindromes.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 /* Palindromes.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 = 0820; + ORGANIZATIONNAME = "Joshua Alvarado"; + TargetAttributes = { + 9437D8801E0D960A00A38FB8 = { + CreatedOnToolsVersion = 8.2; + 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 /* Palindromes.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_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.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_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.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_VERSION = 3.0; + }; + 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_VERSION = 3.0; + }; + 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; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9437D8661E0D945200A38FB8 /* Project object */; +} diff --git a/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Palindromes/Test/Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 72% rename from Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Palindromes/Test/Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 6c0ea8493..87cc241f8 100644 --- a/Palindromes/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Palindromes/Test/Test.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:Test.xcodeproj"> diff --git a/Palindromes/Tests/TestsTests/Info.plist b/Palindromes/Test/Test/Info.plist similarity index 100% rename from Palindromes/Tests/TestsTests/Info.plist rename to Palindromes/Test/Test/Info.plist diff --git a/Palindromes/Tests/TestsTests/PalindromeTests.swift b/Palindromes/Test/Test/Test.swift similarity index 96% rename from Palindromes/Tests/TestsTests/PalindromeTests.swift rename to Palindromes/Test/Test/Test.swift index 27d8f88b0..e86a40cfb 100644 --- a/Palindromes/Tests/TestsTests/PalindromeTests.swift +++ b/Palindromes/Test/Test/Test.swift @@ -1,13 +1,12 @@ // // PalindromeTests.swift -// Tests +// Test // -// Created by Joshua Alvarado on 12/22/16. +// Created by Joshua Alvarado on 12/23/16. // Copyright © 2016 Joshua Alvarado. All rights reserved. // import XCTest -@testable import Tests class PalindromeTests: XCTestCase { @@ -48,13 +47,13 @@ class PalindromeTests: XCTestCase { 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("৯৯")) } diff --git a/Palindromes/Tests/Tests.xcodeproj/project.pbxproj b/Palindromes/Tests/Tests.xcodeproj/project.pbxproj deleted file mode 100644 index 63b68d316..000000000 --- a/Palindromes/Tests/Tests.xcodeproj/project.pbxproj +++ /dev/null @@ -1,413 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 94D8AF0F1E0C9AB4007D8806 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */; }; - 94D8AF161E0C9AB4007D8806 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */; }; - 94D8AF191E0C9AB4007D8806 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */; }; - 94D8AF2F1E0C9AE9007D8806 /* Palindromes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */; }; - 94D8AF331E0C9BB2007D8806 /* PalindromeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 94D8AF201E0C9AB4007D8806 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 94D8AF031E0C9AB4007D8806 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 94D8AF0A1E0C9AB4007D8806; - remoteInfo = Tests; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 94D8AF0B1E0C9AB4007D8806 /* Tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tests.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 94D8AF181E0C9AB4007D8806 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 94D8AF1A1E0C9AB4007D8806 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TestsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 94D8AF251E0C9AB4007D8806 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palindromes.swift; sourceTree = ""; }; - 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PalindromeTests.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 94D8AF081E0C9AB4007D8806 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 94D8AF1C1E0C9AB4007D8806 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 94D8AF021E0C9AB4007D8806 = { - isa = PBXGroup; - children = ( - 94D8AF0D1E0C9AB4007D8806 /* Tests */, - 94D8AF221E0C9AB4007D8806 /* TestsTests */, - 94D8AF0C1E0C9AB4007D8806 /* Products */, - ); - sourceTree = ""; - }; - 94D8AF0C1E0C9AB4007D8806 /* Products */ = { - isa = PBXGroup; - children = ( - 94D8AF0B1E0C9AB4007D8806 /* Tests.app */, - 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 94D8AF0D1E0C9AB4007D8806 /* Tests */ = { - isa = PBXGroup; - children = ( - 94D8AF0E1E0C9AB4007D8806 /* AppDelegate.swift */, - 94D8AF2E1E0C9AE9007D8806 /* Palindromes.swift */, - 94D8AF151E0C9AB4007D8806 /* Assets.xcassets */, - 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */, - 94D8AF1A1E0C9AB4007D8806 /* Info.plist */, - ); - path = Tests; - sourceTree = ""; - }; - 94D8AF221E0C9AB4007D8806 /* TestsTests */ = { - isa = PBXGroup; - children = ( - 94D8AF321E0C9BB2007D8806 /* PalindromeTests.swift */, - 94D8AF251E0C9AB4007D8806 /* Info.plist */, - ); - path = TestsTests; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 94D8AF0A1E0C9AB4007D8806 /* Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 94D8AF281E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "Tests" */; - buildPhases = ( - 94D8AF071E0C9AB4007D8806 /* Sources */, - 94D8AF081E0C9AB4007D8806 /* Frameworks */, - 94D8AF091E0C9AB4007D8806 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Tests; - productName = Tests; - productReference = 94D8AF0B1E0C9AB4007D8806 /* Tests.app */; - productType = "com.apple.product-type.application"; - }; - 94D8AF1E1E0C9AB4007D8806 /* TestsTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 94D8AF2B1E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "TestsTests" */; - buildPhases = ( - 94D8AF1B1E0C9AB4007D8806 /* Sources */, - 94D8AF1C1E0C9AB4007D8806 /* Frameworks */, - 94D8AF1D1E0C9AB4007D8806 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 94D8AF211E0C9AB4007D8806 /* PBXTargetDependency */, - ); - name = TestsTests; - productName = TestsTests; - productReference = 94D8AF1F1E0C9AB4007D8806 /* TestsTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 94D8AF031E0C9AB4007D8806 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0820; - LastUpgradeCheck = 0820; - ORGANIZATIONNAME = "Joshua Alvarado"; - TargetAttributes = { - 94D8AF0A1E0C9AB4007D8806 = { - CreatedOnToolsVersion = 8.2; - ProvisioningStyle = Automatic; - }; - 94D8AF1E1E0C9AB4007D8806 = { - CreatedOnToolsVersion = 8.2; - LastSwiftMigration = 0820; - ProvisioningStyle = Automatic; - TestTargetID = 94D8AF0A1E0C9AB4007D8806; - }; - }; - }; - buildConfigurationList = 94D8AF061E0C9AB4007D8806 /* Build configuration list for PBXProject "Tests" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 94D8AF021E0C9AB4007D8806; - productRefGroup = 94D8AF0C1E0C9AB4007D8806 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 94D8AF0A1E0C9AB4007D8806 /* Tests */, - 94D8AF1E1E0C9AB4007D8806 /* TestsTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 94D8AF091E0C9AB4007D8806 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 94D8AF191E0C9AB4007D8806 /* LaunchScreen.storyboard in Resources */, - 94D8AF161E0C9AB4007D8806 /* Assets.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 94D8AF1D1E0C9AB4007D8806 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 94D8AF071E0C9AB4007D8806 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 94D8AF2F1E0C9AE9007D8806 /* Palindromes.swift in Sources */, - 94D8AF0F1E0C9AB4007D8806 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 94D8AF1B1E0C9AB4007D8806 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 94D8AF331E0C9BB2007D8806 /* PalindromeTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 94D8AF211E0C9AB4007D8806 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 94D8AF0A1E0C9AB4007D8806 /* Tests */; - targetProxy = 94D8AF201E0C9AB4007D8806 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 94D8AF171E0C9AB4007D8806 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 94D8AF181E0C9AB4007D8806 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 94D8AF261E0C9AB4007D8806 /* 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[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; - }; - 94D8AF271E0C9AB4007D8806 /* 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[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; - }; - 94D8AF291E0C9AB4007D8806 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.Tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - }; - name = Debug; - }; - 94D8AF2A1E0C9AB4007D8806 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.Tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - }; - name = Release; - }; - 94D8AF2C1E0C9AB4007D8806 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ENABLE_MODULES = YES; - INFOPLIST_FILE = TestsTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.TestsTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tests.app/Tests"; - }; - name = Debug; - }; - 94D8AF2D1E0C9AB4007D8806 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ENABLE_MODULES = YES; - INFOPLIST_FILE = TestsTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = self.edu.TestsTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tests.app/Tests"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 94D8AF061E0C9AB4007D8806 /* Build configuration list for PBXProject "Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 94D8AF261E0C9AB4007D8806 /* Debug */, - 94D8AF271E0C9AB4007D8806 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 94D8AF281E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 94D8AF291E0C9AB4007D8806 /* Debug */, - 94D8AF2A1E0C9AB4007D8806 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; - 94D8AF2B1E0C9AB4007D8806 /* Build configuration list for PBXNativeTarget "TestsTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 94D8AF2C1E0C9AB4007D8806 /* Debug */, - 94D8AF2D1E0C9AB4007D8806 /* Release */, - ); - defaultConfigurationIsVisible = 0; - }; -/* End XCConfigurationList section */ - }; - rootObject = 94D8AF031E0C9AB4007D8806 /* Project object */; -} diff --git a/Palindromes/Tests/Tests/AppDelegate.swift b/Palindromes/Tests/Tests/AppDelegate.swift deleted file mode 100644 index 481c72c62..000000000 --- a/Palindromes/Tests/Tests/AppDelegate.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// AppDelegate.swift -// Tests -// -// Created by Joshua Alvarado on 12/22/16. -// Copyright © 2016 Joshua Alvarado. All rights reserved. -// - -import UIKit - -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - 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:. - } - - -} - diff --git a/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json b/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 36d2c80d8..000000000 --- a/Palindromes/Tests/Tests/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "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" : "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" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard b/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index fdf3f97d1..000000000 --- a/Palindromes/Tests/Tests/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Palindromes/Tests/Tests/Info.plist b/Palindromes/Tests/Tests/Info.plist deleted file mode 100644 index f197d509b..000000000 --- a/Palindromes/Tests/Tests/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - 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 - UIMainStoryboardFile - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - From 9ac2d762802de647082a7b5977bad4bf9e1db8d6 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 24 Dec 2016 03:39:44 -0800 Subject: [PATCH 0080/1039] Fixed up indentation and removed a few self references. --- .../BoyerMoore.playground/Contents.swift | 114 +++++++++--------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 362a298f9..9bbc7ec19 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -1,66 +1,66 @@ //: Playground - noun: a place where people can play extension String { - func indexOf(pattern: String) -> 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.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) - - // 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.characters.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 = self.index(startIndex, offsetBy: patternLength - 1) + func indexOf(pattern: String) -> 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.characters.count + assert(patternLength > 0) + assert(patternLength <= characters.count) + + // 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.characters.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() -> String.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 { - // 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() -> String.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 - } + // There is a possible match. Do a brute-force search backwards. + if let k = backwards() { return k } - // The main loop. Keep going until the end of the string is reached. - while i < self.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 = self.index(i, offsetBy: skipTable[c] ?? patternLength) - } - } - return nil + // 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) + } } + return nil + } } // A few simple tests From 7a0417e86553dbe67495deba9f16f2ccdf14b3ea Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:18:55 -0300 Subject: [PATCH 0081/1039] Added some tests. There are a failing test in the original code. --- Boyer-Moore/Tests/BoyerMooreTests.swift | 67 +++++ Boyer-Moore/Tests/Info.plist | 24 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 269 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 90 ++++++ 5 files changed, 457 insertions(+) create mode 100755 Boyer-Moore/Tests/BoyerMooreTests.swift create mode 100644 Boyer-Moore/Tests/Info.plist create mode 100644 Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Boyer-Moore/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Boyer-Moore/Tests/BoyerMooreTests.swift b/Boyer-Moore/Tests/BoyerMooreTests.swift new file mode 100755 index 000000000..6536d1800 --- /dev/null +++ b/Boyer-Moore/Tests/BoyerMooreTests.swift @@ -0,0 +1,67 @@ +import Foundation +import XCTest + +class BoyerMooreTest: XCTestCase { + override func setUp() { + super.setUp() + } + + func assert(pattern: String, doesNotExistsIn string: String) { + let index = string.indexOf(pattern: pattern) + XCTAssertNil(index) + } + + func assert(pattern: String, existsIn string: String) { + let index = string.indexOf(pattern: pattern) + XCTAssertNotNil(index) + + let startIndex = index! + let endIndex = string.index(index!, offsetBy: pattern.characters.count) + let match = string.substring(with: startIndex.. + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj b/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..ff4f401a1 --- /dev/null +++ b/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,269 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */; }; + 9AED567C1E0ED6DE00958DCC /* BoyerMoore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AED567B1E0ED6DE00958DCC /* BoyerMoore.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; }; + 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoyerMoore.swift; path = ../../BoyerMoore.swift; sourceTree = ""; }; +/* 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 = ( + 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */, + 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.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 = ( + 9AED567C1E0ED6DE00958DCC /* BoyerMoore.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_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 */; +} diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Boyer-Moore/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..14f27f777 --- /dev/null +++ b/Boyer-Moore/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 2be65b442aafa1c96456322c50039dca8184a1e0 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:19:58 -0300 Subject: [PATCH 0082/1039] Fix failing test. --- Boyer-Moore/BoyerMoore.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 4d7660ec3..d8ff4e6d2 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -61,7 +61,7 @@ extension String { // 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 = self.index(i, offsetBy: skipTable[c] ?? patternLength) + i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex } } return nil From 4ca7ab9fc784afc018f6dde770fc54afc952664a Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:22:59 -0300 Subject: [PATCH 0083/1039] Add Boyer-Moore-Horspool algorithm and tests. --- Boyer-Moore/BoyerMoore.swift | 14 +++++++++++--- Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift | 14 ++++++++++++++ Boyer-Moore/Tests/BoyerMooreTests.swift | 14 ++++++++++++-- Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj | 4 ++++ 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index d8ff4e6d2..24842b59e 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -6,7 +6,7 @@ http://www.drdobbs.com/database/faster-string-searches/184408171 */ extension String { - func indexOf(pattern: String) -> String.Index? { + func indexOf(pattern: String, useHorspoolImprovement: Bool = false) -> 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.characters.count @@ -53,8 +53,16 @@ extension String { // 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) + if !useHorspoolImprovement { + // 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 diff --git a/Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift b/Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift new file mode 100644 index 000000000..3924494c7 --- /dev/null +++ b/Boyer-Moore/Tests/BoyerMooreHorspoolTests.swift @@ -0,0 +1,14 @@ +// +// 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 + } +} diff --git a/Boyer-Moore/Tests/BoyerMooreTests.swift b/Boyer-Moore/Tests/BoyerMooreTests.swift index 6536d1800..8a2cbdc77 100755 --- a/Boyer-Moore/Tests/BoyerMooreTests.swift +++ b/Boyer-Moore/Tests/BoyerMooreTests.swift @@ -1,18 +1,28 @@ +// +// 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.indexOf(pattern: pattern) + let index = string.indexOf(pattern: pattern, useHorspoolImprovement: useHorspoolImprovement) XCTAssertNil(index) } func assert(pattern: String, existsIn string: String) { - let index = string.indexOf(pattern: pattern) + let index = string.indexOf(pattern: pattern, useHorspoolImprovement: useHorspoolImprovement) XCTAssertNotNil(index) let startIndex = index! diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj b/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj index ff4f401a1..f263d846a 100644 --- a/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj +++ b/Boyer-Moore/Tests/Tests.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */; }; 9AED567C1E0ED6DE00958DCC /* BoyerMoore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */; }; + 9AED56801E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -16,6 +17,7 @@ 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; }; 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoyerMoore.swift; path = ../../BoyerMoore.swift; sourceTree = ""; }; + 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoyerMooreHorspoolTests.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -51,6 +53,7 @@ 9AED567B1E0ED6DE00958DCC /* BoyerMoore.swift */, 7B80C3CD1C77A256003CECC7 /* BoyerMooreTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, + 9AED567F1E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift */, ); name = Tests; path = TestsTests; @@ -125,6 +128,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9AED56801E0EE60B00958DCC /* BoyerMooreHorspoolTests.swift in Sources */, 9AED567C1E0ED6DE00958DCC /* BoyerMoore.swift in Sources */, 7B80C3CE1C77A256003CECC7 /* BoyerMooreTests.swift in Sources */, ); From 36fba8ac3f4da6595783f5ebd4e72d19d1621c21 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:25:27 -0300 Subject: [PATCH 0084/1039] Add tests to .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 17655c21e..38099490e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ script: - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Boyer-Moore/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests From c3cad8c13314eda236ca3d98650c5a79c89861e8 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:30:32 -0300 Subject: [PATCH 0085/1039] Updated README: updated algorithms and credits. --- Boyer-Moore/README.markdown | 92 ++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 576f6d17b..08347e3e7 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -87,7 +87,7 @@ extension String { // 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 = self.index(i, offsetBy: skipTable[c] ?? patternLength) + i = index(i, offsetBy: skipTable[c] ?? patternLength, limitedBy: endIndex) ?? endIndex } } return nil @@ -158,40 +158,66 @@ Here's an implementation of the Boyer-Moore-Horspool algorithm: ```swift extension String { func indexOf(pattern: String) -> String.Index? { - let patternLength = pattern.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.count) + // 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.characters.count + assert(patternLength > 0) + assert(patternLength <= self.characters.count) - var skipTable = [Character: Int]() - for (i, c) in pattern.characters.enumerated() { - skipTable[c] = patternLength - i - 1 - } + // 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.characters.enumerated() { + skipTable[c] = patternLength - i - 1 + } - let p = pattern.index(before: pattern.endIndex) - let lastChar = pattern[p] - var i = self.index(startIndex, offsetBy: patternLength - 1) - - func backwards() -> String.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 - } + // This points at the last character in the pattern. + let p = pattern.index(before: pattern.endIndex) + let lastChar = pattern[p] - while i < self.endIndex { - let c = self[i] - if c == lastChar { - if let k = backwards() { return k } - i = index(after: i) - } else { - i = index(i, offsetBy: skipTable[c] ?? patternLength) - } - } - return nil + // 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 = self.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() -> String.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 < self.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 } } ``` @@ -200,4 +226,4 @@ In practice, the Horspool version of the algorithm tends to perform a little bet 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üß_ +_Written for Swift Algorithm Club by Matthijs Hollemans, updated by Andreas Neusüß_, [Matías Mazzei](https://github.com/mmazzei). From 78e78a4b9e81b57698d95e68d8abbd86c218ef95 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sat, 24 Dec 2016 14:42:54 -0300 Subject: [PATCH 0086/1039] Fix swiftlint warnings. --- Boyer-Moore/Tests/BoyerMooreTests.swift | 20 +++++++++---------- .../Tests/Tests.xcodeproj/project.pbxproj | 17 ++++++++++++++++ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Boyer-Moore/Tests/BoyerMooreTests.swift b/Boyer-Moore/Tests/BoyerMooreTests.swift index 8a2cbdc77..f1638afcd 100755 --- a/Boyer-Moore/Tests/BoyerMooreTests.swift +++ b/Boyer-Moore/Tests/BoyerMooreTests.swift @@ -30,48 +30,48 @@ class BoyerMooreTest: XCTestCase { let match = string.substring(with: startIndex.. Date: Sat, 24 Dec 2016 14:47:56 -0300 Subject: [PATCH 0087/1039] Xcode option 'Uncheck Autocreate schemes' unchecked. --- .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Boyer-Moore/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + From cf45ebd0dd84a842a1d032f7545e70c76b2cbb79 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sun, 25 Dec 2016 15:08:31 -0300 Subject: [PATCH 0088/1039] Update as requested in code review. --- .../BoyerMoore.playground/Contents.swift | 143 ++++++++++-------- Boyer-Moore/BoyerMoore.swift | 35 ++--- Boyer-Moore/README.markdown | 28 ++-- Boyer-Moore/Tests/BoyerMooreTests.swift | 22 ++- 4 files changed, 135 insertions(+), 93 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index 9bbc7ec19..f1ae5018e 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -1,72 +1,91 @@ //: 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 indexOf(pattern: String) -> 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.characters.count - assert(patternLength > 0) - assert(patternLength <= characters.count) - - // 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.characters.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() -> String.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) - } + func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { + // There are no possible match in an empty string + guard !isEmpty else { return nil } + + // 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.characters.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.characters.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 } - return nil - } } // A few simple tests -let s = "Hello, World" -s.indexOf(pattern: "World") // 7 +let str = "Hello, World" +str.index(of: "World") // 7 let animals = "🐶🐔🐷🐮🐱" -animals.indexOf(pattern: "🐮") // 6 +animals.index(of: "🐮") // 6 + +let lorem = "Lorem ipsum dolor sit amet" +lorem.index(of: "sit", usingHorspoolImprovement: true) // 18 diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 24842b59e..2f6bf1392 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -6,33 +6,35 @@ http://www.drdobbs.com/database/faster-string-searches/184408171 */ extension String { - func indexOf(pattern: String, useHorspoolImprovement: Bool = false) -> String.Index? { + func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { + // There are no possible match in an empty string + guard !isEmpty else { return nil } + // 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.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.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.characters.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 = self.index(startIndex, offsetBy: patternLength - 1) - + 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() -> String.Index? { + func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { @@ -42,22 +44,21 @@ extension String { } return j } - + // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { + 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 !useHorspoolImprovement { + + if !usingHorspoolImprovement { // If no match, we can only safely skip one character ahead. i = index(after: i) - } - else { + } 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) diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 08347e3e7..2cb42b0bd 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -32,12 +32,14 @@ Here's how you could write it in Swift: ```swift extension String { - func indexOf(pattern: String) -> String.Index? { + func index(of pattern: String) -> Index? { + // There are no possible match in an empty string + guard !isEmpty else { return nil } + // 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.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.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. @@ -53,12 +55,12 @@ extension String { // 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 = self.index(startIndex, offsetBy: patternLength - 1) + 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() -> String.Index? { + func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { @@ -70,7 +72,7 @@ extension String { } // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { + while i < endIndex { let c = self[i] // Does the current character match the last character from the pattern? @@ -157,12 +159,14 @@ Here's an implementation of the Boyer-Moore-Horspool algorithm: ```swift extension String { - func indexOf(pattern: String) -> String.Index? { + func index(of pattern: String) -> Index? { + // There are no possible match in an empty string + guard !isEmpty else { return nil } + // 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.characters.count - assert(patternLength > 0) - assert(patternLength <= self.characters.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. @@ -178,12 +182,12 @@ extension String { // 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 = self.index(startIndex, offsetBy: patternLength - 1) + 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() -> String.Index? { + func backwards() -> Index? { var q = p var j = i while q > pattern.startIndex { @@ -195,7 +199,7 @@ extension String { } // The main loop. Keep going until the end of the string is reached. - while i < self.endIndex { + while i < endIndex { let c = self[i] // Does the current character match the last character from the pattern? diff --git a/Boyer-Moore/Tests/BoyerMooreTests.swift b/Boyer-Moore/Tests/BoyerMooreTests.swift index f1638afcd..9efe60874 100755 --- a/Boyer-Moore/Tests/BoyerMooreTests.swift +++ b/Boyer-Moore/Tests/BoyerMooreTests.swift @@ -17,12 +17,12 @@ class BoyerMooreTest: XCTestCase { } func assert(pattern: String, doesNotExistsIn string: String) { - let index = string.indexOf(pattern: pattern, useHorspoolImprovement: useHorspoolImprovement) + let index = string.index(of: pattern, usingHorspoolImprovement: useHorspoolImprovement) XCTAssertNil(index) } func assert(pattern: String, existsIn string: String) { - let index = string.indexOf(pattern: pattern, useHorspoolImprovement: useHorspoolImprovement) + let index = string.index(of: pattern, usingHorspoolImprovement: useHorspoolImprovement) XCTAssertNotNil(index) let startIndex = index! @@ -31,6 +31,24 @@ class BoyerMooreTest: XCTestCase { XCTAssertEqual(match, pattern) } + func testSearchPatternInEmptyString() { + let string = "" + let pattern = "ABCDEF" + assert(pattern: pattern, doesNotExistsIn: string) + } + + func testSearchEmptyPatternString() { + let string = "ABCDEF" + let pattern = "" + assert(pattern: pattern, doesNotExistsIn: string) + } + + func testSearchPatternLongerThanString() { + let string = "ABC" + let pattern = "ABCDEF" + assert(pattern: pattern, doesNotExistsIn: string) + } + func testSearchTheSameString() { let string = "ABCDEF" let pattern = "ABCDEF" From 960bca13c0207014040b96ba22e586b688279be9 Mon Sep 17 00:00:00 2001 From: mmazzei Date: Sun, 25 Dec 2016 17:58:00 -0300 Subject: [PATCH 0089/1039] Removed redundant validation. --- Boyer-Moore/BoyerMoore.playground/Contents.swift | 3 --- Boyer-Moore/BoyerMoore.swift | 3 --- Boyer-Moore/README.markdown | 6 ------ 3 files changed, 12 deletions(-) diff --git a/Boyer-Moore/BoyerMoore.playground/Contents.swift b/Boyer-Moore/BoyerMoore.playground/Contents.swift index f1ae5018e..f553e1a00 100644 --- a/Boyer-Moore/BoyerMoore.playground/Contents.swift +++ b/Boyer-Moore/BoyerMoore.playground/Contents.swift @@ -9,9 +9,6 @@ */ extension String { func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { - // There are no possible match in an empty string - guard !isEmpty else { return nil } - // 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.characters.count diff --git a/Boyer-Moore/BoyerMoore.swift b/Boyer-Moore/BoyerMoore.swift index 2f6bf1392..af8aea9d9 100644 --- a/Boyer-Moore/BoyerMoore.swift +++ b/Boyer-Moore/BoyerMoore.swift @@ -7,9 +7,6 @@ */ extension String { func index(of pattern: String, usingHorspoolImprovement: Bool = false) -> Index? { - // There are no possible match in an empty string - guard !isEmpty else { return nil } - // 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.characters.count diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index 2cb42b0bd..e821b812e 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -33,9 +33,6 @@ Here's how you could write it in Swift: ```swift extension String { func index(of pattern: String) -> Index? { - // There are no possible match in an empty string - guard !isEmpty else { return nil } - // 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.characters.count @@ -160,9 +157,6 @@ Here's an implementation of the Boyer-Moore-Horspool algorithm: ```swift extension String { func index(of pattern: String) -> Index? { - // There are no possible match in an empty string - guard !isEmpty else { return nil } - // 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.characters.count From f618414c65e8b45f7f11010ad988e733cea23395 Mon Sep 17 00:00:00 2001 From: Joshua Alvarado Date: Mon, 26 Dec 2016 11:31:54 -0700 Subject: [PATCH 0090/1039] Add shared scheme to test Project for tests --- .../xcshareddata/xcschemes/Test.xcscheme | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme diff --git a/Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme b/Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme new file mode 100644 index 000000000..9a1b39e69 --- /dev/null +++ b/Palindromes/Test/Test.xcodeproj/xcshareddata/xcschemes/Test.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d8b96a480aeaefd3ead13c409c6957071ecfc931 Mon Sep 17 00:00:00 2001 From: Nagasawa Hiroki Date: Wed, 28 Dec 2016 08:34:51 +0900 Subject: [PATCH 0091/1039] Fix Access Control position in AVLTree --- AVL Tree/AVLTree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AVL Tree/AVLTree.swift b/AVL Tree/AVLTree.swift index b4b97f0d6..cfcf114c0 100644 --- a/AVL Tree/AVLTree.swift +++ b/AVL Tree/AVLTree.swift @@ -29,7 +29,7 @@ public class TreeNode { internal var leftChild: Node? internal var rightChild: Node? fileprivate var height: Int - weak fileprivate var parent: Node? + fileprivate weak var parent: Node? public init(key: Key, payload: Payload?, leftChild: Node?, rightChild: Node?, parent: Node?, height: Int) { self.key = key From 03f176083b22b1ba2c40e0fb0f21af8d0451424b Mon Sep 17 00:00:00 2001 From: Nagasawa Hiroki Date: Wed, 28 Dec 2016 10:16:36 +0900 Subject: [PATCH 0092/1039] Make each steps clear --- Red-Black Tree/README.markdown | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Red-Black Tree/README.markdown b/Red-Black Tree/README.markdown index d4e86a095..05993f016 100644 --- a/Red-Black Tree/README.markdown +++ b/Red-Black Tree/README.markdown @@ -49,16 +49,17 @@ n n n n n b We create a new node with the value to be inserted into the tree. The color of this new node is always red. We perform a standard BST insert with this node. Now the three might not be a valid RBT anymore. -We now go through several insertion steps in order to make the tree valid again. We call the just inserted node n. -1. We check if n is the rootNode, if so we paint it black and we are done. If not we go to step 2. +We now go through several insertion steps in order to make the tree valid again. We call the just inserted node n. + +**Step 1**: We check if n is the rootNode, if so we paint it black and we are done. If not we go to Step 2. We now know that n at least has a parent as it is not the rootNode. -2. We check if the parent of n is black if so we are done. If not we go to step 3. +**Step 2**: We check if the parent of n is black if so we are done. If not we go to Step 3. We now know the parent is also not the root node as the parent is red. Thus n also has a grandparent and thus also an uncle as every node has two children. This uncle may however be a nullLeaf -3. We check if n's uncle is red. If not we go to 4. If n's uncle is indeed red we recolor uncle and parent to black and n's grandparent to red. We now go back to step 1 performing the same logic on n's grandparent. +**Step 3**: We check if n's uncle is red. If not we go to Step 4. If n's uncle is indeed red we recolor uncle and parent to black and n's grandparent to red. We now go back to step 1 performing the same logic on n's grandparent. From here there are four cases: - **The left left case.** n's parent is the left child of its parent and n is the left child of its parent. @@ -66,14 +67,14 @@ From here there are four cases: - **The right right case** n's parent is the right child of its parent and n is the right child of its parent. - **The right left case** n's parent is the right child of its parent and n is the left child of its parent. -4. Step 4 checks if either the **left right** case or the **right left** case applies to the current situation. - - If we find the **left right case**, we left rotate n's parent and go to step 5 while setting n to n's parent. (This transforms the **left right** case into the **left left** case) - - If we find the **right left case**, we right rotate n's parent and go to step 5 while setting n to n's parent. (This transforms the **right left** case into the **right right** case) - - If we find neither of these two we proceed to step 5. +**Step 4**: checks if either the **left right** case or the **right left** case applies to the current situation. + - If we find the **left right case**, we left rotate n's parent and go to Step 5 while setting n to n's parent. (This transforms the **left right** case into the **left left** case) + - If we find the **right left case**, we right rotate n's parent and go to Step 5 while setting n to n's parent. (This transforms the **right left** case into the **right right** case) + - If we find neither of these two we proceed to Step 5. n's parent is now red, while n's grandparent is black. -5. We swap the colors of n's parent and grandparent. +**Step 5**: We swap the colors of n's parent and grandparent. - We either right rotate n's grandparent in case of the **left left** case - Or we left rotate n's grandparent in case of the **right right** case From f8857406b07e0012c96d862e297669a04aba195a Mon Sep 17 00:00:00 2001 From: Mohamed Emad Hegab Date: Wed, 28 Dec 2016 10:55:57 +0100 Subject: [PATCH 0093/1039] swift 3 update --- Select Minimum Maximum/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index 5e006f50e..a67f4ec8e 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -89,7 +89,7 @@ The result is a minimum of `3` and a maximum of `9`. Here is a simple implementation in Swift: ```swift -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { +func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { guard !array.isEmpty else { return nil } From 411cbd208df10cb6a9bd9516bba3bae66173d7a6 Mon Sep 17 00:00:00 2001 From: mattthousand Date: Wed, 28 Dec 2016 13:33:29 -0500 Subject: [PATCH 0094/1039] Convert to swift 3.0 syntax. --- Heap Sort/HeapSort.playground/Contents.swift | 21 +++++++++++++++++++ Heap Sort/HeapSort.swift | 6 +++--- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Heap/Heap.swift | 18 ++++++++-------- 5 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 Heap Sort/HeapSort.playground/Contents.swift diff --git a/Heap Sort/HeapSort.playground/Contents.swift b/Heap Sort/HeapSort.playground/Contents.swift new file mode 100644 index 000000000..5dbe2e14f --- /dev/null +++ b/Heap Sort/HeapSort.playground/Contents.swift @@ -0,0 +1,21 @@ +//: Playground - noun: a place where people can play + +extension Heap { + public mutating func sort() -> [T] { + for i in (elements.count - 1).stride(through: 1, by: -1) { + swap(&elements[0], &elements[i]) + shiftDown(index: 0, heapSize: i) + } + return elements + } +} + +/* + 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: (T, T) -> Bool) -> [T] { + let reverseOrder = { i1, i2 in sort(i2, i1) } + var h = Heap(array: a, sort: reverseOrder) + return h.sort() +} diff --git a/Heap Sort/HeapSort.swift b/Heap Sort/HeapSort.swift index ec5b4a478..3fbaab14d 100644 --- a/Heap Sort/HeapSort.swift +++ b/Heap Sort/HeapSort.swift @@ -1,8 +1,8 @@ extension Heap { public mutating func sort() -> [T] { - for i in (elements.count - 1).stride(through: 1, by: -1) { + for i in stride(from: (elements.count - 1), through: 1, by: -1) { swap(&elements[0], &elements[i]) - shiftDown(index: 0, heapSize: i) + shiftDown(0, heapSize: i) } return elements } @@ -12,7 +12,7 @@ extension Heap { 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: (T, T) -> Bool) -> [T] { +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() diff --git a/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj b/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj index 454222c49..f7f101cd6 100644 --- a/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Heap Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -149,8 +150,10 @@ 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 = "-"; @@ -193,8 +196,10 @@ 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 = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -224,6 +230,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +242,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Heap Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ { fileprivate mutating func buildHeap(fromArray array: [T]) { elements = array for i in stride(from: (elements.count/2 - 1), through: 0, by: -1) { - shiftDown(index: i, heapSize: elements.count) + shiftDown(i, heapSize: elements.count) } } @@ -98,7 +98,7 @@ public struct Heap { */ public mutating func insert(_ value: T) { elements.append(value) - shiftUp(index: elements.count - 1) + shiftUp(elements.count - 1) } public mutating func insert(_ sequence: S) where S.Iterator.Element == T { @@ -116,7 +116,7 @@ public struct Heap { assert(isOrderedBefore(value, elements[i])) elements[i] = value - shiftUp(index: i) + shiftUp(i) } /** @@ -142,14 +142,14 @@ public struct Heap { * 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? { + public mutating func removeAt(_ index: Int) -> T? { guard index < elements.count else { return nil } let size = elements.count - 1 if index != size { swap(&elements[index], &elements[size]) - shiftDown(index: index, heapSize: size) - shiftUp(index: index) + shiftDown(index, heapSize: size) + shiftUp(index) } return elements.removeLast() } @@ -158,7 +158,7 @@ public struct Heap { * 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) { + mutating func shiftUp(_ index: Int) { var childIndex = index let child = elements[childIndex] var parentIndex = self.parentIndex(ofIndex: childIndex) @@ -173,14 +173,14 @@ public struct Heap { } mutating func shiftDown() { - shiftDown(index: 0, heapSize: elements.count) + 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) { + mutating func shiftDown(_ index: Int, heapSize: Int) { var parentIndex = index while true { From 75d866a0b9df43a2803bcad6f25f3151f51b73c2 Mon Sep 17 00:00:00 2001 From: mattthousand Date: Wed, 28 Dec 2016 13:35:51 -0500 Subject: [PATCH 0095/1039] Update README. --- Heap Sort/README.markdown | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Heap Sort/README.markdown b/Heap Sort/README.markdown index 3d8b0f394..5f047f82b 100644 --- a/Heap Sort/README.markdown +++ b/Heap Sort/README.markdown @@ -48,13 +48,13 @@ Here's how you can implement heap sort in Swift: ```swift extension Heap { - public mutating func sort() -> [T] { - for i in (elements.count - 1).stride(through: 1, by: -1) { - swap(&elements[0], &elements[i]) - shiftDown(index: 0, heapSize: i) - } + 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 - } + } } ``` @@ -70,10 +70,10 @@ Because we need a max-heap to sort from low-to-high, you need to give `Heap` the We can write a handy helper function for that: ```swift -public func heapsort(a: [T], _ sort: (T, T) -> Bool) -> [T] { - let reverseOrder = { i1, i2 in sort(i2, i1) } - var h = Heap(array: a, sort: reverseOrder) - return h.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() } ``` From bb5cbe6e839501edbc6a75d9c99748511b369040 Mon Sep 17 00:00:00 2001 From: mattthousand Date: Wed, 28 Dec 2016 13:39:53 -0500 Subject: [PATCH 0096/1039] Uncomment .travis.yml. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7b5faffa6..79eb3e051 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ script: # - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests # - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests From 6a15e73d72369d44d1b5b118c1e2f45f04b504b7 Mon Sep 17 00:00:00 2001 From: mattthousand Date: Wed, 28 Dec 2016 13:41:50 -0500 Subject: [PATCH 0097/1039] Remove playground. --- Heap Sort/HeapSort.playground/Contents.swift | 21 -------------------- 1 file changed, 21 deletions(-) delete mode 100644 Heap Sort/HeapSort.playground/Contents.swift diff --git a/Heap Sort/HeapSort.playground/Contents.swift b/Heap Sort/HeapSort.playground/Contents.swift deleted file mode 100644 index 5dbe2e14f..000000000 --- a/Heap Sort/HeapSort.playground/Contents.swift +++ /dev/null @@ -1,21 +0,0 @@ -//: Playground - noun: a place where people can play - -extension Heap { - public mutating func sort() -> [T] { - for i in (elements.count - 1).stride(through: 1, by: -1) { - swap(&elements[0], &elements[i]) - shiftDown(index: 0, heapSize: i) - } - return elements - } -} - -/* - 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: (T, T) -> Bool) -> [T] { - let reverseOrder = { i1, i2 in sort(i2, i1) } - var h = Heap(array: a, sort: reverseOrder) - return h.sort() -} From 356844c7d61630b4aa09eb9e3d3d785593cf86e2 Mon Sep 17 00:00:00 2001 From: cruisediary Date: Thu, 29 Dec 2016 18:18:14 +0900 Subject: [PATCH 0098/1039] Updating to Swift3 (enum lowercase) - playground - README.md - some.swift file --- .../Contents.swift | 2 +- .../Sources/BinarySearchTree.swift | 54 ++++++------- .../Solution 2/BinarySearchTree.swift | 54 ++++++------- .../CountingSort.playground/Contents.swift | 6 +- Counting Sort/CountingSort.swift | 4 +- Linked List/README.markdown | 4 +- .../ShuntingYard.playground/Contents.swift | 78 +++++++++---------- Shunting Yard/ShuntingYard.swift | 62 +++++++-------- 8 files changed, 132 insertions(+), 132 deletions(-) diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift index 12fbba81d..8df69fb6a 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift @@ -1,7 +1,7 @@ //: 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) +var tree = BinarySearchTree.leaf(7) tree = tree.insert(newValue: 2) tree = tree.insert(newValue: 5) tree = tree.insert(newValue: 10) diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift index b692efdc4..5128bb348 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -4,25 +4,25 @@ 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) + 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 + 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) + case .empty: return 0 + case .leaf: return 1 + case let .node(left, _, right): return 1 + max(left.height, right.height) } } @@ -32,21 +32,21 @@ public enum BinarySearchTree { */ public func insert(newValue: T) -> BinarySearchTree { switch self { - case .Empty: - return .Leaf(newValue) + case .empty: + return .leaf(newValue) - case .Leaf(let value): + case .leaf(let value): if newValue < value { - return .Node(.Leaf(newValue), value, .Empty) + return .node(.leaf(newValue), value, .empty) } else { - return .Node(.Empty, value, .Leaf(newValue)) + return .node(.empty, value, .leaf(newValue)) } - case .Node(let left, let value, let right): + case .node(let left, let value, let right): if newValue < value { - return .Node(left.insert(newValue: newValue), value, right) + return .node(left.insert(newValue: newValue), value, right) } else { - return .Node(left, value, right.insert(newValue: newValue)) + return .node(left, value, right.insert(newValue: newValue)) } } } @@ -57,11 +57,11 @@ public enum BinarySearchTree { */ public func search(x: T) -> BinarySearchTree? { switch self { - case .Empty: + case .empty: return nil - case .Leaf(let y): + case .leaf(let y): return (x == y) ? self : nil - case let .Node(left, y, right): + case let .node(left, y, right): if x < y { return left.search(x: x) } else if y < x { @@ -82,11 +82,11 @@ public enum BinarySearchTree { public func minimum() -> BinarySearchTree { var node = self var prev = node - while case let .Node(next, _, _) = node { + while case let .node(next, _, _) = node { prev = node node = next } - if case .Leaf = node { + if case .leaf = node { return node } return prev @@ -98,11 +98,11 @@ public enum BinarySearchTree { public func maximum() -> BinarySearchTree { var node = self var prev = node - while case let .Node(_, _, next) = node { + while case let .node(_, _, next) = node { prev = node node = next } - if case .Leaf = node { + if case .leaf = node { return node } return prev @@ -112,9 +112,9 @@ public enum BinarySearchTree { 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): + case .empty: return "." + case .leaf(let value): return "\(value)" + case .node(let left, let value, let right): return "(\(left.debugDescription) <- \(value) -> \(right.debugDescription))" } } diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.swift b/Binary Search Tree/Solution 2/BinarySearchTree.swift index ce2868bbf..272b86368 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.swift @@ -4,25 +4,25 @@ 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) + 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 + 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) + case .empty: return 0 + case .leaf: return 1 + case let .node(left, _, right): return 1 + max(left.height, right.height) } } @@ -32,21 +32,21 @@ public enum BinarySearchTree { */ public func insert(newValue: T) -> BinarySearchTree { switch self { - case .Empty: - return .Leaf(newValue) + case .empty: + return .leaf(newValue) - case .Leaf(let value): + case .leaf(let value): if newValue < value { - return .Node(.Leaf(newValue), value, .Empty) + return .node(.leaf(newValue), value, .empty) } else { - return .Node(.Empty, value, .Leaf(newValue)) + return .node(.empty, value, .leaf(newValue)) } - case .Node(let left, let value, let right): + case .node(let left, let value, let right): if newValue < value { - return .Node(left.insert(newValue), value, right) + return .node(left.insert(newValue), value, right) } else { - return .Node(left, value, right.insert(newValue)) + return .node(left, value, right.insert(newValue)) } } } @@ -57,11 +57,11 @@ public enum BinarySearchTree { */ public func search(x: T) -> BinarySearchTree? { switch self { - case .Empty: + case .empty: return nil - case .Leaf(let y): + case .leaf(let y): return (x == y) ? self : nil - case let .Node(left, y, right): + case let .node(left, y, right): if x < y { return left.search(x) } else if y < x { @@ -82,11 +82,11 @@ public enum BinarySearchTree { public func minimum() -> BinarySearchTree { var node = self var prev = node - while case let .Node(next, _, _) = node { + while case let .node(next, _, _) = node { prev = node node = next } - if case .Leaf = node { + if case .leaf = node { return node } return prev @@ -98,11 +98,11 @@ public enum BinarySearchTree { public func maximum() -> BinarySearchTree { var node = self var prev = node - while case let .Node(_, _, next) = node { + while case let .node(_, _, next) = node { prev = node node = next } - if case .Leaf = node { + if case .leaf = node { return node } return prev @@ -112,9 +112,9 @@ public enum BinarySearchTree { 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): + case .empty: return "." + case .leaf(let value): return "\(value)" + case .node(let left, let value, let right): return "(\(left.debugDescription) <- \(value) -> \(right.debugDescription))" } } diff --git a/Counting Sort/CountingSort.playground/Contents.swift b/Counting Sort/CountingSort.playground/Contents.swift index 2d85347ef..1d84f8132 100644 --- a/Counting Sort/CountingSort.playground/Contents.swift +++ b/Counting Sort/CountingSort.playground/Contents.swift @@ -1,12 +1,12 @@ //: Playground - noun: a place where people can play enum CountingSortError: Error { - case ArrayEmpty + case arrayEmpty } func countingSort(array: [Int]) throws -> [Int] { guard array.count > 0 else { - throw CountingSortError.ArrayEmpty + throw CountingSortError.arrayEmpty } // Step 1 @@ -38,4 +38,4 @@ func countingSort(array: [Int]) throws -> [Int] { } -try countingSort(array: [10, 9, 8, 7, 1, 2, 7, 3]) \ No newline at end of file +try countingSort(array: [10, 9, 8, 7, 1, 2, 7, 3]) diff --git a/Counting Sort/CountingSort.swift b/Counting Sort/CountingSort.swift index ec8c5adcb..d37bb2eff 100644 --- a/Counting Sort/CountingSort.swift +++ b/Counting Sort/CountingSort.swift @@ -7,12 +7,12 @@ // enum CountingSortError: ErrorType { - case ArrayEmpty + case arrayEmpty } func countingSort(array: [Int]) throws -> [Int] { guard array.count > 0 else { - throw CountingSortError.ArrayEmpty + throw CountingSortError.arrayEmpty } // Step 1 diff --git a/Linked List/README.markdown b/Linked List/README.markdown index 7b2ec0c0d..1884aeb23 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -526,8 +526,8 @@ It is possible to implement a linked list with value semantics using an enum. Th ```swift enum ListNode { - indirect case Node(T, next: ListNode) - case End + indirect case node(T, next: ListNode) + case end } ``` diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index 04fed7739..707e2a0a3 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -1,51 +1,51 @@ //: Playground - noun: a place where people can play internal enum OperatorAssociativity { - case LeftAssociative - case RightAssociative + case leftAssociative + case rightAssociative } public enum OperatorType: CustomStringConvertible { - case Add - case Subtract - case Divide - case Multiply - case Percent - case Exponent + case add + case subtract + case divide + case multiply + case percent + case exponent public var description: String { switch self { - case Add: + case add: return "+" - case Subtract: + case subtract: return "-" - case Divide: + case divide: return "/" - case Multiply: + case multiply: return "*" - case Percent: + case percent: return "%" - case Exponent: + case exponent: return "^" } } } public enum TokenType: CustomStringConvertible { - case OpenBracket - case CloseBracket + case openBracket + case closeBracket case Operator(OperatorToken) - case Operand(Double) + case operand(Double) public var description: String { switch self { - case OpenBracket: + case openBracket: return "(" - case CloseBracket: + case closeBracket: return ")" case Operator(let operatorToken): return operatorToken.description - case Operand(let value): + case operand(let value): return "\(value)" } } @@ -60,21 +60,21 @@ public struct OperatorToken: CustomStringConvertible { var precedence: Int { switch operatorType { - case .Add, .Subtract: + case .add, .subtract: return 0 - case .Divide, .Multiply, .Percent: + case .divide, .multiply, .percent: return 5 - case .Exponent: + case .exponent: return 10 } } var associativity: OperatorAssociativity { switch operatorType { - case .Add, .Subtract, .Divide, .Multiply, .Percent: - return .LeftAssociative - case .Exponent: - return .RightAssociative + case .add, .subtract, .divide, .multiply, .percent: + return .leftAssociative + case .exponent: + return .rightAssociative } } @@ -99,7 +99,7 @@ public struct Token: CustomStringConvertible { } init(operand: Double) { - tokenType = .Operand(operand) + tokenType = .operand(operand) } init(operatorType: OperatorType) { @@ -108,7 +108,7 @@ public struct Token: CustomStringConvertible { var isOpenBracket: Bool { switch tokenType { - case .OpenBracket: + case .openBracket: return true default: return false @@ -175,14 +175,14 @@ public func reversePolishNotation(expression: [Token]) -> String { for token in expression { switch token.tokenType { - case .Operand(_): + case .operand(_): reversePolishNotation.append(token) - case .OpenBracket: + case .openBracket: tokenStack.push(token) - case .CloseBracket: - while tokenStack.count > 0, let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + case .closeBracket: + while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) } @@ -217,19 +217,19 @@ public func reversePolishNotation(expression: [Token]) -> String { let expr = InfixExpressionBuilder() .addOperand(3) - .addOperator(.Add) + .addOperator(.add) .addOperand(4) - .addOperator(.Multiply) + .addOperator(.multiply) .addOperand(2) - .addOperator(.Divide) + .addOperator(.divide) .addOpenBracket() .addOperand(1) - .addOperator(.Subtract) + .addOperator(.subtract) .addOperand(5) .addCloseBracket() - .addOperator(.Exponent) + .addOperator(.exponent) .addOperand(2) - .addOperator(.Exponent) + .addOperator(.exponent) .addOperand(3) .build() diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index 5159c9172..9d31d5a58 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -7,51 +7,51 @@ // internal enum OperatorAssociativity { - case LeftAssociative - case RightAssociative + case leftAssociative + case rightAssociative } public enum OperatorType: CustomStringConvertible { - case Add - case Subtract - case Divide - case Multiply - case Percent - case Exponent + case add + case subtract + case divide + case multiply + case percent + case exponent public var description: String { switch self { - case Add: + case add: return "+" - case Subtract: + case subtract: return "-" - case Divide: + case divide: return "/" - case Multiply: + case multiply: return "*" - case Percent: + case percent: return "%" - case Exponent: + case exponent: return "^" } } } public enum TokenType: CustomStringConvertible { - case OpenBracket - case CloseBracket + case openBracket + case closeBracket case Operator(OperatorToken) - case Operand(Double) + case operand(Double) public var description: String { switch self { - case OpenBracket: + case openBracket: return "(" - case CloseBracket: + case closeBracket: return ")" case Operator(let operatorToken): return operatorToken.description - case Operand(let value): + case operand(let value): return "\(value)" } } @@ -66,20 +66,20 @@ public struct OperatorToken: CustomStringConvertible { var precedence: Int { switch operatorType { - case .Add, .Subtract: + case .add, .subtract: return 0 - case .Divide, .Multiply, .Percent: + case .divide, .multiply, .percent: return 5 - case .Exponent: + case .exponent: return 10 } } var associativity: OperatorAssociativity { switch operatorType { - case .Add, .Subtract, .Divide, .Multiply, .Percent: + case .add, .subtract, .divide, .multiply, .percent: return .LeftAssociative - case .Exponent: + case .exponent: return .RightAssociative } } @@ -105,7 +105,7 @@ public struct Token: CustomStringConvertible { } init(operand: Double) { - tokenType = .Operand(operand) + tokenType = .operand(operand) } init(operatorType: OperatorType) { @@ -114,7 +114,7 @@ public struct Token: CustomStringConvertible { var isOpenBracket: Bool { switch tokenType { - case .OpenBracket: + case .openBracket: return true default: return false @@ -181,14 +181,14 @@ public func reversePolishNotation(expression: [Token]) -> String { for token in expression { switch token.tokenType { - case .Operand(_): + case .operand(_): reversePolishNotation.append(token) - case .OpenBracket: + case .openBracket: tokenStack.push(token) - case .CloseBracket: - while tokenStack.count > 0, let tempToken = tokenStack.pop() where !tempToken.isOpenBracket { + case .closeBracket: + while tokenStack.count > 0, let tempToken = tokenStack.pop(), !tempToken.isOpenBracket { reversePolishNotation.append(tempToken) } From e1517dc458375a589a4cfd49a3f7c0c16caaffd6 Mon Sep 17 00:00:00 2001 From: zaccone Date: Thu, 29 Dec 2016 14:34:48 -0500 Subject: [PATCH 0099/1039] Corrected a spelling error and removed the "get" syntax for a property. --- Trie/Trie/Trie/Trie.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index ad4e9f2e7..8f3b46123 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -16,9 +16,7 @@ class TrieNode { var children: [T: TrieNode] = [:] var isTerminating = false var isLeaf: Bool { - get { - return children.count == 0 - } + return children.count == 0 } /// Initializes a node. @@ -62,7 +60,7 @@ class Trie { fileprivate let root: Node fileprivate var wordCount: Int - /// Creats an empty trie. + /// Creates an empty trie. init() { root = Node() wordCount = 0 From 5021bc79cd44f1d8ae8f32780984759d2cc57b5a Mon Sep 17 00:00:00 2001 From: zaccone Date: Thu, 29 Dec 2016 16:48:29 -0500 Subject: [PATCH 0100/1039] Added NSCoding conformance. --- ...6ABF2F62-9363-4450-8DE1-D20F57026950.plist | 22 ++++++ .../Info.plist | 33 ++++++++ Trie/Trie/Trie/Trie.swift | 25 ++++++- Trie/Trie/TrieTests/TrieTests.swift | 75 +++++++++++-------- 4 files changed, 121 insertions(+), 34 deletions(-) create mode 100644 Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist create mode 100644 Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist diff --git a/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist new file mode 100644 index 000000000..01ff985c8 --- /dev/null +++ b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist @@ -0,0 +1,22 @@ + + + + + classNames + + TrieTests + + testInsertPerformance() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 3.0053 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist new file mode 100644 index 000000000..3c07f3d6a --- /dev/null +++ b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/Info.plist @@ -0,0 +1,33 @@ + + + + + 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 + + + + diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index 8f3b46123..ec3b1c5cc 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -43,7 +43,7 @@ class TrieNode { /// A trie data structure containing words. Each node is a single /// character of a word. -class Trie { +class Trie: NSObject, NSCoding { typealias Node = TrieNode /// The number of words in the trie public var count: Int { @@ -61,10 +61,31 @@ class Trie { fileprivate var wordCount: Int /// Creates an empty trie. - init() { + override init() { root = Node() wordCount = 0 } + + // 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 diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 236908ece..7ef02553f 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -12,20 +12,20 @@ import XCTest 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 wordArrayu and trie should + + /// 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. @@ -36,7 +36,7 @@ class TrieTests: XCTestCase { 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) @@ -48,24 +48,23 @@ class TrieTests: XCTestCase { 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 trie.count == 0 else { return } - let numberOfWordsToInsert = wordArray!.count - for i in 0.. Date: Thu, 29 Dec 2016 17:28:41 -0500 Subject: [PATCH 0101/1039] Added a ReadMe file. --- Trie/Trie/Trie.xcodeproj/project.pbxproj | 4 +++ Trie/Trie/Trie/ReadMe.md | 33 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Trie/Trie/Trie/ReadMe.md diff --git a/Trie/Trie/Trie.xcodeproj/project.pbxproj b/Trie/Trie/Trie.xcodeproj/project.pbxproj index 8d3611b6d..055885ee1 100644 --- a/Trie/Trie/Trie.xcodeproj/project.pbxproj +++ b/Trie/Trie/Trie.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 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 */; }; + EB8369AD1E15C5710003A7F8 /* ReadMe.md in Sources */ = {isa = PBXBuildFile; fileRef = EB8369AC1E15C5710003A7F8 /* ReadMe.md */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -51,6 +52,7 @@ 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 */ @@ -101,6 +103,7 @@ EB798DFC1DFEF79900F0628D /* Trie */ = { isa = PBXGroup; children = ( + EB8369AC1E15C5710003A7F8 /* ReadMe.md */, EB798DFD1DFEF79900F0628D /* AppDelegate.swift */, EB798DFF1DFEF79900F0628D /* ViewController.swift */, EB798E011DFEF79900F0628D /* Assets.xcassets */, @@ -267,6 +270,7 @@ files = ( EB798E291DFEF81400F0628D /* Trie.swift in Sources */, EB798E001DFEF79900F0628D /* ViewController.swift in Sources */, + EB8369AD1E15C5710003A7F8 /* ReadMe.md in Sources */, EB798DFE1DFEF79900F0628D /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Trie/Trie/Trie/ReadMe.md b/Trie/Trie/Trie/ReadMe.md new file mode 100644 index 000000000..934585a3f --- /dev/null +++ b/Trie/Trie/Trie/ReadMe.md @@ -0,0 +1,33 @@ +# 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. From 02ff5694e848fa5f39ab717b2c418e0fbf014190 Mon Sep 17 00:00:00 2001 From: Yohannes Wijaya Date: Fri, 30 Dec 2016 09:33:55 +0700 Subject: [PATCH 0102/1039] Added a new algorithms book under "Learn More" --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 5c769688a..6766e7025 100644 --- a/README.markdown +++ b/README.markdown @@ -198,6 +198,7 @@ For more information, check out these great books: - [The Algorithm Design Manual](http://www.algorist.com) by Skiena - [Elements of Programming Interviews](http://elementsofprogramminginterviews.com) by Aziz, Lee, Prakash - [Algorithms](http://www.cs.princeton.edu/~rs/) by Sedgewick +- [Grokking Algorithms](https://www.manning.com/books/grokking-algorithms) by Aditya Bhargava The following books are available for free online: From 89fb804a5f006f2bcbe9c55f784a277852484581 Mon Sep 17 00:00:00 2001 From: gonini Date: Mon, 2 Jan 2017 23:24:24 +0900 Subject: [PATCH 0103/1039] Updating to Swift3 I upgraded to swift 3 because it did not run as a grammar problem. --- .../Contents.swift | 24 +++++++++---------- .../timeline.xctimeline | 6 ----- .../Sources/Graph.swift | 8 +++---- .../Sources/Node.swift | 2 +- Shortest Path (Unweighted)/ShortestPath.swift | 2 +- 5 files changed, 18 insertions(+), 24 deletions(-) delete mode 100644 Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift index cfc582c49..2380ebb69 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift @@ -2,15 +2,15 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() - let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) - queue.enqueue(sourceInShortestPathsGraph) + 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(neighborNode) + queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } @@ -23,14 +23,14 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { 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 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) @@ -40,5 +40,5 @@ graph.addEdge(nodeC, neighbor: nodeF) graph.addEdge(nodeC, neighbor: nodeG) graph.addEdge(nodeE, neighbor: nodeH) -let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) +let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA) print(shortestPathGraph.nodes) diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline b/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Pages/Shortest path example.xcplaygroundpage/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift index 8cfb2a09c..8c3281aa8 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Graph.swift @@ -11,7 +11,7 @@ public class Graph: CustomStringConvertible, Equatable { return node } - public func addEdge(source: Node, neighbor: Node) { + public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } @@ -35,13 +35,13 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + duplicated.addNode(label: node.label) } for node in nodes { for edge in node.neighbors { - let source = duplicated.findNodeWithLabel(node.label) - let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label) + let source = duplicated.findNodeWithLabel(label: node.label) + let neighbour = duplicated.findNodeWithLabel(label: edge.neighbor.label) duplicated.addEdge(source, neighbor: neighbour) } } diff --git a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift index 37a3b3fdf..ebdb6f4e3 100644 --- a/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift +++ b/Shortest Path (Unweighted)/ShortestPath.playground/Sources/Node.swift @@ -23,7 +23,7 @@ public class Node: CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + neighbors.remove(at: neighbors.index { $0 === edge }!) } } diff --git a/Shortest Path (Unweighted)/ShortestPath.swift b/Shortest Path (Unweighted)/ShortestPath.swift index 13ed0c080..6aa082a96 100644 --- a/Shortest Path (Unweighted)/ShortestPath.swift +++ b/Shortest Path (Unweighted)/ShortestPath.swift @@ -10,7 +10,7 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { for edge in current.neighbors { let neighborNode = edge.neighbor if !neighborNode.hasDistance { - queue.enqueue(neighborNode) + queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } From 998fc13118dc7d7cefb7f088d3a70719ec5ea5d1 Mon Sep 17 00:00:00 2001 From: Mohamed Emad Hegab Date: Mon, 2 Jan 2017 15:44:58 +0100 Subject: [PATCH 0104/1039] Fix for swift 3 on playground and rest of the classes --- Select Minimum Maximum/Maximum.swift | 23 ++--- Select Minimum Maximum/Minimum.swift | 23 ++--- .../MinimumMaximumPairs.swift | 63 ++++++------ Select Minimum Maximum/README.markdown | 7 +- .../Contents.swift | 99 ++++++++++--------- .../timeline.xctimeline | 6 -- 6 files changed, 112 insertions(+), 109 deletions(-) delete mode 100644 Select Minimum Maximum/SelectMinimumMaximum.playground/timeline.xctimeline diff --git a/Select Minimum Maximum/Maximum.swift b/Select Minimum Maximum/Maximum.swift index 8c78ba478..991a0544e 100644 --- a/Select Minimum Maximum/Maximum.swift +++ b/Select Minimum Maximum/Maximum.swift @@ -1,15 +1,16 @@ /* - Finds the maximum value in an array in O(n) time. -*/ + Finds the maximum value in an array in O(n) time. + */ -func maximum(var array: [T]) -> T? { - guard !array.isEmpty else { - return nil - } +func maximum(_ array: [T]) -> T? { + var array = array + guard !array.isEmpty else { + return nil + } - var maximum = array.removeFirst() - for element in array { - maximum = element > maximum ? element : maximum - } - return maximum + var maximum = array.removeFirst() + for element in array { + maximum = element > maximum ? element : maximum + } + return maximum } diff --git a/Select Minimum Maximum/Minimum.swift b/Select Minimum Maximum/Minimum.swift index 9b08deb4f..90dfbd54b 100644 --- a/Select Minimum Maximum/Minimum.swift +++ b/Select Minimum Maximum/Minimum.swift @@ -1,15 +1,16 @@ /* - Finds the minimum value in an array in O(n) time. -*/ + Finds the minimum value in an array in O(n) time. + */ -func minimum(var array: [T]) -> T? { - guard !array.isEmpty else { - return nil - } +func minimum(_ array: [T]) -> T? { + var array = array + guard !array.isEmpty else { + return nil + } - var minimum = array.removeFirst() - for element in array { - minimum = element < minimum ? element : minimum - } - return minimum + var minimum = array.removeFirst() + for element in array { + minimum = element < minimum ? element : minimum + } + return minimum } diff --git a/Select Minimum Maximum/MinimumMaximumPairs.swift b/Select Minimum Maximum/MinimumMaximumPairs.swift index 5798e1f32..b7deb570a 100644 --- a/Select Minimum Maximum/MinimumMaximumPairs.swift +++ b/Select Minimum Maximum/MinimumMaximumPairs.swift @@ -1,39 +1,40 @@ /* - Finds the maximum and minimum value in an array in O(n) time. -*/ + Finds the maximum and minimum value in an array in O(n) time. + */ -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { - guard !array.isEmpty else { - return nil - } +func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { + var array = array + guard !array.isEmpty else { + return nil + } - var minimum = array.first! - var maximum = array.first! + var minimum = array.first! + var maximum = array.first! - let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } + let hasOddNumberOfItems = array.count % 2 != 0 + if hasOddNumberOfItems { + array.removeFirst() + } - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) + while !array.isEmpty { + let pair = (array.removeFirst(), array.removeFirst()) - 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 - } + 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) + + return (minimum, maximum) } diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index a67f4ec8e..09ca97039 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -23,7 +23,8 @@ Repeat this process until the all elements in the list have been processed. Here is a simple implementation in Swift: ```swift -func minimum(var array: [T]) -> T? { +func minimum(_ array: [T]) -> T? { + var array = array guard !array.isEmpty else { return nil } @@ -35,7 +36,8 @@ func minimum(var array: [T]) -> T? { return minimum } -func maximum(var array: [T]) -> T? { +func maximum(_ array: [T]) -> T? { + var array = array guard !array.isEmpty else { return nil } @@ -90,6 +92,7 @@ Here is a simple implementation in Swift: ```swift func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { + var array = array guard !array.isEmpty else { return nil } diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index ef92ac1e6..6076b5246 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -1,64 +1,67 @@ // Compare each item to find minimum -func minimum(var array: [T]) -> T? { - guard !array.isEmpty else { - return nil - } +func minimum(_ array: [T]) -> T? { + var array = array + guard !array.isEmpty else { + return nil + } - var minimum = array.removeFirst() - for element in array { - minimum = element < minimum ? element : minimum - } - return minimum + var minimum = array.removeFirst() + for element in array { + minimum = element < minimum ? element : minimum + } + return minimum } // Compare each item to find maximum -func maximum(var array: [T]) -> T? { - guard !array.isEmpty else { - return nil - } +func maximum(_ array: [T]) -> T? { + var array = array + guard !array.isEmpty else { + return nil + } - var maximum = array.removeFirst() - for element in array { - maximum = element > maximum ? element : maximum - } - return maximum + var maximum = array.removeFirst() + for element in array { + maximum = element > maximum ? element : maximum + } + return maximum } // Compare in pairs to find minimum and maximum -func minimumMaximum(var array: [T]) -> (minimum: T, maximum: T)? { - guard !array.isEmpty else { - return nil - } +func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { + var array = array + guard !array.isEmpty else { + return nil + } - var minimum = array.first! - var maximum = array.first! + var minimum = array.first! + var maximum = array.first! - let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } + let hasOddNumberOfItems = array.count % 2 != 0 + if hasOddNumberOfItems { + array.removeFirst() + } - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) + while !array.isEmpty { + let pair = (array.removeFirst(), array.removeFirst()) - 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 - } + 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) + return (minimum, maximum) } // Test of minimum and maximum functions @@ -72,5 +75,5 @@ result.minimum result.maximum // Built-in Swift functions -array.minElement() -array.maxElement() +array.min() +array.max() diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/timeline.xctimeline b/Select Minimum Maximum/SelectMinimumMaximum.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From dfc27f868b20b5ad6408238f7d97489ff518cd49 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 2 Jan 2017 07:52:15 -0800 Subject: [PATCH 0105/1039] Fixed indentation of the code. --- .../Contents.swift | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index 6076b5246..182060805 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -1,67 +1,67 @@ // Compare each item to find minimum func minimum(_ array: [T]) -> T? { - var array = array - guard !array.isEmpty else { - return nil - } - - var minimum = array.removeFirst() - for element in array { - minimum = element < minimum ? element : minimum - } - return minimum + var array = array + guard !array.isEmpty else { + return nil + } + + var minimum = array.removeFirst() + for element in array { + minimum = element < minimum ? element : minimum + } + return minimum } // Compare each item to find maximum func maximum(_ array: [T]) -> T? { - var array = array - guard !array.isEmpty else { - return nil - } - - var maximum = array.removeFirst() - for element in array { - maximum = element > maximum ? element : maximum - } - return maximum + var array = array + guard !array.isEmpty else { + return nil + } + + var maximum = array.removeFirst() + for element in array { + maximum = element > maximum ? element : maximum + } + return maximum } // Compare in pairs to find minimum and maximum func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { - var array = array - guard !array.isEmpty else { - return nil + var array = array + guard !array.isEmpty else { + return nil + } + + var minimum = array.first! + var maximum = array.first! + + let hasOddNumberOfItems = array.count % 2 != 0 + if hasOddNumberOfItems { + array.removeFirst() + } + + while !array.isEmpty { + let pair = (array.removeFirst(), array.removeFirst()) + + 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 + } } - - var minimum = array.first! - var maximum = array.first! - - let hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } - - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) - - 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) + } + + return (minimum, maximum) } // Test of minimum and maximum functions From 728d749d535359788d701296ce338b681fa18b1d Mon Sep 17 00:00:00 2001 From: Zhang Date: Tue, 3 Jan 2017 08:54:29 +0900 Subject: [PATCH 0106/1039] Update README. Convert to swift 3.0 syntax. --- Shortest Path (Unweighted)/README.markdown | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Shortest Path (Unweighted)/README.markdown b/Shortest Path (Unweighted)/README.markdown index 0107964ae..a16519260 100644 --- a/Shortest Path (Unweighted)/README.markdown +++ b/Shortest Path (Unweighted)/README.markdown @@ -23,7 +23,7 @@ The root of the tree is the node you started the breadth-first search from. To f Let's put breadth-first search into practice and calculate the shortest path from `A` to all the other nodes. We start with the source node `A` and add it to a queue with a distance of `0`. ```swift -queue.enqueue(A) +queue.enqueue(element: A) A.distance = 0 ``` @@ -31,9 +31,9 @@ The queue is now `[ A ]`. We dequeue `A` and enqueue its two immediate neighbor ```swift queue.dequeue() // A -queue.enqueue(B) +queue.enqueue(element: B) B.distance = A.distance + 1 // result: 1 -queue.enqueue(C) +queue.enqueue(element: C) C.distance = A.distance + 1 // result: 1 ``` @@ -41,9 +41,9 @@ The queue is now `[ B, C ]`. Dequeue `B` and enqueue `B`'s neighbor nodes `D` an ```swift queue.dequeue() // B -queue.enqueue(D) +queue.enqueue(element: D) D.distance = B.distance + 1 // result: 2 -queue.enqueue(E) +queue.enqueue(element: E) E.distance = B.distance + 1 // result: 2 ``` @@ -51,9 +51,9 @@ The queue is now `[ C, D, E ]`. Dequeue `C` and enqueue `C`'s neighbor nodes `F` ```swift queue.dequeue() // C -queue.enqueue(F) +queue.enqueue(element: F) F.distance = C.distance + 1 // result: 2 -queue.enqueue(G) +queue.enqueue(element: G) G.distance = C.distance + 1 // result: 2 ``` @@ -66,15 +66,15 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() - let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) - queue.enqueue(sourceInShortestPathsGraph) + 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(neighborNode) + queue.enqueue(element: neighborNode) neighborNode.distance = current.distance! + 1 } } @@ -87,7 +87,7 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { Put this code in a playground and test it like so: ```swift -let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA) +let shortestPathGraph = breadthFirstSearchShortestPath(graph: graph, source: nodeA) print(shortestPathGraph.nodes) ``` From b2688ad3cb3a9705aa73aa8fe54773192acd90a2 Mon Sep 17 00:00:00 2001 From: Zhang Date: Tue, 3 Jan 2017 09:26:34 +0900 Subject: [PATCH 0107/1039] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7b5faffa6..f6c64488d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ script: # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests From 6aab6200651772d8f6f7c1e7cf641f2242a784fe Mon Sep 17 00:00:00 2001 From: gonini Date: Tue, 3 Jan 2017 09:40:13 +0900 Subject: [PATCH 0108/1039] Updated with XCTest Swift3 syntax for shortest path --- Shortest Path (Unweighted)/Tests/Graph.swift | 159 +++++++++--------- .../Tests/ShortestPathTests.swift | 72 ++++---- 2 files changed, 116 insertions(+), 115 deletions(-) diff --git a/Shortest Path (Unweighted)/Tests/Graph.swift b/Shortest Path (Unweighted)/Tests/Graph.swift index ed71cab7c..0d2a735c2 100644 --- a/Shortest Path (Unweighted)/Tests/Graph.swift +++ b/Shortest Path (Unweighted)/Tests/Graph.swift @@ -1,106 +1,107 @@ // MARK: - Edge public class Edge: Equatable { - public var neighbor: Node - - public init(neighbor: Node) { - self.neighbor = neighbor - } + public var neighbor: Node + + public init(neighbor: Node) { + self.neighbor = neighbor + } } public func == (lhs: Edge, rhs: Edge) -> Bool { - return lhs.neighbor == rhs.neighbor + 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))" + 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 }!) } - return "Node(label: \(label), distance: infinity)" - } - - public var hasDistance: Bool { - return distance != nil - } - - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) - } } public func == (lhs: Node, rhs: Node) -> Bool { - return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors + 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})]" - } + public private(set) var nodes: [Node] + + public init() { + self.nodes = [] } - 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) + + public func addNode(label: String) -> Node { + let node = Node(label: label) + nodes.append(node) + return node } - - 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) - } + + 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 } - - return duplicated - } } public func == (lhs: Graph, rhs: Graph) -> Bool { - return lhs.nodes == rhs.nodes + return lhs.nodes == rhs.nodes } diff --git a/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift b/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift index 003f3cf20..71b9f88ab 100644 --- a/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift +++ b/Shortest Path (Unweighted)/Tests/ShortestPathTests.swift @@ -4,14 +4,14 @@ class ShortestPathTests: XCTestCase { func testShortestPathWhenGivenTree() { 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") + 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) @@ -20,30 +20,30 @@ class ShortestPathTests: XCTestCase { tree.addEdge(nodeC, neighbor: nodeG) tree.addEdge(nodeE, neighbor: nodeH) - let shortestPaths = breadthFirstSearchShortestPath(tree, source: nodeA) + let shortestPaths = breadthFirstSearchShortestPath(graph: tree, source: nodeA) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeA.label).distance, 0) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeB.label).distance, 1) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeC.label).distance, 1) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeD.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeE.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeF.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeG.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 3) + 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("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") + 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) @@ -74,16 +74,16 @@ class ShortestPathTests: XCTestCase { graph.addEdge(nodeI, neighbor: nodeG) graph.addEdge(nodeI, neighbor: nodeH) - let shortestPaths = breadthFirstSearchShortestPath(graph, source: nodeA) + let shortestPaths = breadthFirstSearchShortestPath(graph: graph, source: nodeA) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeA.label).distance, 0) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeB.label).distance, 1) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeC.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeD.label).distance, 3) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeE.label).distance, 4) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeF.label).distance, 3) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeG.label).distance, 2) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeH.label).distance, 1) - XCTAssertEqual(shortestPaths.findNodeWithLabel(nodeI.label).distance, 2) + 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) } } From 6eed97951a180899d8887c739bdb493e554e99da Mon Sep 17 00:00:00 2001 From: gonini Date: Tue, 3 Jan 2017 09:51:16 +0900 Subject: [PATCH 0109/1039] Updated with XCTest Swift3 syntax for shortest path XCTest Success --- Shortest Path (Unweighted)/ShortestPath.swift | 4 +-- Shortest Path (Unweighted)/Tests/Graph.swift | 34 +++++++++---------- Shortest Path (Unweighted)/Tests/Queue.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 3 ++ 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Shortest Path (Unweighted)/ShortestPath.swift b/Shortest Path (Unweighted)/ShortestPath.swift index 6aa082a96..555ad893b 100644 --- a/Shortest Path (Unweighted)/ShortestPath.swift +++ b/Shortest Path (Unweighted)/ShortestPath.swift @@ -2,8 +2,8 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph { let shortestPathGraph = graph.duplicate() var queue = Queue() - let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label) - queue.enqueue(sourceInShortestPathsGraph) + let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(label: source.label) + queue.enqueue(element: sourceInShortestPathsGraph) sourceInShortestPathsGraph.distance = 0 while let current = queue.dequeue() { diff --git a/Shortest Path (Unweighted)/Tests/Graph.swift b/Shortest Path (Unweighted)/Tests/Graph.swift index 0d2a735c2..8322ba0a9 100644 --- a/Shortest Path (Unweighted)/Tests/Graph.swift +++ b/Shortest Path (Unweighted)/Tests/Graph.swift @@ -1,7 +1,7 @@ // MARK: - Edge -public class Edge: Equatable { - public var neighbor: Node +open class Edge: Equatable { + open var neighbor: Node public init(neighbor: Node) { self.neighbor = neighbor @@ -15,12 +15,12 @@ public func == (lhs: Edge, rhs: Edge) -> Bool { // MARK: - Node -public class Node: CustomStringConvertible, Equatable { - public var neighbors: [Edge] +open class Node: CustomStringConvertible, Equatable { + open var neighbors: [Edge] - public private(set) var label: String - public var distance: Int? - public var visited: Bool + open fileprivate(set) var label: String + open var distance: Int? + open var visited: Bool public init(label: String) { self.label = label @@ -28,18 +28,18 @@ public class Node: CustomStringConvertible, Equatable { visited = false } - public var description: String { + open var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } - public var hasDistance: Bool { + open var hasDistance: Bool { return distance != nil } - public func remove(edge: Edge) { + open func remove(_ edge: Edge) { neighbors.remove(at: neighbors.index { $0 === edge }!) } } @@ -50,25 +50,25 @@ public func == (lhs: Node, rhs: Node) -> Bool { // MARK: - Graph -public class Graph: CustomStringConvertible, Equatable { - public private(set) var nodes: [Node] +open class Graph: CustomStringConvertible, Equatable { + open fileprivate(set) var nodes: [Node] public init() { self.nodes = [] } - public func addNode(label: String) -> Node { + open func addNode(label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(_ source: Node, neighbor: Node) { + open func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } - public var description: String { + open var description: String { var description = "" for node in nodes { @@ -79,11 +79,11 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + open func findNodeWithLabel(label: String) -> Node { return nodes.filter { $0.label == label }.first! } - public func duplicate() -> Graph { + open func duplicate() -> Graph { let duplicated = Graph() for node in nodes { diff --git a/Shortest Path (Unweighted)/Tests/Queue.swift b/Shortest Path (Unweighted)/Tests/Queue.swift index bf462bbdd..0d8752466 100644 --- a/Shortest Path (Unweighted)/Tests/Queue.swift +++ b/Shortest Path (Unweighted)/Tests/Queue.swift @@ -1,5 +1,5 @@ public struct Queue { - private var array: [T] + fileprivate var array: [T] public init() { array = [] diff --git a/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj index 35aeffa54..f1744fcf1 100644 --- a/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj +++ b/Shortest Path (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -230,6 +231,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -242,6 +244,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From 914441ec8285ae1e8354c22f692a81ae9bb70de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Tue, 3 Jan 2017 14:40:59 +0100 Subject: [PATCH 0110/1039] converts Huffman Coding to Swift 3 syntax --- .../Huffman.playground/Contents.swift | 10 +- .../Huffman.playground/Sources/Heap.swift | 34 +- .../Huffman.playground/Sources/Huffman.swift | 30 +- .../Sources/NSData+Bits.swift | 8 +- .../Sources/PriorityQueue.swift | 8 +- .../Huffman.playground/timeline.xctimeline | 10 + Huffman Coding/Huffman.swift | 294 +++++++++--------- Huffman Coding/NSData+Bits.swift | 76 ++--- Huffman Coding/README.markdown | 52 ++-- 9 files changed, 265 insertions(+), 257 deletions(-) diff --git a/Huffman Coding/Huffman.playground/Contents.swift b/Huffman Coding/Huffman.playground/Contents.swift index b67f93a6a..017c5baf2 100644 --- a/Huffman Coding/Huffman.playground/Contents.swift +++ b/Huffman Coding/Huffman.playground/Contents.swift @@ -3,21 +3,21 @@ import Foundation let s1 = "so much words wow many compression" -if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) { - print(originalData.length) +if let originalData = s1.data(using: String.Encoding.utf8) { + print(originalData.count) let huffman1 = Huffman() - let compressedData = huffman1.compressData(originalData) + let compressedData = huffman1.compressData(data: originalData as NSData) print(compressedData.length) let frequencyTable = huffman1.frequencyTable() //print(frequencyTable) let huffman2 = Huffman() - let decompressedData = huffman2.decompressData(compressedData, frequencyTable: frequencyTable) + let decompressedData = huffman2.decompressData(data: compressedData, frequencyTable: frequencyTable) print(decompressedData.length) - let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! + let s2 = String(data: decompressedData as Data, encoding: String.Encoding.utf8)! print(s2) assert(s1 == s2) } diff --git a/Huffman Coding/Huffman.playground/Sources/Heap.swift b/Huffman Coding/Huffman.playground/Sources/Heap.swift index 64bd90cd8..5ace98a17 100644 --- a/Huffman Coding/Huffman.playground/Sources/Heap.swift +++ b/Huffman Coding/Huffman.playground/Sources/Heap.swift @@ -8,14 +8,14 @@ public struct Heap { var elements = [T]() /** Determines whether this is a max-heap (>) or min-heap (<). */ - private var isOrderedBefore: (T, T) -> Bool + 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: (T, T) -> Bool) { + public init(sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort } @@ -24,9 +24,9 @@ public struct Heap { * the elements are inserted into the heap in the order determined by the * sort function. */ - public init(array: [T], sort: (T, T) -> Bool) { + public init(array: [T], sort: @escaping (T, T) -> Bool) { self.isOrderedBefore = sort - buildHeap(array) + buildHeap(array: array) } /* @@ -45,7 +45,7 @@ public struct Heap { */ private mutating func buildHeap(array: [T]) { elements = array - for i in (elements.count/2 - 1).stride(through: 0, by: -1) { + for i in stride(from: elements.count/2 - 1, to: 0, by: -1) { shiftDown(index: i, heapSize: elements.count) } } @@ -96,12 +96,12 @@ public struct Heap { * 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) { + public mutating func insert(_ value: T) { elements.append(value) shiftUp(index: elements.count - 1) } - public mutating func insert(sequence: S) { + public mutating func insert(sequence: S) where S.Iterator.Element == T { for value in sequence { insert(value) } @@ -154,15 +154,15 @@ public struct Heap { * 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 index: Int) { + mutating func shiftUp(index: Int) { var childIndex = index let child = elements[childIndex] - var parentIndex = indexOfParent(childIndex) + var parentIndex = indexOfParent(i: childIndex) while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { elements[childIndex] = elements[parentIndex] childIndex = parentIndex - parentIndex = indexOfParent(childIndex) + parentIndex = indexOfParent(i: childIndex) } elements[childIndex] = child @@ -176,11 +176,11 @@ public struct Heap { * 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 index: Int, heapSize: Int) { + mutating func shiftDown(index: Int, heapSize: Int) { var parentIndex = index while true { - let leftChildIndex = indexOfLeftChild(parentIndex) + let leftChildIndex = indexOfLeftChild(i: parentIndex) let rightChildIndex = leftChildIndex + 1 // Figure out which comes first if we order them by the sort function: @@ -208,16 +208,16 @@ extension Heap where T: Equatable { /** * Searches the heap for the given element. Performance: O(n). */ - public func indexOf(element: T) -> Int? { - return indexOf(element, 0) + public func index(of element: T) -> Int? { + return index(of: element, 0) } - private func indexOf(element: T, _ i: Int) -> Int? { + 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 = indexOf(element, indexOfLeftChild(i)) { return j } - if let j = indexOf(element, indexOfRightChild(i)) { return j } + if let j = index(of: element, indexOfLeftChild(i: i)) { return j } + if let j = index(of: element, indexOfRightChild(i: i)) { return j } return nil } } diff --git a/Huffman Coding/Huffman.playground/Sources/Huffman.swift b/Huffman Coding/Huffman.playground/Sources/Huffman.swift index d50b90d82..79b24b09a 100644 --- a/Huffman Coding/Huffman.playground/Sources/Huffman.swift +++ b/Huffman Coding/Huffman.playground/Sources/Huffman.swift @@ -29,7 +29,7 @@ public class Huffman { /* 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](count: 256, repeatedValue: Node()) + var tree = [Node](repeating: Node(), count: 256) /* This is the last node we add to the tree. */ var root: NodeIndex = -1 @@ -50,10 +50,10 @@ extension Huffman { 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. */ - private func countByteFrequency(data: NSData) { - var ptr = UnsafePointer(data.bytes) + fileprivate func countByteFrequency(inData data: NSData) { + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0..(sort: { $0.count < $1.count }) for node in tree where node.count > 0 { @@ -123,13 +123,13 @@ extension Huffman { extension Huffman { /* Compresses the contents of an NSData object. */ public func compressData(data: NSData) -> NSData { - countByteFrequency(data) + countByteFrequency(inData: data) buildTree() let writer = BitWriter() - var ptr = UnsafePointer(data.bytes) + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. NSData { - restoreTree(frequencyTable) + restoreTree(fromTable: frequencyTable) let reader = BitReader(data: data) let outData = NSMutableData() @@ -167,7 +167,7 @@ extension Huffman { var i = 0 while i < byteCount { var b = findLeafNode(reader: reader, nodeIndex: root) - outData.appendBytes(&b, length: 1) + outData.append(&b, length: 1) i += 1 } return outData @@ -177,7 +177,7 @@ extension Huffman { 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 reader: BitReader, nodeIndex: Int) -> UInt8 { + private func findLeafNode(reader: BitReader, nodeIndex: Int) -> UInt8 { var h = nodeIndex while tree[h].right != -1 { if reader.readBit() { diff --git a/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift b/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift index 0aa821f72..3e5163521 100644 --- a/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift +++ b/Huffman Coding/Huffman.playground/Sources/NSData+Bits.swift @@ -8,7 +8,7 @@ public class BitWriter { public func writeBit(bit: Bool) { if outCount == 8 { - data.appendBytes(&outByte, length: 1) + data.append(&outByte, length: 1) outCount = 0 } outByte = (outByte << 1) | (bit ? 1 : 0) @@ -21,7 +21,7 @@ public class BitWriter { let diff = UInt8(8 - outCount) outByte <<= diff } - data.appendBytes(&outByte, length: 1) + data.append(&outByte, length: 1) } } } @@ -33,12 +33,12 @@ public class BitReader { var inCount = 8 public init(data: NSData) { - ptr = UnsafePointer(data.bytes) + ptr = data.bytes.assumingMemoryBound(to: UInt8.self) } public func readBit() -> Bool { if inCount == 8 { - inByte = ptr.memory // load the next byte + inByte = ptr.pointee // load the next byte inCount = 0 ptr = ptr.successor() } diff --git a/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift b/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift index 757a6c539..4cc9d15ed 100644 --- a/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift +++ b/Huffman Coding/Huffman.playground/Sources/PriorityQueue.swift @@ -11,13 +11,13 @@ queue (largest element first) or a min-priority queue (smallest element first). */ public struct PriorityQueue { - private var heap: Heap + fileprivate var heap: Heap /* To create a max-priority queue, supply a > sort function. For a min-priority queue, use <. */ - public init(sort: (T, T) -> Bool) { + public init(sort: @escaping (T, T) -> Bool) { heap = Heap(sort: sort) } @@ -33,7 +33,7 @@ public struct PriorityQueue { return heap.peek() } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { heap.insert(element) } @@ -53,6 +53,6 @@ public struct PriorityQueue { extension PriorityQueue where T: Equatable { public func indexOf(element: T) -> Int? { - return heap.indexOf(element) + return heap.index(of: element) } } diff --git a/Huffman Coding/Huffman.playground/timeline.xctimeline b/Huffman Coding/Huffman.playground/timeline.xctimeline index bf468afec..2b2555bb1 100644 --- a/Huffman Coding/Huffman.playground/timeline.xctimeline +++ b/Huffman Coding/Huffman.playground/timeline.xctimeline @@ -2,5 +2,15 @@ + + + + diff --git a/Huffman Coding/Huffman.swift b/Huffman Coding/Huffman.swift index d50b90d82..7e2961a2f 100644 --- a/Huffman Coding/Huffman.swift +++ b/Huffman Coding/Huffman.swift @@ -1,191 +1,191 @@ 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. -*/ + 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 + /* 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 + 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 + 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](count: 256, repeatedValue: Node()) - - /* 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. + 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() { } + 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 + /* 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. */ - private func countByteFrequency(data: NSData) { - var ptr = UnsafePointer(data.bytes) - 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)) + public func frequencyTable() -> [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 } - return a - } } extension Huffman { - /* Builds a Huffman tree from a frequency table. */ - private 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) + /* 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 } - - 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(data) - buildTree() - - let writer = BitWriter() - var ptr = UnsafePointer(data.bytes) - for _ in 0.. NSData { + countByteFrequency(inData: data) + buildTree() + + let writer = BitWriter() + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) + for _ in 0.. NSData { - restoreTree(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.appendBytes(&b, length: 1) - i += 1 + /* Takes a Huffman-compressed NSData object and outputs the uncompressed data. */ + public 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 } - return outData - } - - /* Walks the tree from the root down to the leaf node. At every node, read the + + /* 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 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 - } + 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) } - return UInt8(h) - } } diff --git a/Huffman Coding/NSData+Bits.swift b/Huffman Coding/NSData+Bits.swift index 0aa821f72..4ae3c5c6d 100644 --- a/Huffman Coding/NSData+Bits.swift +++ b/Huffman Coding/NSData+Bits.swift @@ -2,49 +2,49 @@ 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.appendBytes(&outByte, length: 1) - outCount = 0 + 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 } - 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.appendBytes(&outByte, length: 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 = UnsafePointer(data.bytes) - } - - public func readBit() -> Bool { - if inCount == 8 { - inByte = ptr.memory // load the next byte - inCount = 0 - ptr = ptr.successor() + 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 } - let bit = inByte & 0x80 // read the next bit - inByte <<= 1 - inCount += 1 - return bit == 0 ? false : true - } } diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 528ba3a1d..6b2c0d245 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -70,10 +70,10 @@ public class BitWriter { public var data = NSMutableData() var outByte: UInt8 = 0 var outCount = 0 - + public func writeBit(bit: Bool) { if outCount == 8 { - data.appendBytes(&outByte, length: 1) + data.append(&outByte, length: 1) outCount = 0 } outByte = (outByte << 1) | (bit ? 1 : 0) @@ -86,7 +86,7 @@ public class BitWriter { let diff = UInt8(8 - outCount) outByte <<= diff } - data.appendBytes(&outByte, length: 1) + data.append(&outByte, length: 1) } } } @@ -103,14 +103,14 @@ public class BitReader { var ptr: UnsafePointer var inByte: UInt8 = 0 var inCount = 8 - + public init(data: NSData) { - ptr = UnsafePointer(data.bytes) + ptr = data.bytes.assumingMemoryBound(to: UInt8.self) } - + public func readBit() -> Bool { if inCount == 8 { - inByte = ptr.memory // load the next byte + inByte = ptr.pointee // load the next byte inCount = 0 ptr = ptr.successor() } @@ -145,8 +145,8 @@ class Huffman { var left: NodeIndex = -1 var right: NodeIndex = -1 } - - var tree = [Node](count: 256, repeatedValue: Node()) + + var tree = [Node](repeating: Node(), count: 256) var root: NodeIndex = -1 } @@ -159,10 +159,10 @@ Note that `tree` currently has room for 256 entries. These are for the leaf node We use the following method to count how often each byte occurs in the input data: ```swift - private func countByteFrequency(data: NSData) { - var ptr = UnsafePointer(data.bytes) + fileprivate func countByteFrequency(inData data: NSData) { + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0..(sort: { $0.count < $1.count }) for node in tree where node.count > 0 { queue.enqueue(node) // 1 @@ -252,7 +252,7 @@ Here is how it works step-by-step: 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're done with `node1` and `node2`, but the `parentNode` stills need to be connected to other nodes in the tree. +5. Put the new intermediate node back into the queue. At this point we're done with `node1` and `node2`, but the `parentNode` still need 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're done. @@ -269,20 +269,18 @@ The animation shows what the process looks like: 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 - func compressData(data: NSData) -> NSData { - countByteFrequency(data) + public func compressData(data: NSData) -> NSData { + countByteFrequency(inData: data) buildTree() - - let writer = BitWriter() - var ptr = UnsafePointer(data.bytes) + let writer = BitWriter() + var ptr = data.bytes.assumingMemoryBound(to: UInt8.self) for _ in 0.. NSData { - restoreTree(frequencyTable) + restoreTree(fromTable: frequencyTable) let reader = BitReader(data: data) let outData = NSMutableData() @@ -364,7 +362,7 @@ Here is the code for `decompressData()`, which takes an `NSData` object with Huf var i = 0 while i < byteCount { var b = findLeafNode(reader: reader, nodeIndex: root) - outData.appendBytes(&b, length: 1) + outData.append(&b, length: 1) i += 1 } return outData From 1e9ebe41a2a74c3a7dc4c01a2176ae14e5f63864 Mon Sep 17 00:00:00 2001 From: zaccone Date: Tue, 3 Jan 2017 18:21:23 -0500 Subject: [PATCH 0111/1039] Added super.init() to the initializer. --- Trie/Trie/Trie.xcodeproj/project.pbxproj | 2 -- Trie/Trie/Trie/Trie.swift | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Trie/Trie/Trie.xcodeproj/project.pbxproj b/Trie/Trie/Trie.xcodeproj/project.pbxproj index 055885ee1..90c5734cc 100644 --- a/Trie/Trie/Trie.xcodeproj/project.pbxproj +++ b/Trie/Trie/Trie.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ 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 */; }; - EB8369AD1E15C5710003A7F8 /* ReadMe.md in Sources */ = {isa = PBXBuildFile; fileRef = EB8369AC1E15C5710003A7F8 /* ReadMe.md */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -270,7 +269,6 @@ files = ( EB798E291DFEF81400F0628D /* Trie.swift in Sources */, EB798E001DFEF79900F0628D /* ViewController.swift in Sources */, - EB8369AD1E15C5710003A7F8 /* ReadMe.md in Sources */, EB798DFE1DFEF79900F0628D /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index ec3b1c5cc..bf1c7d9c2 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -64,6 +64,7 @@ class Trie: NSObject, NSCoding { override init() { root = Node() wordCount = 0 + super.init() } // MARK: NSCoding From b48107ff77ecd007656177914a9bb2860d0f1737 Mon Sep 17 00:00:00 2001 From: zaccone Date: Tue, 3 Jan 2017 18:32:52 -0500 Subject: [PATCH 0112/1039] Added a check for wordArray not nil to the guard statement in insertWordsIntoTrie. --- Trie/Trie/TrieTests/TrieTests.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 7ef02553f..f8e934f0d 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -51,10 +51,8 @@ class TrieTests: XCTestCase { /// Inserts words into a trie. If the trie is non-empty, don't do anything. func insertWordsIntoTrie() { - guard trie.count == 0 else { - return - } - for word in self.wordArray! { + guard let wordArray = wordArray, trie.count == 0 else { return } + for word in wordArray { trie.insert(word: word) } } From 947d4f8052bccdb6f8a104ab1d36892d8152d92e Mon Sep 17 00:00:00 2001 From: gonini Date: Wed, 4 Jan 2017 09:46:09 +0900 Subject: [PATCH 0113/1039] Update Minimum Spanning Tree (Unweighted Graph) to Swift 3 --- .../Contents.swift | 2 +- .../timeline.xctimeline | 6 ------ .../MinimumSpanningTree.playground/Sources/Graph.swift | 6 +++--- .../MinimumSpanningTree.playground/Sources/Node.swift | 4 ++-- .../MinimumSpanningTree.playground/Sources/Queue.swift | 2 +- .../MinimumSpanningTree.swift | 2 +- Minimum Spanning Tree (Unweighted)/Tests/Graph.swift | 10 +++++----- Minimum Spanning Tree (Unweighted)/Tests/Queue.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 3 +++ 9 files changed, 17 insertions(+), 20 deletions(-) delete mode 100644 Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift index 088da1d11..86fe27df8 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift @@ -1,4 +1,4 @@ -func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { +func breadthFirstSearchMinimumSpanningTree(_ graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() var queue = Queue() diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift index 8cfb2a09c..8f02baf92 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift @@ -5,13 +5,13 @@ public class Graph: CustomStringConvertible, Equatable { self.nodes = [] } - public func addNode(label: String) -> Node { + public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { + public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } @@ -27,7 +27,7 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift index 37a3b3fdf..0aedb6ef9 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Node.swift @@ -22,8 +22,8 @@ public class Node: CustomStringConvertible, Equatable { return distance != nil } - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + public func remove(_ edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } } diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift index bf462bbdd..3d98f801c 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Queue.swift @@ -13,7 +13,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift index 92d370878..645a41999 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.swift @@ -1,4 +1,4 @@ -func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph { +func breadthFirstSearchMinimumSpanningTree(_ graph: Graph, source: Node) -> Graph { let minimumSpanningTree = graph.duplicate() var queue = Queue() diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift index ed71cab7c..2d4161245 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift @@ -38,8 +38,8 @@ public class Node: CustomStringConvertible, Equatable { return distance != nil } - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + public func remove(_ edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } } @@ -56,13 +56,13 @@ public class Graph: CustomStringConvertible, Equatable { self.nodes = [] } - public func addNode(label: String) -> Node { + public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { + public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } @@ -78,7 +78,7 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift b/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift index bf462bbdd..3d98f801c 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift +++ b/Minimum Spanning Tree (Unweighted)/Tests/Queue.swift @@ -13,7 +13,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj index 659c7e9f2..a066b7a71 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj +++ b/Minimum Spanning Tree (Unweighted)/Tests/Tests.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -230,6 +231,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -242,6 +244,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From fc208c61f96838af6266980bd058f7141b3cac24 Mon Sep 17 00:00:00 2001 From: GongUi Date: Wed, 4 Jan 2017 09:48:04 +0900 Subject: [PATCH 0114/1039] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4e2918431..4fbf215de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ script: # - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests From 017351f6bb67368ff273d73cba89e1ee42aa45f2 Mon Sep 17 00:00:00 2001 From: gonini Date: Thu, 5 Jan 2017 08:10:11 +0900 Subject: [PATCH 0115/1039] Warning correction for unused return function --- .../MinimumSpanningTree.playground/Sources/Graph.swift | 2 +- Minimum Spanning Tree (Unweighted)/Tests/Graph.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift index 8f02baf92..e2bb82677 100644 --- a/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/MinimumSpanningTree.playground/Sources/Graph.swift @@ -35,7 +35,7 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + _ = duplicated.addNode(node.label) } for node in nodes { diff --git a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift index 2d4161245..c8cb77ac8 100644 --- a/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift +++ b/Minimum Spanning Tree (Unweighted)/Tests/Graph.swift @@ -86,7 +86,7 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + _ = duplicated.addNode(node.label) } for node in nodes { From 58058cf6e9f6813ffbde7cf89ebefba07950d18b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Thu, 5 Jan 2017 08:02:06 +0100 Subject: [PATCH 0116/1039] aligning with style guidelines --- Huffman Coding/Huffman.playground/Contents.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Huffman Coding/Huffman.playground/Contents.swift b/Huffman Coding/Huffman.playground/Contents.swift index 017c5baf2..2d59908e9 100644 --- a/Huffman Coding/Huffman.playground/Contents.swift +++ b/Huffman Coding/Huffman.playground/Contents.swift @@ -3,7 +3,7 @@ import Foundation let s1 = "so much words wow many compression" -if let originalData = s1.data(using: String.Encoding.utf8) { +if let originalData = s1.data(using: .utf8) { print(originalData.count) let huffman1 = Huffman() @@ -17,7 +17,7 @@ if let originalData = s1.data(using: String.Encoding.utf8) { let decompressedData = huffman2.decompressData(data: compressedData, frequencyTable: frequencyTable) print(decompressedData.length) - let s2 = String(data: decompressedData as Data, encoding: String.Encoding.utf8)! + let s2 = String(data: decompressedData as Data, encoding: .utf8)! print(s2) assert(s1 == s2) } From 07dc70e66a3a3e42a3cec94a2cfa6b884f1af739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Thu, 5 Jan 2017 12:42:42 +0100 Subject: [PATCH 0117/1039] Migrates App-Pairs Shortest Paths to Swift3 syntax --- .travis.yml | 2 +- .../APSP/APSP.xcodeproj/project.pbxproj | 13 +++++++++- .../xcshareddata/xcschemes/APSP.xcscheme | 2 +- .../xcshareddata/xcschemes/APSPTests.xcscheme | 2 +- All-Pairs Shortest Paths/APSP/APSP/APSP.swift | 2 +- .../APSP/APSP/FloydWarshall.swift | 26 +++++++++---------- .../APSP/APSP/Helpers.swift | 11 ++++---- .../APSP/APSPTests/APSPTests.swift | 6 ++--- 8 files changed, 38 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4fbf215de..2417b4b6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ install: script: -# - xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests +- xcodebuild test -project ./All-Pairs\ Shortest\ Paths/APSP/APSP.xcodeproj -scheme APSPTests - xcodebuild test -project ./Array2D/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj index e7e95bbb7..b2d93ea35 100644 --- a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/project.pbxproj @@ -187,14 +187,16 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 493D8DDF1CDD2A1C0089795A = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0820; }; 493D8DF01CDD5B960089795A = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0820; }; }; }; @@ -305,8 +307,10 @@ 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 = "-"; @@ -350,8 +354,10 @@ 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 = "-"; @@ -370,6 +376,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -381,6 +388,7 @@ 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 = 3.0; }; name = Debug; }; @@ -392,6 +400,7 @@ 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 = 3.0; }; name = Release; }; @@ -411,6 +420,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -432,6 +442,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.APSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; diff --git a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme index 475997aa9..e313c4b88 100644 --- a/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme +++ b/All-Pairs Shortest Paths/APSP/APSP.xcodeproj/xcshareddata/xcschemes/APSP.xcscheme @@ -1,6 +1,6 @@ ) -> P + static func apply(_ graph: AbstractGraph) -> P } diff --git a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift index 806c8677c..b1a870f2a 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift @@ -17,7 +17,7 @@ private typealias StepResult = (distances: Distances, predecessors: Predecessors - 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 { +public struct FloydWarshall: APSPAlgorithm where T: Hashable { public typealias Q = T public typealias P = FloydWarshallResult @@ -29,7 +29,7 @@ public struct FloydWarshall: APSPAlgorithm { - 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 { + public static func apply(_ graph: AbstractGraph) -> FloydWarshallResult { var previousDistance = constructInitialDistanceMatrix(graph) var previousPredecessor = constructInitialPredecessorMatrix(previousDistance) @@ -59,12 +59,12 @@ public struct FloydWarshall: APSPAlgorithm { - returns: a tuple containing the next distance matrix with weights of currently known shortest paths and the corresponding predecessor matrix */ - static private func nextStep(intermediateIdx: Int, previousDistances: Distances, + static fileprivate func nextStep(_ intermediateIdx: Int, previousDistances: Distances, previousPredecessors: Predecessors, graph: AbstractGraph) -> StepResult { let vertexCount = graph.vertices.count - var nextDistances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) - var nextPredecessors = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: nil)) + 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 { @@ -97,12 +97,12 @@ public struct FloydWarshall: APSPAlgorithm { - complexity: `Θ(V^2)` time/space - returns: weighted adjacency matrix in form ready for processing with Floyd-Warshall */ - static private func constructInitialDistanceMatrix(graph: AbstractGraph) -> Distances { + static fileprivate func constructInitialDistanceMatrix(_ graph: AbstractGraph) -> Distances { let vertices = graph.vertices let vertexCount = graph.vertices.count - var distances = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: Double.infinity)) + var distances = Array(repeating: Array(repeating: Double.infinity, count: vertexCount), count: vertexCount) for row in vertices { for col in vertices { @@ -125,10 +125,10 @@ public struct FloydWarshall: APSPAlgorithm { - complexity: `Θ(V^2)` time/space */ - static private func constructInitialPredecessorMatrix(distances: Distances) -> Predecessors { + static fileprivate func constructInitialPredecessorMatrix(_ distances: Distances) -> Predecessors { let vertexCount = distances.count - var predecessors = Array(count: vertexCount, repeatedValue: Array(count: vertexCount, repeatedValue: nil)) + var predecessors = Array(repeating: Array(repeating: nil, count: vertexCount), count: vertexCount) for fromIdx in 0 ..< vertexCount { for toIdx in 0 ..< vertexCount { @@ -151,10 +151,10 @@ public struct FloydWarshall: APSPAlgorithm { 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 { +public struct FloydWarshallResult: APSPResult where T: Hashable { - private var weights: Distances - private var predecessors: Predecessors + fileprivate var weights: Distances + fileprivate var predecessors: Predecessors /** - returns: the total weight of the path from a starting vertex to a destination. @@ -190,7 +190,7 @@ public struct FloydWarshallResult: APSPResult { - returns: the list of predecessors discovered so far */ - private func recursePathFrom(fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], + fileprivate func recursePathFrom(fromVertex from: Vertex, toVertex to: Vertex, path: [Vertex], inGraph graph: AbstractGraph) -> [Vertex]? { if from.index == to.index { diff --git a/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift b/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift index 644454491..3812b3f58 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/Helpers.swift @@ -7,10 +7,11 @@ 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) { +func printMatrix(_ matrix: [[Double]], i: Int = -1, j: Int = -1, k: Int = -1) { if i >= 0 { print(" k: \(k); i: \(i); j: \(j)\n") @@ -31,12 +32,12 @@ func printMatrix(matrix: [[Double]], i: Int = -1, j: Int = -1, k: Int = -1) { } grid.append(row) } - print((grid as NSArray).componentsJoinedByString("\n")) + print((grid as NSArray).componentsJoined(by: "\n")) print(" =======================") } -func printIntMatrix(matrix: [[Int?]]) { +func printIntMatrix(_ matrix: [[Int?]]) { var grid = [String]() @@ -46,14 +47,14 @@ func printIntMatrix(matrix: [[Int?]]) { for y in 0.. { +struct TestCase where T: Hashable { var from: Vertex var to: Vertex @@ -71,7 +71,7 @@ class APSPTests: XCTestCase { for testCase: TestCase in cases { if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), - computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { + 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)") } @@ -111,7 +111,7 @@ class APSPTests: XCTestCase { for testCase: TestCase in cases { if let computedPath = result.path(fromVertex: testCase.from, toVertex: testCase.to, inGraph: graph), - computedDistance = result.distance(fromVertex: testCase.from, toVertex: testCase.to) { + 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)") } From 797a2e9e2bf70911222cac674e05841b80679310 Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Fri, 6 Jan 2017 02:56:13 +0530 Subject: [PATCH 0118/1039] Updated Merge Sort (Recursive) to Generic. --- .../MergeSort.playground/Contents.swift | 6 +- Merge Sort/MergeSort.swift | 72 +++++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Merge Sort/MergeSort.playground/Contents.swift b/Merge Sort/MergeSort.playground/Contents.swift index ac166131e..e76570481 100644 --- a/Merge Sort/MergeSort.playground/Contents.swift +++ b/Merge Sort/MergeSort.playground/Contents.swift @@ -1,6 +1,6 @@ /* Top-down recursive version */ -func mergeSort(_ array: [Int]) -> [Int] { +func mergeSort(_ array: [T]) -> [T] { guard array.count > 1 else { return array } let middleIndex = array.count / 2 let leftArray = mergeSort(Array(array[0.. [Int] { return merge(leftPile: leftArray, rightPile: rightArray) } -func merge(leftPile: [Int], rightPile: [Int]) -> [Int] { +func merge(leftPile: [T], rightPile: [T]) -> [T] { var leftIndex = 0 var rightIndex = 0 - var orderedPile = [Int]() + var orderedPile = [T]() while leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index 20316663f..bb89ea4d4 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -6,45 +6,45 @@ // // -func mergeSort(_ array: [Int]) -> [Int] { - guard array.count > 1 else { return array } - let middleIndex = array.count / 2 - let leftArray = mergeSort(Array(array[0..(_ array: [T]) -> [T] { + guard array.count > 1 else { return array } + let middleIndex = array.count / 2 + let leftArray = mergeSort(Array(array[0.. [Int] { - var leftIndex = 0 - var rightIndex = 0 - var orderedPile = [Int]() - - 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 +func merge(leftPile: [T], rightPile: [T]) -> [T] { + var leftIndex = 0 + var rightIndex = 0 + var orderedPile = [T]() + + 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 + } } - } - - while leftIndex < leftPile.count { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - } - - while rightIndex < rightPile.count { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } - - return orderedPile + + while leftIndex < leftPile.count { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + } + + while rightIndex < rightPile.count { + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } + + return orderedPile } /* From e7b54f7bbb1c48be56f0f85ff433f889e1ddd880 Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Fri, 6 Jan 2017 02:58:50 +0530 Subject: [PATCH 0119/1039] Extra Example Added. --- Merge Sort/MergeSort.playground/Contents.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Merge Sort/MergeSort.playground/Contents.swift b/Merge Sort/MergeSort.playground/Contents.swift index e76570481..2952fc299 100644 --- a/Merge Sort/MergeSort.playground/Contents.swift +++ b/Merge Sort/MergeSort.playground/Contents.swift @@ -43,6 +43,8 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { let array = [2, 1, 5, 4, 9] let sortedArray = mergeSort(array) +let array2 = ["Tom", "Harry", "Ron", "Chandler", "Monica"] +let sortedArray2 = mergeSort(array2) From 369bff5d3ed3634c140b73c348dbe000ca7df4da Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Sun, 8 Jan 2017 03:47:54 +0530 Subject: [PATCH 0120/1039] Code Re-Indented With 2 Space Indentation. --- Merge Sort/MergeSort.swift | 70 +++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index bb89ea4d4..a7677b0bb 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -7,44 +7,44 @@ // func mergeSort(_ array: [T]) -> [T] { - guard array.count > 1 else { return array } - let middleIndex = array.count / 2 - let leftArray = mergeSort(Array(array[0.. 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]() - - 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 - } - } - - while leftIndex < leftPile.count { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 - } - - while rightIndex < rightPile.count { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 - } - - return orderedPile + var leftIndex = 0 + var rightIndex = 0 + var orderedPile = [T]() + + 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 + } + } + + while leftIndex < leftPile.count { + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 + } + + while rightIndex < rightPile.count { + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 + } + + return orderedPile } /* From f9412936fc0656eebf5f7ad1a79a241a5e05c572 Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Sun, 8 Jan 2017 03:57:16 +0530 Subject: [PATCH 0121/1039] Code Re Indented with 2 Space Indentation (Part 2) --- Merge Sort/MergeSort.swift | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index a7677b0bb..4332fc44b 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -20,28 +20,28 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { var orderedPile = [T]() 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 - } + 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 + } } while leftIndex < leftPile.count { - orderedPile.append(leftPile[leftIndex]) - leftIndex += 1 + orderedPile.append(leftPile[leftIndex]) + leftIndex += 1 } while rightIndex < rightPile.count { - orderedPile.append(rightPile[rightIndex]) - rightIndex += 1 + orderedPile.append(rightPile[rightIndex]) + rightIndex += 1 } return orderedPile From 0e819963fe321021486aa8247776cb20d65d58cf Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Sun, 8 Jan 2017 15:52:39 -0500 Subject: [PATCH 0122/1039] Updated K-Means Tests.xcodeproj to latest settings. Updated K-Means code to Swift3 syntax and changes to API. --- .travis.yml | 2 +- K-Means/KMeans.swift | 18 ++++----- K-Means/Tests/KMeansTests.swift | 2 +- K-Means/Tests/Tests.xcodeproj/project.pbxproj | 40 ++++++++++++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- K-Means/Tests/Vector.swift | 12 +++--- 6 files changed, 57 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 727b247a5..b33835565 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ script: # - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests diff --git a/K-Means/KMeans.swift b/K-Means/KMeans.swift index 972fd7230..4a89a3fae 100644 --- a/K-Means/KMeans.swift +++ b/K-Means/KMeans.swift @@ -11,11 +11,11 @@ class KMeans { self.numCenters = labels.count } - private func indexOfNearestCenter(x: Vector, centers: [Vector]) -> Int { + private func indexOfNearestCenter(_ x: Vector, centers: [Vector]) -> Int { var nearestDist = DBL_MAX var minIndex = 0 - for (idx, center) in centers.enumerate() { + for (idx, center) in centers.enumerated() { let dist = x.distanceTo(center) if dist < nearestDist { minIndex = idx @@ -25,8 +25,8 @@ class KMeans { return minIndex } - func trainCenters(points: [Vector], convergeDistance: Double) { - let zeroVector = Vector([Double](count: points[0].length, repeatedValue: 0)) + 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) @@ -34,7 +34,7 @@ class KMeans { var centerMoveDist = 0.0 repeat { // This array keeps track of which data points belong to which centroids. - var classification: [[Vector]] = .init(count: numCenters, repeatedValue: []) + var classification: [[Vector]] = .init(repeating: [], count: numCenters) // For each data point, find the centroid that it is closest to. for p in points { @@ -45,7 +45,7 @@ class KMeans { // 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, combine: +) / Double(assignedPoints.count) + assignedPoints.reduce(zeroVector, +) / Double(assignedPoints.count) } // Find out how far each centroid moved since the last iteration. If it's @@ -61,14 +61,14 @@ class KMeans { centroids = centers } - func fit(point: Vector) -> Label { + 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] { + func fit(_ points: [Vector]) -> [Label] { assert(!centroids.isEmpty, "Exception: KMeans tried to fit on a non trained model.") return points.map(fit) @@ -76,7 +76,7 @@ class KMeans { } // Pick k random elements from samples -func reservoirSample(samples: [T], k: Int) -> [T] { +func reservoirSample(_ samples: [T], k: Int) -> [T] { var result = [T]() // Fill the result array with first k elements diff --git a/K-Means/Tests/KMeansTests.swift b/K-Means/Tests/KMeansTests.swift index 179f9d418..7e0c93004 100644 --- a/K-Means/Tests/KMeansTests.swift +++ b/K-Means/Tests/KMeansTests.swift @@ -10,7 +10,7 @@ import Foundation import XCTest class KMeansTests: XCTestCase { - func genPoints(numPoints: Int, numDimensions: Int) -> [Vector] { + func genPoints(_ numPoints: Int, numDimensions: Int) -> [Vector] { var points = [Vector]() for _ in 0.. Double { + func distanceTo(_ other: Vector) -> Double { var result = 0.0 for idx in 0.. Vector { return Vector(results) } -func += (inout left: Vector, right: Vector) { +func += (left: inout Vector, right: Vector) { left = left + right } @@ -51,18 +51,18 @@ func - (left: Vector, right: Vector) -> Vector { return Vector(results) } -func -= (inout left: Vector, right: Vector) { +func -= (left: inout Vector, right: Vector) { left = left - right } func / (left: Vector, right: Double) -> Vector { - var results = [Double](count: left.length, repeatedValue: 0) - for (idx, value) in left.data.enumerate() { + var results = [Double](repeating: 0, count: left.length) + for (idx, value) in left.data.enumerated() { results[idx] = value / right } return Vector(results) } -func /= (inout left: Vector, right: Double) { +func /= (left: inout Vector, right: Double) { left = left / right } From bf46bb528139e05d41a48bed0a54d78030b420b2 Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Sun, 8 Jan 2017 16:29:16 -0500 Subject: [PATCH 0123/1039] Converted playground and combSort code to Swift 3 syntax. Changed combSort to use generic type. --- Comb Sort/Comb Sort.playground/Contents.swift | 24 +------------ .../Sources/Comb Sort.swift | 36 +++++++++++++++++++ Comb Sort/Comb Sort.swift | 6 ++-- 3 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift diff --git a/Comb Sort/Comb Sort.playground/Contents.swift b/Comb Sort/Comb Sort.playground/Contents.swift index 2d6155b50..d6add44f5 100644 --- a/Comb Sort/Comb Sort.playground/Contents.swift +++ b/Comb Sort/Comb Sort.playground/Contents.swift @@ -4,34 +4,12 @@ import Cocoa -func combSort (input: [Int]) -> [Int] { - var copy = 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 -} - // 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](count: 1000, repeatedValue: 0) +var bigArray = [Int](repeating: 0, count: 1000) var i = 0 while i < 1000 { bigArray[i] = Int(arc4random_uniform(1000) + 1) diff --git a/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift b/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift new file mode 100644 index 000000000..b6e85fa2b --- /dev/null +++ b/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift @@ -0,0 +1,36 @@ +// 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] { + swap(©[index], ©[index + gap]) + } + index += 1 + } + } + return copy +} + +fileprivate func swap(a: inout T, b: inout T) { + let temp = a + a = b + b = temp +} diff --git a/Comb Sort/Comb Sort.swift b/Comb Sort/Comb Sort.swift index 7abba8c7f..b6e85fa2b 100644 --- a/Comb Sort/Comb Sort.swift +++ b/Comb Sort/Comb Sort.swift @@ -7,8 +7,8 @@ import Foundation -func combSort (input: [Int]) -> [Int] { - var copy: [Int] = input +public func combSort(_ input: [T]) -> [T] { + var copy: [T] = input var gap = copy.count let shrink = 1.3 @@ -29,7 +29,7 @@ func combSort (input: [Int]) -> [Int] { return copy } -func swap (inout a: Int, inout b: Int) { +fileprivate func swap(a: inout T, b: inout T) { let temp = a a = b b = temp From f1dd6b66c4eca5e01b7b363a329fa4ffa5a46d0e Mon Sep 17 00:00:00 2001 From: iamsimranjot Date: Mon, 9 Jan 2017 03:12:18 +0530 Subject: [PATCH 0124/1039] Removed Extra Spaces. --- Merge Sort/MergeSort.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index 4332fc44b..f77d1cd84 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -18,7 +18,7 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { var leftIndex = 0 var rightIndex = 0 var orderedPile = [T]() - + while leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { orderedPile.append(leftPile[leftIndex]) @@ -33,17 +33,17 @@ func merge(leftPile: [T], rightPile: [T]) -> [T] { rightIndex += 1 } } - + while leftIndex < leftPile.count { orderedPile.append(leftPile[leftIndex]) leftIndex += 1 } - + while rightIndex < rightPile.count { orderedPile.append(rightPile[rightIndex]) rightIndex += 1 } - + return orderedPile } From af8b44f97392fb8f8cb5704b0799fb0523ee8e31 Mon Sep 17 00:00:00 2001 From: zaccone Date: Mon, 9 Jan 2017 13:50:28 -0500 Subject: [PATCH 0125/1039] Changed the baseline for one of the tests. --- .../6ABF2F62-9363-4450-8DE1-D20F57026950.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist index 01ff985c8..d8e350129 100644 --- a/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist +++ b/Trie/Trie/Trie.xcodeproj/xcshareddata/xcbaselines/EB798E0A1DFEF79900F0628D.xcbaseline/6ABF2F62-9363-4450-8DE1-D20F57026950.plist @@ -11,7 +11,7 @@ com.apple.XCTPerformanceMetric_WallClockTime baselineAverage - 3.0053 + 3.407 baselineIntegrationDisplayName Local Baseline From f0e83bdea4dce34d5a495fcd7dc3b3f3dec8c178 Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Mon, 9 Jan 2017 22:05:24 -0500 Subject: [PATCH 0126/1039] Added Comb Sort test. --- .travis.yml | 1 + Comb Sort/Tests/CombSortTests.swift | 28 ++ Comb Sort/Tests/Info.plist | 22 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 277 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 101 +++++++ 6 files changed, 436 insertions(+) create mode 100644 Comb Sort/Tests/CombSortTests.swift create mode 100644 Comb Sort/Tests/Info.plist create mode 100644 Comb Sort/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/.travis.yml b/.travis.yml index 727b247a5..b4691467f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ script: # - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Comb\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests diff --git a/Comb Sort/Tests/CombSortTests.swift b/Comb Sort/Tests/CombSortTests.swift new file mode 100644 index 000000000..1bcc67fd0 --- /dev/null +++ b/Comb Sort/Tests/CombSortTests.swift @@ -0,0 +1,28 @@ +// +// 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) + } +} diff --git a/Comb Sort/Tests/Info.plist b/Comb Sort/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Comb Sort/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Comb Sort/Tests/Tests.xcodeproj/project.pbxproj b/Comb Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..60039196c --- /dev/null +++ b/Comb Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,277 @@ +// !$*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 = 0820; + 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_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; + }; + 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_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; + }; + 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 = 3.0; + }; + 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 = 3.0; + }; + 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 */; +} diff --git a/Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Comb Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..55e697ad3 --- /dev/null +++ b/Comb Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6ec92d76ccecd3f0083252d406e1fc5b3a59d57b Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 10 Jan 2017 00:12:50 -0800 Subject: [PATCH 0127/1039] Fixes compile error due to missing brace. --- Trie/Trie/Trie/Trie.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index d3c845720..0e11a9c61 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -11,15 +11,15 @@ 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 - } + 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: From 53b87713a7f3a8083d67053416d4bc633090e68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Wed, 11 Jan 2017 02:30:24 +0100 Subject: [PATCH 0128/1039] Migrates Ternary Search Tree to Swift 3 syntax (#352) * migrates Ternary Search Tree to Swift 3 syntax * aligning function names as suggested * adds unit tests to TernarySearchTree * adds guards as suggested --- .travis.yml | 1 + .../TST.playground/Contents.swift | 30 +- .../Sources/TernarySearchTree.swift | 48 ++-- .../TST.playground/Sources/Utils.swift | 30 ++ .../TST.playground/contents.xcplayground | 2 +- Ternary Search Tree/TernarySearchTree.swift | 54 ++-- Ternary Search Tree/Tests/Info.plist | 22 ++ .../Tests/TernarySearchTreeTests.swift | 58 ++++ .../Tests/Tests.xcodeproj/project.pbxproj | 264 ++++++++++++++++++ .../xcshareddata/xcschemes/Tests.xcscheme | 56 ++++ Ternary Search Tree/Utils.swift | 30 ++ .../contents.xcworkspacedata | 10 + 12 files changed, 529 insertions(+), 76 deletions(-) create mode 100644 Ternary Search Tree/TST.playground/Sources/Utils.swift create mode 100644 Ternary Search Tree/Tests/Info.plist create mode 100644 Ternary Search Tree/Tests/TernarySearchTreeTests.swift create mode 100644 Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme create mode 100644 Ternary Search Tree/Utils.swift diff --git a/.travis.yml b/.travis.yml index 6812ac32a..117400d97 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,3 +43,4 @@ script: - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests - xcodebuild test -project ./Palindromes/Test/Test.xcodeproj -scheme Test +- xcodebuild test -project ./Ternary\ Search\ Tree/Tests/Tests.xcodeproj -scheme Tests diff --git a/Ternary Search Tree/TST.playground/Contents.swift b/Ternary Search Tree/TST.playground/Contents.swift index 6b1fe3eaa..bacf56aee 100644 --- a/Ternary Search Tree/TST.playground/Contents.swift +++ b/Ternary Search Tree/TST.playground/Contents.swift @@ -4,39 +4,23 @@ import Cocoa import Foundation let treeOfStrings = TernarySearchTree() -let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - -//Random string generator from: -//http://stackoverflow.com/questions/26845307/generate-random-alphanumeric-string-in-swift/26845710 -func randomAlphaNumericString(length: Int) -> String { - let allowedCharsCount = UInt32(allowedChars.characters.count) - var randomString = "" - - for _ in (0..() for _ in (1...testCount) { let randomNum = Int(arc4random_uniform(UInt32.max)) let randomLength = Int(arc4random_uniform(10)) - let key = randomAlphaNumericString(randomLength) + let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) if key != "" { testNums.append((key, randomNum)) - treeOfInts.insert(randomNum, withKey: key) + treeOfInts.insert(data: randomNum, withKey: key) } } for aTest in testNums { - let data = treeOfInts.find(aTest.key) + let data = treeOfInts.find(key: aTest.key) if data == nil { print("TEST FAILED. Key: \(aTest.key) Data: \(aTest.data)") } diff --git a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift index 43c4453e3..fed8f9710 100644 --- a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift +++ b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift @@ -18,11 +18,10 @@ public class TernarySearchTree { //MARK: - Insertion public func insert(data: Element, withKey key: String) -> Bool { - return insertNode(&root, withData: data, andKey: key, atIndex: 0) - + return insert(node: &root, withData: data, andKey: key, atIndex: 0) } - private func insertNode(inout aNode: TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { + private func insert(node: inout TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { //sanity check. if key.characters.count == 0 { @@ -30,30 +29,30 @@ public class TernarySearchTree { } //create a new node if necessary. - if aNode == nil { - let index = key.startIndex.advancedBy(charIndex) - aNode = TSTNode(key: key[index]) + 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.startIndex.advancedBy(charIndex) - if key[index] < aNode!.key { - return insertNode(&aNode!.left, withData: data, andKey: key, atIndex: charIndex) + 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] > aNode!.key { - return insertNode(&aNode!.right, withData: data, andKey: key, atIndex: charIndex) + 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 insertNode(&aNode!.middle, withData: data, andKey: key, atIndex: charIndex + 1) + return insert(node: &node!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } //otherwise, all done. else { - aNode!.data = data - aNode?.hasData = true + node!.data = data + node?.hasData = true return true } } @@ -64,32 +63,31 @@ public class TernarySearchTree { public func find(key: String) -> Element? { - return findNode(root, withKey: key, atIndex: 0) + return find(node: root, withKey: key, atIndex: 0) } - - private func findNode(aNode: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { + private func find(node: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { //Given key does not exist in tree. - if aNode == nil { + if node == nil { return nil } - let index = key.startIndex.advancedBy(charIndex) + let index = key.index(key.startIndex, offsetBy: charIndex) //go left - if key[index] < aNode!.key { - return findNode(aNode!.left, withKey: key, atIndex: charIndex) + if key[index] < node!.key { + return find(node: node!.left, withKey: key, atIndex: charIndex) } //go right - else if key[index] > aNode!.key { - return findNode(aNode!.right, withKey: key, atIndex: charIndex) + 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 findNode(aNode!.middle, withKey: key, atIndex: charIndex + 1) + return find(node: node!.middle, withKey: key, atIndex: charIndex + 1) } else { - return aNode!.data + return node!.data } } } diff --git a/Ternary Search Tree/TST.playground/Sources/Utils.swift b/Ternary Search Tree/TST.playground/Sources/Utils.swift new file mode 100644 index 000000000..cabfe1b68 --- /dev/null +++ b/Ternary Search Tree/TST.playground/Sources/Utils.swift @@ -0,0 +1,30 @@ +// +// 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.. - + \ No newline at end of file diff --git a/Ternary Search Tree/TernarySearchTree.swift b/Ternary Search Tree/TernarySearchTree.swift index 2f143bead..c4b51519a 100644 --- a/Ternary Search Tree/TernarySearchTree.swift +++ b/Ternary Search Tree/TernarySearchTree.swift @@ -33,52 +33,52 @@ public class TernarySearchTree { - returns: Value indicating insertion success/failure. */ - public func insert(data: Element, withKey key: String) -> Bool { - return insertNode(&root, withData: data, andKey: key, atIndex: 0) + @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 aNode: The current node to insert below. + - 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 insertNode(inout aNode: TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { + private func insert(node: inout TSTNode?, withData data: Element, andKey key: String, atIndex charIndex: Int) -> Bool { //sanity check. - if key.characters.count == 0 { + guard key.characters.count > 0 else { return false } //create a new node if necessary. - if aNode == nil { - let index = key.startIndex.advancedBy(charIndex) - aNode = TSTNode(key: key[index]) + 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.startIndex.advancedBy(charIndex) - if key[index] < aNode!.key { - return insertNode(&aNode!.left, withData: data, andKey: key, atIndex: charIndex) + 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] > aNode!.key { - return insertNode(&aNode!.right, withData: data, andKey: key, atIndex: charIndex) + 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 insertNode(&aNode!.middle, withData: data, andKey: key, atIndex: charIndex + 1) + return insert(node: &node!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } //otherwise, all done. else { - aNode!.data = data - aNode?.hasData = true + node!.data = data + node?.hasData = true return true } } @@ -95,40 +95,40 @@ public class TernarySearchTree { - returns: The element, if found. Otherwise, nil. */ public func find(key: String) -> Element? { - return findNode(root, withKey: key, atIndex: 0) + return find(node: root, withKey: key, atIndex: 0) } /** Helper method that performs actual legwork of find operation. Implemented recursively. - - parameter aNode: The current node being evaluated. + - 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 findNode(aNode: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { + private func find(node: TSTNode?, withKey key: String, atIndex charIndex: Int) -> Element? { //Given key does not exist in tree. - if aNode == nil { + guard let node = node else { return nil } - let index = key.startIndex.advancedBy(charIndex) + let index = key.index(key.startIndex, offsetBy: charIndex) //go left - if key[index] < aNode!.key { - return findNode(aNode!.left, withKey: key, atIndex: charIndex) + if key[index] < node.key { + return find(node: node.left, withKey: key, atIndex: charIndex) } //go right - else if key[index] > aNode!.key { - return findNode(aNode!.right, withKey: key, atIndex: charIndex) + 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 findNode(aNode!.middle, withKey: key, atIndex: charIndex + 1) + return find(node: node.middle, withKey: key, atIndex: charIndex + 1) } else { - return aNode!.data + return node.data } } } diff --git a/Ternary Search Tree/Tests/Info.plist b/Ternary Search Tree/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Ternary Search Tree/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Ternary Search Tree/Tests/TernarySearchTreeTests.swift b/Ternary Search Tree/Tests/TernarySearchTreeTests.swift new file mode 100644 index 000000000..51e7c808c --- /dev/null +++ b/Ternary Search Tree/Tests/TernarySearchTreeTests.swift @@ -0,0 +1,58 @@ +// +// 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 treeOfStrings = TernarySearchTree() + let testCount = 30 + + func testCanFindStringInTree() { + var testStrings: [(key: String, data: String)] = [] + 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) + + 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)) + 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) + XCTAssertNotNil(data) + XCTAssertEqual(data, aTest.data) + } + } +} diff --git a/Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj b/Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..7afaca944 --- /dev/null +++ b/Ternary Search Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,264 @@ +// !$*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 = 3.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 = 3.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 */; +} diff --git a/Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..752b0c7fc --- /dev/null +++ b/Ternary Search Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Ternary Search Tree/Utils.swift b/Ternary Search Tree/Utils.swift new file mode 100644 index 000000000..cabfe1b68 --- /dev/null +++ b/Ternary Search Tree/Utils.swift @@ -0,0 +1,30 @@ +// +// 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.. + + + + + + From b9b491d98c50a270184204a98e982e1ccc3b07ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20B=C3=B8dskov?= Date: Wed, 11 Jan 2017 16:05:37 +0100 Subject: [PATCH 0129/1039] fixing failing test (#355) the problem was that the testdata generator could generate keys that was not unique...which caused the `find` method to return the wrong values for keys when the keys were the same. --- Ternary Search Tree/TernarySearchTree.swift | 2 +- .../Tests/TernarySearchTreeTests.swift | 25 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Ternary Search Tree/TernarySearchTree.swift b/Ternary Search Tree/TernarySearchTree.swift index c4b51519a..2e2ca2917 100644 --- a/Ternary Search Tree/TernarySearchTree.swift +++ b/Ternary Search Tree/TernarySearchTree.swift @@ -75,7 +75,7 @@ public class TernarySearchTree { if charIndex + 1 < key.characters.count { return insert(node: &node!.middle, withData: data, andKey: key, atIndex: charIndex + 1) } - //otherwise, all done. + //otherwise, all done. else { node!.data = data node?.hasData = true diff --git a/Ternary Search Tree/Tests/TernarySearchTreeTests.swift b/Ternary Search Tree/Tests/TernarySearchTreeTests.swift index 51e7c808c..40739c888 100644 --- a/Ternary Search Tree/Tests/TernarySearchTreeTests.swift +++ b/Ternary Search Tree/Tests/TernarySearchTreeTests.swift @@ -10,14 +10,23 @@ import XCTest class TernarySearchTreeTests: XCTestCase { - let treeOfStrings = TernarySearchTree() + let testCount = 30 func testCanFindStringInTree() { var testStrings: [(key: String, data: String)] = [] + let treeOfStrings = TernarySearchTree() + for _ in (1...testCount) { - let randomLength = Int(arc4random_uniform(10)) - let key = Utils.shared.randomAlphaNumericString(withLength: randomLength) + 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)") @@ -29,7 +38,6 @@ class TernarySearchTreeTests: XCTestCase { for aTest in testStrings { let data = treeOfStrings.find(key: aTest.key) - XCTAssertNotNil(data) XCTAssertEqual(data, aTest.data) } @@ -40,8 +48,13 @@ class TernarySearchTreeTests: XCTestCase { 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) + 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)) From bc73299363a92f07b95bd831942985c2daba1d4b Mon Sep 17 00:00:00 2001 From: Keita Date: Wed, 11 Jan 2017 16:58:11 -0800 Subject: [PATCH 0130/1039] Update Stack and Queue files to use top and front properties (#351) * Update Stack.swift and StackTests.swift to use top property - peek() method was replaced with top property. Update Stack.swift and StackTests.swift to use top property instead of peek() method. - Fix indentation in Stack/README.markdown. * Update Queue-Optimized.swift and QueueTests.swift to use front property - peek() method was replaced with front property. Update Queue-Optimized.swift and QueueTests.swift to use front property instead of peek() method. - Fix front property implementation of Queue-Optimized in Queue/README.markdown. * Update Queue-Simple.swift to use front property instead of peek() method --- Queue/Queue-Optimized.swift | 2 +- Queue/Queue-Simple.swift | 2 +- Queue/README.markdown | 6 +++++- Queue/Tests/QueueTests.swift | 16 ++++++++-------- Stack/README.markdown | 2 +- Stack/Stack.swift | 2 +- Stack/Tests/StackTests.swift | 16 ++++++++-------- 7 files changed, 25 insertions(+), 21 deletions(-) diff --git a/Queue/Queue-Optimized.swift b/Queue/Queue-Optimized.swift index ad6999295..7dff91698 100644 --- a/Queue/Queue-Optimized.swift +++ b/Queue/Queue-Optimized.swift @@ -37,7 +37,7 @@ public struct Queue { return element } - public func peek() -> T? { + public var front: T? { if isEmpty { return nil } else { diff --git a/Queue/Queue-Simple.swift b/Queue/Queue-Simple.swift index 27fbdee4d..c5e8067c8 100644 --- a/Queue/Queue-Simple.swift +++ b/Queue/Queue-Simple.swift @@ -30,7 +30,7 @@ public struct Queue { } } - public func peek() -> T? { + public var front: T? { return array.first } } diff --git a/Queue/README.markdown b/Queue/README.markdown index 25d6205f8..f8259c31c 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -167,7 +167,11 @@ public struct Queue { } public var front: T? { - return array.first + if isEmpty { + return nil + } else { + return array[head] + } } } ``` diff --git a/Queue/Tests/QueueTests.swift b/Queue/Tests/QueueTests.swift index 7406f8d35..b820ac0d3 100755 --- a/Queue/Tests/QueueTests.swift +++ b/Queue/Tests/QueueTests.swift @@ -6,7 +6,7 @@ class QueueTest: XCTestCase { var queue = Queue() XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) - XCTAssertEqual(queue.peek(), nil) + XCTAssertEqual(queue.front, nil) XCTAssertNil(queue.dequeue()) } @@ -16,13 +16,13 @@ class QueueTest: XCTestCase { queue.enqueue(123) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) - XCTAssertEqual(queue.peek(), 123) + XCTAssertEqual(queue.front, 123) let result = queue.dequeue() XCTAssertEqual(result, 123) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) - XCTAssertEqual(queue.peek(), nil) + XCTAssertEqual(queue.front, nil) } func testTwoElements() { @@ -32,19 +32,19 @@ class QueueTest: XCTestCase { queue.enqueue(456) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 2) - XCTAssertEqual(queue.peek(), 123) + XCTAssertEqual(queue.front, 123) let result1 = queue.dequeue() XCTAssertEqual(result1, 123) XCTAssertFalse(queue.isEmpty) XCTAssertEqual(queue.count, 1) - XCTAssertEqual(queue.peek(), 456) + XCTAssertEqual(queue.front, 456) let result2 = queue.dequeue() XCTAssertEqual(result2, 456) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) - XCTAssertEqual(queue.peek(), nil) + XCTAssertEqual(queue.front, nil) } func testMakeEmpty() { @@ -58,12 +58,12 @@ class QueueTest: XCTestCase { queue.enqueue(789) XCTAssertEqual(queue.count, 1) - XCTAssertEqual(queue.peek(), 789) + XCTAssertEqual(queue.front, 789) let result = queue.dequeue() XCTAssertEqual(result, 789) XCTAssertTrue(queue.isEmpty) XCTAssertEqual(queue.count, 0) - XCTAssertEqual(queue.peek(), nil) + XCTAssertEqual(queue.front, nil) } } diff --git a/Stack/README.markdown b/Stack/README.markdown index a79e2c261..1a3ca2638 100644 --- a/Stack/README.markdown +++ b/Stack/README.markdown @@ -61,7 +61,7 @@ public struct Stack { } public var top: T? { - return array.last + return array.last } } ``` diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 49edaf4cb..974d5a443 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -22,7 +22,7 @@ public struct Stack { return array.popLast() } - public func peek() -> T? { + public var top: T? { return array.last } } diff --git a/Stack/Tests/StackTests.swift b/Stack/Tests/StackTests.swift index 62e26b0fa..f4df09a67 100755 --- a/Stack/Tests/StackTests.swift +++ b/Stack/Tests/StackTests.swift @@ -6,7 +6,7 @@ class StackTest: XCTestCase { var stack = Stack() XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) - XCTAssertEqual(stack.peek(), nil) + XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } @@ -16,13 +16,13 @@ class StackTest: XCTestCase { stack.push(123) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 1) - XCTAssertEqual(stack.peek(), 123) + XCTAssertEqual(stack.top, 123) let result = stack.pop() XCTAssertEqual(result, 123) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) - XCTAssertEqual(stack.peek(), nil) + XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } @@ -33,19 +33,19 @@ class StackTest: XCTestCase { stack.push(456) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 2) - XCTAssertEqual(stack.peek(), 456) + XCTAssertEqual(stack.top, 456) let result1 = stack.pop() XCTAssertEqual(result1, 456) XCTAssertFalse(stack.isEmpty) XCTAssertEqual(stack.count, 1) - XCTAssertEqual(stack.peek(), 123) + XCTAssertEqual(stack.top, 123) let result2 = stack.pop() XCTAssertEqual(result2, 123) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) - XCTAssertEqual(stack.peek(), nil) + XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } @@ -60,13 +60,13 @@ class StackTest: XCTestCase { stack.push(789) XCTAssertEqual(stack.count, 1) - XCTAssertEqual(stack.peek(), 789) + XCTAssertEqual(stack.top, 789) let result = stack.pop() XCTAssertEqual(result, 789) XCTAssertTrue(stack.isEmpty) XCTAssertEqual(stack.count, 0) - XCTAssertEqual(stack.peek(), nil) + XCTAssertEqual(stack.top, nil) XCTAssertNil(stack.pop()) } } From d3b2496c3b5a3eca4f80fdc8d33159ccd2fa6c2a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 12 Jan 2017 01:43:41 -0800 Subject: [PATCH 0131/1039] Update README.markdown --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 9e0ae00fa..e5c8f8dae 100644 --- a/README.markdown +++ b/README.markdown @@ -8,7 +8,7 @@ If you're a computer science student who needs to learn this stuff for exams -- 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. -All code is compatible with **Xcode 7.3** and **Swift 2.2**. We'll keep this updated with the latest version of Swift. +Most code is compatible with **Xcode 8.2** and **Swift 3**. We'll keep this updated with the latest version of Swift. This is a work in progress. More algorithms will be added soon. :-) From d44abb819f182abc44f86026d211ed1a132ccc88 Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Tue, 10 Jan 2017 21:47:58 -0500 Subject: [PATCH 0132/1039] Updated radixSort argument to swift3 syntax. --- Radix Sort/radixSort.swift | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Radix Sort/radixSort.swift b/Radix Sort/radixSort.swift index 31a783db7..24d4155d7 100644 --- a/Radix Sort/radixSort.swift +++ b/Radix Sort/radixSort.swift @@ -5,43 +5,42 @@ */ -func radixSort(inout arr: [Int] ) { - - +// 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 arr { + + + 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.. Date: Tue, 10 Jan 2017 21:48:55 -0500 Subject: [PATCH 0133/1039] Added playground demonstrating radixSort. --- .../RadixSort.playground/Contents.swift | 16 +++++++ .../Sources/radixSort.swift | 46 +++++++++++++++++++ .../contents.xcplayground | 4 ++ 3 files changed, 66 insertions(+) create mode 100644 Radix Sort/RadixSort.playground/Contents.swift create mode 100644 Radix Sort/RadixSort.playground/Sources/radixSort.swift create mode 100644 Radix Sort/RadixSort.playground/contents.xcplayground diff --git a/Radix Sort/RadixSort.playground/Contents.swift b/Radix Sort/RadixSort.playground/Contents.swift new file mode 100644 index 000000000..a4f7e3527 --- /dev/null +++ b/Radix Sort/RadixSort.playground/Contents.swift @@ -0,0 +1,16 @@ +//: Playground - noun: a place where people can play + +import Cocoa + +// 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 = [Int](repeating: 0, count: 1000) +var i = 0 +while i < 1000 { + bigArray[i] = Int(arc4random_uniform(1000) + 1) + i += 1 +} +radixSort(&bigArray) diff --git a/Radix Sort/RadixSort.playground/Sources/radixSort.swift b/Radix Sort/RadixSort.playground/Sources/radixSort.swift new file mode 100644 index 000000000..136ede4fd --- /dev/null +++ b/Radix Sort/RadixSort.playground/Sources/radixSort.swift @@ -0,0 +1,46 @@ +/* + + Sorting Algorithm that sorts an input array of integers digit by digit. + + */ +import Foundation + +// 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.. + + + \ No newline at end of file From 021772eee7c6b8da4598fa7d0ecffb817388aa94 Mon Sep 17 00:00:00 2001 From: Tai Heng Date: Tue, 10 Jan 2017 21:49:55 -0500 Subject: [PATCH 0134/1039] Added tests for RadixSort. --- .travis.yml | 1 + .../contents.xcworkspacedata | 7 + Radix Sort/Tests/Info.plist | 22 ++ Radix Sort/Tests/RadixSortTests.swift | 18 ++ .../Tests/Tests.xcodeproj/project.pbxproj | 277 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 101 +++++++ 7 files changed, 433 insertions(+) create mode 100644 Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Radix Sort/Tests/Info.plist create mode 100644 Radix Sort/Tests/RadixSortTests.swift create mode 100644 Radix Sort/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/.travis.yml b/.travis.yml index 9d8c6e346..64c23eb56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ script: # - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Radix\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Rootish\ Array\ Stack/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests diff --git a/Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata b/Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Radix Sort/RadixSort.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Radix Sort/Tests/Info.plist b/Radix Sort/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Radix Sort/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Radix Sort/Tests/RadixSortTests.swift b/Radix Sort/Tests/RadixSortTests.swift new file mode 100644 index 000000000..688bcdcb8 --- /dev/null +++ b/Radix Sort/Tests/RadixSortTests.swift @@ -0,0 +1,18 @@ +// +// 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) + } +} diff --git a/Radix Sort/Tests/Tests.xcodeproj/project.pbxproj b/Radix Sort/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..4b32f71b5 --- /dev/null +++ b/Radix Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,277 @@ +// !$*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"; + }; + 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_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_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E92991E25D03300B30F52 /* Debug */, + 056E929A1E25D03300B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E92A81E25D04D00B30F52 /* Debug */, + 056E92A91E25D04D00B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 056E92861E25D03300B30F52 /* Project object */; +} diff --git a/Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Radix Sort/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..b3f6d696a --- /dev/null +++ b/Radix Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 548f11791666bb2df3cae77183efda861171a0d0 Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 12 Jan 2017 20:17:41 -0800 Subject: [PATCH 0135/1039] Code restructuring - Moved source files Matrix.swift, MatrixSize.swift & Number.swift to the Sources foler in the PLayground - Restrucutred the code into extensions to make it more organized and readable - Deleted all the objects from the playground and moved them to the Sources folder --- .../MatrixSize.swift | 26 -- .../Contents.swift | 297 +----------------- .../Sources}/Matrix.swift | 183 +++++------ .../Sources/MatrixSize.swift | 33 ++ .../Sources}/Number.swift | 15 +- 5 files changed, 136 insertions(+), 418 deletions(-) delete mode 100644 Strassen Matrix Multiplication/MatrixSize.swift rename Strassen Matrix Multiplication/{ => StrassensMatrixMultiplication.playground/Sources}/Matrix.swift (72%) create mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift rename Strassen Matrix Multiplication/{ => StrassensMatrixMultiplication.playground/Sources}/Number.swift (71%) diff --git a/Strassen Matrix Multiplication/MatrixSize.swift b/Strassen Matrix Multiplication/MatrixSize.swift deleted file mode 100644 index f1eada931..000000000 --- a/Strassen Matrix Multiplication/MatrixSize.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// MatrixSize.swift -// -// -// Created by Richard Ash on 10/28/16. -// -// - -import Foundation - -struct MatrixSize: Equatable { - let rows: Int - let columns: Int - - func forEach(_ body: (Int, Int) throws -> Void) rethrows { - for row in 0.. Bool { - return lhs.columns == rhs.columns && lhs.rows == rhs.rows -} diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift index d4b4d8330..50af60a6f 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift @@ -1,302 +1,7 @@ //: Playground - noun: a place where people can play // Reference - http://mathworld.wolfram.com/StrassenFormulas.html - -import UIKit - -enum RowOrColumn { - case row, column -} - -protocol Number: Multipliable, Addable { - static var zero: Self { get } -} - -protocol Addable { - static func +(lhs: Self, rhs: Self) -> Self - static func -(lhs: Self, rhs: Self) -> Self -} - -protocol Multipliable { - static func *(lhs: Self, rhs: Self) -> Self -} - -extension Int: Number { - static var zero: Int { - return 0 - } -} - -extension Double: Number { - static var zero: Double { - return 0.0 - } -} - -extension Float: Number { - static var zero: Float { - return 0.0 - } -} - - -extension Array where Element: Number { - 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 }) - } -} - -struct MatrixSize: Equatable { - let rows: Int - let columns: Int - - func forEach(_ body: (Int, Int) throws -> Void) rethrows { - for row in 0.. Bool { - return lhs.columns == rhs.columns && lhs.rows == rhs.rows -} - - -struct Matrix { - - // MARK: - Variables - - let rows: Int, columns: Int - var grid: [T] - - var isSquare: Bool { - return rows == columns - } - - var size: MatrixSize { - return MatrixSize(rows: rows, columns: columns) - } - - // MARK: - Init - - init(rows: Int, columns: Int, initialValue: T = T.zero) { - self.rows = rows - self.columns = columns - self.grid = Array(repeating: initialValue, count: rows * columns) - } - - init(size: Int, initialValue: T = T.zero) { - self.rows = size - self.columns = size - self.grid = Array(repeating: initialValue, count: rows * columns) - } - - // MARK: - Subscript - - 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 - } - } - - subscript(type: RowOrColumn, 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") - var columns: [T] = [] - for row in 0.. Bool { - return row >= 0 && row < rows && column >= 0 && column < columns - } - - private func strassenR(by B: Matrix) -> 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 - - var a11 = Matrix(size: nBy2) - var a12 = Matrix(size: nBy2) - var a21 = Matrix(size: nBy2) - var a22 = Matrix(size: nBy2) - var b11 = Matrix(size: nBy2) - var b12 = Matrix(size: nBy2) - var b21 = Matrix(size: nBy2) - var b22 = Matrix(size: nBy2) - - for i in 0.. Int { - return Int(pow(2, ceil(log2(Double(n))))) - } - - // MARK: - Functions - - func strassenMatrixMultiply(by B: Matrix) -> 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(of: n) - - var APrep = Matrix(size: m) - var BPrep = Matrix(size: m) - - A.size.forEach { (i, j) in - APrep[i,j] = A[i,j] - } - - B.size.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.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..(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..(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.. { +public struct Matrix { // MARK: - Variables @@ -29,20 +29,22 @@ struct Matrix { // MARK: - Init - init(rows: Int, columns: Int, initialValue: T = T.zero) { + public init(rows: Int, columns: Int, initialValue: T = T.zero) { self.rows = rows self.columns = columns self.grid = Array(repeating: initialValue, count: rows * columns) } - init(size: Int, initialValue: T = T.zero) { + public init(size: Int, initialValue: T = T.zero) { self.rows = size self.columns = size self.grid = Array(repeating: initialValue, count: rows * columns) } - - // MARK: - Subscript - +} + +// MARK: - Public Functions + +public extension Matrix { subscript(row: Int, column: Int) -> T { get { assert(indexIsValid(row: row, column: column), "Index out of range") @@ -88,13 +90,59 @@ struct Matrix { } } - // MARK: - Private Functions + func strassenMatrixMultiply(by B: Matrix) -> 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(of: n) + + var APrep = Matrix(size: m) + var BPrep = Matrix(size: m) + + A.size.forEach { (i, j) in + APrep[i,j] = A[i,j] + } + + B.size.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.. Bool { + func matrixMultiply(by B: Matrix) -> 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.. Bool { return row >= 0 && row < rows && column >= 0 && column < columns } - private func strassenR(by B: Matrix) -> Matrix { + func strassenR(by B: Matrix) -> 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 } @@ -150,97 +198,56 @@ struct Matrix { return C } - private func nextPowerOfTwo(of n: Int) -> Int { + func nextPowerOfTwo(of n: Int) -> Int { return Int(pow(2, ceil(log2(Double(n))))) } - - // MARK: - Functions - - func strassenMatrixMultiply(by B: Matrix) -> 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(of: n) - - var APrep = Matrix(size: m) - var BPrep = Matrix(size: m) - - A.size.forEach { (i, j) in - APrep[i,j] = A[i,j] - } - - B.size.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.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..(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..(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 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 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.. Void) rethrows { + for row in 0.. Bool { + return lhs.columns == rhs.columns && lhs.rows == rhs.rows + } +} diff --git a/Strassen Matrix Multiplication/Number.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift similarity index 71% rename from Strassen Matrix Multiplication/Number.swift rename to Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift index 34c6d5308..9f4c7f4ab 100644 --- a/Strassen Matrix Multiplication/Number.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift @@ -8,40 +8,39 @@ import Foundation -protocol Number: Multipliable, Addable { +public protocol Number: Multipliable, Addable { static var zero: Self { get } } -protocol Addable { +public protocol Addable { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self } -protocol Multipliable { +public protocol Multipliable { static func *(lhs: Self, rhs: Self) -> Self } extension Int: Number { - static var zero: Int { + public static var zero: Int { return 0 } } extension Double: Number { - static var zero: Double { + public static var zero: Double { return 0.0 } } extension Float: Number { - static var zero: Float { + public static var zero: Float { return 0.0 } } - extension Array where Element: Number { - func dot(_ b: Array) -> Element { + 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] } From c260a3438c5e7103654d3b576b528065089c6972 Mon Sep 17 00:00:00 2001 From: pbodsk Date: Fri, 13 Jan 2017 13:31:37 +0100 Subject: [PATCH 0136/1039] migrates Single-Source Shortest Paths to Swift 3 syntax --- .travis.yml | 2 +- .../SSSP.playground/Contents.swift | 2 +- .../SSSP.xcodeproj/project.pbxproj | 13 +++++++++++- .../xcshareddata/xcschemes/SSSP.xcscheme | 2 +- .../xcshareddata/xcschemes/SSSPTests.xcscheme | 2 +- .../SSSP/BellmanFord.swift | 20 +++++++++---------- .../SSSP/SSSP.swift | 2 +- .../SSSPTests/SSSPTests.swift | 20 +++++++++---------- 8 files changed, 37 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9d8c6e346..765f07786 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ script: - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests +- xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Topological\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Treap/Treap/Treap.xcodeproj -scheme Tests diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift b/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift index ece36a663..652b558b1 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSP.playground/Contents.swift @@ -25,4 +25,4 @@ graph.addDirectedEdge(z, to: x, withWeight: 7) let result = BellmanFord.apply(graph, source: s)! -let path = result.path(z, inGraph: graph) +let path = result.path(to: z, inGraph: graph) diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj index 55893acfd..0dd67f69c 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj @@ -184,14 +184,16 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 49BFA2921CDF86E100522D66 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0810; }; 49BFA29C1CDF86E100522D66 = { CreatedOnToolsVersion = 7.3; + LastSwiftMigration = 0810; }; }; }; @@ -301,8 +303,10 @@ 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 = "-"; @@ -349,8 +353,10 @@ 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 = "-"; @@ -370,6 +376,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -392,6 +399,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -411,6 +419,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.swift-algorithm-club.SSSP"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -422,6 +431,7 @@ 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 = 3.0; }; name = Debug; }; @@ -433,6 +443,7 @@ 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 = 3.0; }; name = Release; }; diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme index 9d28c18c4..469159bd8 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/xcshareddata/xcschemes/SSSP.xcscheme @@ -1,6 +1,6 @@ { +public struct BellmanFord where T: Hashable { public typealias Q = T } @@ -30,12 +30,12 @@ extension BellmanFord: SSSPAlgorithm { - 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? { + public static func apply(_ graph: AbstractGraph, source: Vertex) -> BellmanFordResult? { let vertices = graph.vertices let edges = graph.edges - var predecessors = Array(count: vertices.count, repeatedValue: nil) - var weights = Array(count: vertices.count, repeatedValue: Double.infinity) + 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 @@ -78,10 +78,10 @@ extension BellmanFord: SSSPAlgorithm { 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 { +public struct BellmanFordResult where T: Hashable { - private var predecessors: [Int?] - private var weights: [Double] + fileprivate var predecessors: [Int?] + fileprivate var weights: [Double] } @@ -112,7 +112,7 @@ extension BellmanFordResult: SSSPResult { return nil } - guard let path = recursePath(to, inGraph: graph, path: [to]) else { + guard let path = recursePath(to: to, inGraph: graph, path: [to]) else { return nil } @@ -126,7 +126,7 @@ extension BellmanFordResult: SSSPResult { - returns: the list of predecessors discovered so far, or `nil` if the next vertex has no predecessor */ - private func recursePath(to: Vertex, inGraph graph: AbstractGraph, path: [Vertex]) -> [Vertex]? { + fileprivate func recursePath(to: Vertex, inGraph graph: AbstractGraph, path: [Vertex]) -> [Vertex]? { guard let predecessorIdx = predecessors[to.index] else { return nil } @@ -136,7 +136,7 @@ extension BellmanFordResult: SSSPResult { return [ to ] } - guard let buildPath = recursePath(predecessor, inGraph: graph, path: path) else { + guard let buildPath = recursePath(to: predecessor, inGraph: graph, path: path) else { return nil } diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift index 8e3afc40a..3066f6516 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSP/SSSP.swift @@ -18,7 +18,7 @@ protocol SSSPAlgorithm { associatedtype Q: Equatable, Hashable associatedtype P: SSSPResult - static func apply(graph: AbstractGraph, source: Vertex) -> P? + static func apply(_ graph: AbstractGraph, source: Vertex) -> P? } diff --git a/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift b/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift index 1bb862b74..04584dfeb 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSPTests/SSSPTests.swift @@ -40,11 +40,11 @@ class SSSPTests: XCTestCase { let result = BellmanFord.apply(graph, source: s)! let expectedPath = ["s", "y", "x", "t", "z"] - let computedPath = result.path(z, inGraph: graph)! + 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(z) + let computedWeight = result.distance(to: z) XCTAssertEqual(expectedWeight, computedWeight, "expected weight of \(expectedWeight) but got \(computedWeight)") } @@ -71,11 +71,11 @@ class SSSPTests: XCTestCase { let result = BellmanFord.apply(graph, source: a)! let expectedPath = ["a", "b", "c", "e", "d"] - let computedPath = result.path(d, inGraph: graph)! + 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(d) + let computedWeight = result.distance(to: d) XCTAssertEqual(expectedWeight, computedWeight, "expected weight of \(expectedWeight) but got \(computedWeight)") } @@ -104,12 +104,12 @@ class SSSPTests: XCTestCase { let result = BellmanFord.apply(graph, source: a)! - XCTAssertNil(result.path(b, inGraph: graph), "a path should not be defined from a ~> b") - XCTAssertNil(result.distance(b), "a path should not be defined from a ~> b") - XCTAssertNotNil(result.path(s, inGraph: graph), "a path should be defined from a ~> s") - XCTAssertNotNil(result.distance(s), "a path should be defined from a ~> s") - XCTAssertNotNil(result.path(t, inGraph: graph), "a path should be defined from a ~> t") - XCTAssertNotNil(result.distance(t), "a path should be defined from a ~> t") + 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() { From 2e5a4a60471ba9d215bfe52975bd563524908637 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 12:50:59 +0000 Subject: [PATCH 0137/1039] Update README.md --- DiningPhilosophers/README.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 06302cf2a..5f5d5383d 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -1,13 +1,35 @@ # SwiftDiningPhilosophers Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using GCD and Semaphore in Swift) -Written by Jacopo Mangiavacchi +Written for Swift Algorithm Club by Jacopo Mangiavacchi -# from https://en.wikipedia.org/wiki/Dining_philosophers_problem +# Introduction In computer science, the dining philosophers problem is an example problem often used in 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 use GCD Dispatch and Semaphone on 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. However, a philosopher can only eat spaghetti when they have both left and right forks. Each fork can be held by only one philosopher and so a philosopher can use the fork only if it is not being used by another philosopher. After an individual 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 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 an dinining table: + +![Dining Philosophers table](https://upload.wikimedia.org/wikipedia/commons/7/7b/An_illustration_of_the_dining_philosophers_problem.png) + + + +# See also + +Dining Philosophers on Wikipedia https://en.wikipedia.org/wiki/Dining_philosophers_problem + +Written for Swift Algorithm Club by Jacopo Mangiavacchi From 13d1827d697b030de86dcb042a2068b9f26f3f52 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 13:00:23 +0000 Subject: [PATCH 0138/1039] Update README.md --- DiningPhilosophers/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 5f5d5383d..22687d2fd 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -27,6 +27,27 @@ This is an illustration of an dinining 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 on the Chandy/Misra solution that more generally allows for arbitrary agents to contend for an arbitrary number of resources in a completely distributed scenario with no needs for a central authority to control the locking and serialization of resources. + +However, it is very important to note here that 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. For all such forks the philosopher does not have, they send a request message. +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 will solve an arbitrarily large problem. + +It also solves the starvation problem. The clean / dirty labels act as a way of giving 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. Chandy and Misra's solution is more flexible than that, but has an element tending in that direction. + +In their analysis they derive a system of preference levels from the distribution of the forks and their clean/dirty states. They show that this system may describe an acyclic graph, and if so, the operations in their 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, like all philosophers holding their left side forks, then the graph is cyclic at the outset, and their 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 + + # See also From 4daf0d07dedf6f638a494a535b69d63e17bdf53c Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 13:01:02 +0000 Subject: [PATCH 0139/1039] Update README.md --- DiningPhilosophers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 22687d2fd..3ac5b1343 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -1,4 +1,4 @@ -# SwiftDiningPhilosophers +# Dining Philosophers Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using GCD and Semaphore in Swift) Written for Swift Algorithm Club by Jacopo Mangiavacchi From 5b3f3c4570b17be37d4f19344e3755523a9bcd21 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 13:08:16 +0000 Subject: [PATCH 0140/1039] Update main.swift --- DiningPhilosophers/Sources/main.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DiningPhilosophers/Sources/main.swift b/DiningPhilosophers/Sources/main.swift index dfde40773..deff344b9 100755 --- a/DiningPhilosophers/Sources/main.swift +++ b/DiningPhilosophers/Sources/main.swift @@ -12,7 +12,7 @@ import Dispatch let numberOfPhilosophers = 4 -class ForkPair { +struct ForkPair { static let forksSemaphore:[DispatchSemaphore] = Array(repeating: DispatchSemaphore(value: 1), count: numberOfPhilosophers) let leftFork: DispatchSemaphore @@ -44,7 +44,7 @@ class ForkPair { } -class Philosophers { +struct Philosophers { let forkPair: ForkPair let philosopherIndex: Int From dca7bf14870e3007247344415b9d00e7d5cd8471 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Sat, 14 Jan 2017 13:23:28 +0000 Subject: [PATCH 0141/1039] Update README.md --- DiningPhilosophers/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 3ac5b1343..29b5916e9 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -47,7 +47,13 @@ In their analysis they derive a system of preference levels from the distributio # Swift implementation +This Swift 3.0 implementation of the Chandy/Misra solution is based on GCD and Semaphore tecnique and it could 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 simply used in order to keep the main thread on wait forever and let the Philosophers contienue forever in their alternate think and eat cycle. # See also From 671aa3b26f8ec5ea16c2bfdbc567c1f7a2f5819a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sat, 14 Jan 2017 14:57:45 -0800 Subject: [PATCH 0142/1039] Update README.markdown Added Dining Philosophers link. --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index e5c8f8dae..ad5f910b4 100644 --- a/README.markdown +++ b/README.markdown @@ -190,6 +190,7 @@ A lot of software developer interview questions consist of algorithmic puzzles. - [Fizz Buzz](Fizz Buzz/) - [Monty Hall Problem](Monty Hall Problem/) - [Finding Palindromes](Palindromes/) +- [Dining Philosophers](DiningPhilosophers/) ## Learn more! From 71d8a43149fe3b125ce21b4ae3f0ec8eeb50220c Mon Sep 17 00:00:00 2001 From: vincentngo Date: Sun, 15 Jan 2017 11:23:42 -0500 Subject: [PATCH 0143/1039] Update Target to Swift 3.0 --- .../SSSP.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj index 0dd67f69c..fb425a73e 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj +++ b/Single-Source Shortest Paths (Weighted)/SSSP.xcodeproj/project.pbxproj @@ -334,6 +334,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -377,6 +378,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; From cf0d1b539b2bf628a76e37b33332bab02c9bcc1a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 16 Jan 2017 10:59:20 -0800 Subject: [PATCH 0144/1039] Modified Z-Algorithm to conform to our style guide. --- Z-Algorithm/ZAlgorithm.swift | 116 +++++++------- .../ZetaAlgorithm.playground/Contents.swift | 150 +++++++++--------- Z-Algorithm/ZetaAlgorithm.swift | 56 +++---- 3 files changed, 161 insertions(+), 161 deletions(-) diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift index c9d7de876..9bef69687 100644 --- a/Z-Algorithm/ZAlgorithm.swift +++ b/Z-Algorithm/ZAlgorithm.swift @@ -1,66 +1,66 @@ /* 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 -*/ + + 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.characters) - 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 - } + + let pattern = Array(ptrn.characters) + 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 + } + return zeta } diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift index c9d942149..395122af0 100644 --- a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -2,88 +2,88 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { - - let pattern = Array(ptrn.characters) - 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 - } + + let pattern = Array(ptrn.characters) + 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 + } + return zeta } extension String { - - func indexesOf(pattern: String) -> [Int]? { - let patternLength: Int = pattern.characters.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 + + func indexesOf(pattern: String) -> [Int]? { + let patternLength = pattern.characters.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 */ diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift index 4d80aa665..c35703272 100644 --- a/Z-Algorithm/ZetaAlgorithm.swift +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -1,36 +1,36 @@ /* 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 -*/ + + 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.characters.count + let zeta = ZetaAlgorithm(ptrn: pattern + "💲" + self) + + guard zeta != nil else { + return nil + } + + var indexes: [Int] = [Int]() - func indexesOf(pattern: String) -> [Int]? { - let patternLength: Int = pattern.characters.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 + /* 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 + } } From e5fb825ffa5fb4604ac0dd40782c372b5a5aef20 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 16 Jan 2017 11:01:46 -0800 Subject: [PATCH 0145/1039] Update README.markdown Added Z-algorithm link. --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index ad5f910b4..2d7522b1e 100644 --- a/README.markdown +++ b/README.markdown @@ -50,6 +50,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [k-th Largest Element](Kth Largest Element/). Find the *k*-th largest element in an array, such as the median. - [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. - [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. +- [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. ### String Search From 10abdbc8efa765f6b9700498e9a08ab8de0ffbe1 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 16 Jan 2017 11:02:39 -0800 Subject: [PATCH 0146/1039] Update README.markdown Updated the Z-algorithm link to the String Search section. --- README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 2d7522b1e..97b84057b 100644 --- a/README.markdown +++ b/README.markdown @@ -50,7 +50,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [k-th Largest Element](Kth Largest Element/). Find the *k*-th largest element in an array, such as the median. - [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. - [Union-Find](Union-Find/). Keeps track of disjoint sets and lets you quickly merge them. -- [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. + ### String Search @@ -59,6 +59,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - Knuth-Morris-Pratt - Rabin-Karp - [Longest Common Subsequence](Longest Common Subsequence/). 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 From ca35d57d14073ac99f6a74c5a2057f1ab7f28c60 Mon Sep 17 00:00:00 2001 From: Bo Qian Date: Wed, 18 Jan 2017 17:25:53 -0800 Subject: [PATCH 0147/1039] Simplify the insert method by removing the fileprivate method. Delete duplicated BinarySearchTree.swift, so that there is only one single file. --- .../Sources/BinarySearchTree.swift | 14 +- .../Solution 1/BinarySearchTree.swift | 377 ------------------ .../Tests/Tests.xcodeproj/project.pbxproj | 8 +- .../contents.xcworkspacedata | 3 - 4 files changed, 9 insertions(+), 393 deletions(-) delete mode 100644 Binary Search Tree/Solution 1/BinarySearchTree.swift diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index f4960380e..5edbfc48a 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -23,7 +23,7 @@ public class BinarySearchTree { precondition(array.count > 0) self.init(value: array.first!) for v in array.dropFirst() { - insert(value: v, parent: self) + insert(value: v) } } @@ -74,23 +74,19 @@ extension BinarySearchTree { Performance: runs in O(h) time, where h is the height of the tree. */ public func insert(value: T) { - insert(value: value, parent: self) - } - - fileprivate func insert(value: T, parent: BinarySearchTree) { if value < self.value { if let left = left { - left.insert(value: value, parent: left) + left.insert(value: value) } else { left = BinarySearchTree(value: value) - left?.parent = parent + left?.parent = self } } else { if let right = right { - right.insert(value: value, parent: right) + right.insert(value: value) } else { right = BinarySearchTree(value: value) - right?.parent = parent + right?.parent = self } } } diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.swift deleted file mode 100644 index a58ac075a..000000000 --- a/Binary Search Tree/Solution 1/BinarySearchTree.swift +++ /dev/null @@ -1,377 +0,0 @@ -/* - 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 { - 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 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 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) { - insert(value, parent: self) - } - - private func insert(value: T, parent: BinarySearchTree) { - if value < self.value { - if let left = left { - left.insert(value, parent: left) - } else { - left = BinarySearchTree(value: value) - left?.parent = parent - } - } else { - if let right = right { - right.insert(value, parent: right) - } else { - right = BinarySearchTree(value: value) - right?.parent = parent - } - } - } -} - -// 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. - */ - public func remove() -> BinarySearchTree? { - let replacement: BinarySearchTree? - - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) - } else { - // This node only has a left child. The left child replaces the node. - replacement = left - } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - } - - reconnectParentToNode(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 removeNodeWithTwoChildren(left: BinarySearchTree, _ right: BinarySearchTree) -> BinarySearchTree { - // 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: 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 case 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) != nil - } - - /* - Returns the leftmost descendent. O(h) time. - */ - public func minimum() -> BinarySearchTree { - var node = self - while case let next? = node.left { - node = next - } - return node - } - - /* - Returns the rightmost descendent. O(h) time. - */ - public func maximum() -> BinarySearchTree { - var node = self - while case 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 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() -> BinarySearchTree? { - if let left = left { - return left.maximum() - } else { - var node = self - while case let parent? = node.parent { - if parent.value < value { return parent } - node = parent - } - return nil - } - } - - /* - Finds the node whose value succeeds our value in sorted order. - */ - public func successor() -> BinarySearchTree? { - if let right = right { - return right.minimum() - } else { - var node = self - while case let parent? = node.parent { - if parent.value > value { return parent } - node = parent - } - return nil - } - } -} - -// MARK: - Traversal - -extension BinarySearchTree { - public func traverseInOrder(@noescape process: T -> Void) { - left?.traverseInOrder(process) - process(value) - right?.traverseInOrder(process) - } - - public func traversePreOrder(@noescape process: T -> Void) { - process(value) - left?.traversePreOrder(process) - right?.traversePreOrder(process) - } - - public func traversePostOrder(@noescape process: T -> Void) { - left?.traversePostOrder(process) - right?.traversePostOrder(process) - process(value) - } - - /* - Performs an in-order traversal and collects the results in an array. - */ - public func map(@noescape formula: T -> T) -> [T] { - var a = [T]() - if let left = left { a += left.map(formula) } - a.append(formula(value)) - if let right = right { a += right.map(formula) } - return a - } -} - -/* - Is this binary tree a valid binary search tree? -*/ -extension BinarySearchTree { - public func isBST(minValue 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 - } -} - -extension BinarySearchTree: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" - } - if let left = left { - s += ", left = [" + left.debugDescription + "]" - } - if let right = right { - s += ", right = [" + right.debugDescription + "]" - } - return s - } - - public func toArray() -> [T] { - return map { $0 } - } -} diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj index c1d6c8029..7ecfe593f 100644 --- a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj @@ -7,15 +7,15 @@ objects = { /* Begin PBXBuildFile section */ - 7B80C3D81C77A313003CECC7 /* BinarySearchTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */; }; 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; }; - 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BinarySearchTree.swift; path = ../BinarySearchTree.swift; 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -48,7 +48,7 @@ 7B2BBC831C779D720067B71D /* Tests */ = { isa = PBXGroup; children = ( - 7B80C3D71C77A313003CECC7 /* BinarySearchTree.swift */, + 9E5A58B81E304C3100DAB3BB /* BinarySearchTree.swift */, 7B80C3D91C77A323003CECC7 /* BinarySearchTreeTests.swift */, 7B2BBC941C779E7B0067B71D /* Info.plist */, ); @@ -125,7 +125,7 @@ buildActionMask = 2147483647; files = ( 7B80C3DA1C77A323003CECC7 /* BinarySearchTreeTests.swift in Sources */, - 7B80C3D81C77A313003CECC7 /* BinarySearchTree.swift in Sources */, + 9E5A58B91E304C3100DAB3BB /* BinarySearchTree.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 4231528aa..b2ffce836 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -310,9 +310,6 @@ - - From 942e3b1738d95645e4dc49c483d84e9e094b1ea5 Mon Sep 17 00:00:00 2001 From: Bo Qian Date: Thu, 19 Jan 2017 18:33:43 -0800 Subject: [PATCH 0148/1039] Simplified the remove(). I feel the new implementation is more elegant and conceptually more straightforward. --- .../Sources/BinarySearchTree.swift | 97 +++++++------------ 1 file changed, 34 insertions(+), 63 deletions(-) diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index 5edbfc48a..31ae99a2f 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -106,58 +106,30 @@ extension BinarySearchTree { */ @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 left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) - } else { - // This node only has a left child. The left child replaces the node. - replacement = left - } + replacement = left.maximum() } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right + replacement = right.minimum() } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil + replacement = nil; } - - reconnectParentTo(node: replacement) - + + replacement?.remove(); + + // Place the replacement on current node's position + replacement?.right = right; + replacement?.left = left; + 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 removeNodeWithTwoChildren(_ left: BinarySearchTree, _ right: BinarySearchTree) -> BinarySearchTree { - // 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 + + return replacement; } private func reconnectParentTo(node: BinarySearchTree?) { @@ -350,24 +322,23 @@ extension BinarySearchTree: CustomStringConvertible { } return s } -} - -extension BinarySearchTree: CustomDebugStringConvertible { - public var debugDescription: String { - var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" - } - if let left = left { - s += ", left = [" + left.debugDescription + "]" - } - if let right = right { - s += ", right = [" + right.debugDescription + "]" - } - return s - } + + public func toArray() -> [T] { + return map { $0 } + } - 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 +// } +//} From c3ea705cb7623f9d6a9df3babcfcb01c61abcf4e Mon Sep 17 00:00:00 2001 From: Ray Wenderlich Date: Wed, 25 Jan 2017 11:46:55 -0500 Subject: [PATCH 0149/1039] Added license clarification. --- How to Contribute.markdown | 2 +- README.markdown | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 9e83b5ed6..258357e8b 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -21,7 +21,7 @@ To keep this a high quality repo, please follow this process when submitting you 1. Create a pull request to "claim" an algorithm or data structure. Just so multiple people don't work 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. If you wrote it, you deserve the credit and fame. +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. 6. Run [SwiftLint](https://github.com/realm/SwiftLint) - [Install](https://github.com/realm/SwiftLint#installation) diff --git a/README.markdown b/README.markdown index c6d2e0149..b33a8f8ae 100644 --- a/README.markdown +++ b/README.markdown @@ -233,4 +233,6 @@ The Swift Algorithm Club is a collaborative effort from the [most algorithmic me 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) From 40f667cfbb57e51ed5f639c9bfff5bdcc45fa867 Mon Sep 17 00:00:00 2001 From: Ray Wenderlich Date: Wed, 25 Jan 2017 11:47:48 -0500 Subject: [PATCH 0150/1039] Added Vincent as maintainer. --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index b33a8f8ae..e2d99e2bc 100644 --- a/README.markdown +++ b/README.markdown @@ -225,7 +225,7 @@ Other algorithm repositories: The Swift Algorithm Club was originally created by [Matthijs Hollemans](https://github.com/hollance). -It is now maintained by [Chris Pilcher](https://github.com/chris-pilcher) and [Kelvin Lau](https://github.com/kelvinlauKL). +It is now maintained by [Vincent Ngo](https://www.raywenderlich.com/u/jomoka) and [Kelvin Lau](https://github.com/kelvinlauKL). The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/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](How to Contribute.markdown)? :] From 1504e605537c2c2b881c8bdbdadac8eabc209bfd Mon Sep 17 00:00:00 2001 From: Jaap Date: Sat, 28 Jan 2017 01:10:46 +0100 Subject: [PATCH 0151/1039] migrated to swift 3 --- Run-Length Encoding/README.markdown | 121 ++++---- .../RLE.playground/Contents.swift | 162 ++++++----- .../RLE.playground/Sources/RLE.swift | 68 +++++ Run-Length Encoding/RLE.swift | 70 ----- Run-Length Encoding/Tests/Info.plist | 24 -- Run-Length Encoding/Tests/RLETests.swift | 110 -------- .../Tests/Tests.xcodeproj/project.pbxproj | 261 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/xcschemes/Tests.xcscheme | 90 ------ 9 files changed, 228 insertions(+), 685 deletions(-) create mode 100644 Run-Length Encoding/RLE.playground/Sources/RLE.swift delete mode 100644 Run-Length Encoding/RLE.swift delete mode 100644 Run-Length Encoding/Tests/Info.plist delete mode 100644 Run-Length Encoding/Tests/RLETests.swift delete mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/project.pbxproj delete mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Run-Length Encoding/README.markdown b/Run-Length Encoding/README.markdown index 8371b1227..f7d196161 100644 --- a/Run-Length Encoding/README.markdown +++ b/Run-Length Encoding/README.markdown @@ -3,14 +3,14 @@ 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 `NSData` that does a version of RLE inspired by the old [PCX image file format](https://en.wikipedia.org/wiki/PCX). +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: @@ -20,44 +20,42 @@ The rules are these: - 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 `NSData` object containing the run-length encoded bytes: +Here is the compression code. It returns a new `Data` object containing the run-length encoded bytes: ```swift -extension NSData { - public func compressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { // 1 - var count = 0 - var byte = ptr.memory - var next = byte - - while next == byte && ptr < end && count < 64 { // 2 - ptr = ptr.advancedBy(1) - next = ptr.memory - count += 1 - } - - if count > 1 || byte >= 192 { // 3 - var size = 191 + UInt8(count) - data.appendBytes(&size, length: 1) - data.appendBytes(&byte, length: 1) - } else { // 4 - data.appendBytes(&byte, length: 1) +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 } - return data - } -} ``` How it works: -1. We use an `UnsafePointer` to step through the bytes of the original `NSData` object. +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. @@ -69,11 +67,11 @@ You can test it like this in a playground: ```swift let originalString = "aaaaabbbcdeeeeeeef" -let utf8 = originalString.dataUsingEncoding(NSUTF8StringEncoding)! +let utf8 = originalString.data(using: String.Encoding.utf8)! let compressed = utf8.compressRLE() ``` -The compressed `NSData` object should be ``. Let's decode that by hand to see what has happened: +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". @@ -90,34 +88,38 @@ So that's 9 bytes encoded versus 18 original. That's a savings of 50%. Of course Here is the decompression code: ```swift - public func decompressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { - var byte = ptr.memory // 1 - ptr = ptr.advancedBy(1) - - if byte < 192 { // 2 - data.appendBytes(&byte, length: 1) - - } else if ptr < end { // 3 - var value = ptr.memory - ptr = ptr.advancedBy(1) - - for _ in 0 ..< byte - 191 { - data.appendBytes(&value, length: 1) - } +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 } - return data - } + ``` -1. Again this uses an `UnsafePointer` to read the `NSData`. Here we read the next byte; this is either a single value less than 192, or the start of a byte run. +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. @@ -134,6 +136,7 @@ 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. +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* diff --git a/Run-Length Encoding/RLE.playground/Contents.swift b/Run-Length Encoding/RLE.playground/Contents.swift index 41dcae3b1..62b4ef437 100644 --- a/Run-Length Encoding/RLE.playground/Contents.swift +++ b/Run-Length Encoding/RLE.playground/Contents.swift @@ -2,81 +2,115 @@ import Foundation -extension NSData { - /* - Compresses the NSData using run-length encoding. - */ - public func compressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length +let originalString = "aaaaabbbcdeeeeeeef" +let utf8 = originalString.data(using: String.Encoding.utf8)! +let compressed = utf8.compressRLE() - while ptr < end { - var count = 0 - var byte = ptr.memory - var next = byte +let decompressed = compressed.decompressRLE() +let restoredString = String(data: decompressed, encoding: String.Encoding.utf8) +originalString == restoredString - // 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.advancedBy(1) - next = ptr.memory - count += 1 - } +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 +} - if count > 1 || byte >= 192 { // byte run of up to 64 repeats - var size = 191 + UInt8(count) - data.appendBytes(&size, length: 1) - data.appendBytes(&byte, length: 1) - } else { // single byte between 0 and 192 - data.appendBytes(&byte, length: 1) - } - } - } - return data - } +func testEmpty() -> Bool { + let bytes: [UInt8] = [] + return encodeAndDecode(bytes) +} - /* - Converts a run-length encoded NSData back to the original. - */ - public func decompressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length +func testOneByteWithLowValue() -> Bool { + let bytes: [UInt8] = [0x80] + return encodeAndDecode(bytes) +} - 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.memory - ptr = ptr.advancedBy(1) +func testOneByteWithHighValue() -> Bool { + let bytes: [UInt8] = [0xD0] + return encodeAndDecode(bytes) +} - if byte < 192 { // single value - data.appendBytes(&byte, length: 1) +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) +} - } else if ptr < end { // byte run - // Read the actual data value. - var value = ptr.memory - ptr = ptr.advancedBy(1) +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) +} - // And write it out repeatedly. - for _ in 0 ..< byte - 191 { - data.appendBytes(&value, length: 1) - } +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 +} -let originalString = "aaaaabbbcdeeeeeeef" -let utf8 = originalString.dataUsingEncoding(NSUTF8StringEncoding)! -let compressed = utf8.compressRLE() - -let decompressed = compressed.decompressRLE() -let restoredString = String(data: decompressed, encoding: NSUTF8StringEncoding) -originalString == restoredString +runTests() \ No newline at end of file diff --git a/Run-Length Encoding/RLE.playground/Sources/RLE.swift b/Run-Length Encoding/RLE.playground/Sources/RLE.swift new file mode 100644 index 000000000..5707e3d9d --- /dev/null +++ b/Run-Length Encoding/RLE.playground/Sources/RLE.swift @@ -0,0 +1,68 @@ +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 + } +} diff --git a/Run-Length Encoding/RLE.swift b/Run-Length Encoding/RLE.swift deleted file mode 100644 index b62c59c63..000000000 --- a/Run-Length Encoding/RLE.swift +++ /dev/null @@ -1,70 +0,0 @@ -import Foundation - -extension NSData { - /* - Compresses the NSData using run-length encoding. - */ - public func compressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - while ptr < end { - var count = 0 - var byte = ptr.memory - 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.advancedBy(1) - next = ptr.memory - count += 1 - } - - if count > 1 || byte >= 192 { // byte run of up to 64 repeats - var size = 191 + UInt8(count) - data.appendBytes(&size, length: 1) - data.appendBytes(&byte, length: 1) - } else { // single byte between 0 and 192 - data.appendBytes(&byte, length: 1) - } - } - } - return data - } - - /* - Converts a run-length encoded NSData back to the original. - */ - public func decompressRLE() -> NSData { - let data = NSMutableData() - if length > 0 { - var ptr = UnsafePointer(bytes) - let end = ptr + length - - 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.memory - ptr = ptr.advancedBy(1) - - if byte < 192 { // single value - data.appendBytes(&byte, length: 1) - - } else if ptr < end { // byte run - // Read the actual data value. - var value = ptr.memory - ptr = ptr.advancedBy(1) - - // And write it out repeatedly. - for _ in 0 ..< byte - 191 { - data.appendBytes(&value, length: 1) - } - } - } - } - return data - } -} diff --git a/Run-Length Encoding/Tests/Info.plist b/Run-Length Encoding/Tests/Info.plist deleted file mode 100644 index ba72822e8..000000000 --- a/Run-Length Encoding/Tests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/Run-Length Encoding/Tests/RLETests.swift b/Run-Length Encoding/Tests/RLETests.swift deleted file mode 100644 index f4b2f8d7d..000000000 --- a/Run-Length Encoding/Tests/RLETests.swift +++ /dev/null @@ -1,110 +0,0 @@ -import XCTest - -class RLETests: XCTestCase { - private var showExtraOutput = false - - private func dumpData(data: NSData) { - if showExtraOutput { - var ptr = UnsafePointer(data.bytes) - for _ in 0.. - - - - diff --git a/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme deleted file mode 100644 index 8ef8d8581..000000000 --- a/Run-Length Encoding/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 2accb9907f434968e8806afe5637eeab69d4a0a9 Mon Sep 17 00:00:00 2001 From: Jaap Date: Sat, 28 Jan 2017 01:39:29 +0100 Subject: [PATCH 0152/1039] Migrate Shunting Yard to Swift 3 --- Shunting Yard/README.markdown | 5 +- .../ShuntingYard.playground/Contents.swift | 38 +- .../Sources/Stack.swift | 32 +- Shunting Yard/ShuntingYard.swift | 364 +++++++++--------- 4 files changed, 218 insertions(+), 221 deletions(-) diff --git a/Shunting Yard/README.markdown b/Shunting Yard/README.markdown index d2e568d39..72df4d346 100644 --- a/Shunting Yard/README.markdown +++ b/Shunting Yard/README.markdown @@ -6,7 +6,7 @@ Any mathematics we write is expressed in a notation known as *infix notation*. F The operator is placed in between the operands, hence the expression is said to be in *infix* form. If you think about it, any expression that you write on a piece of paper will always be in infix form. This is what we humans understand. -Multiplication has higher precedence than addition, so when the above expression is evaluated you would first multiply **B** and **C**, and then add the result to **A**. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. +Multiplication has higher precedence than addition, so when the above expression is evaluated you would first multiply **B** and **C**, and then add the result to **A**. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. To change the order of evaluation, we can use parentheses: @@ -108,4 +108,5 @@ We end up with the postfix expression: [Shunting yard algorithm on Wikipedia](https://en.wikipedia.org/wiki/Shunting-yard_algorithm) -*Written for the Swift Algorithm Club by [Ali Hafizji](http://www.github.com/aliHafizji)* \ No newline at end of file +*Written for the Swift Algorithm Club by [Ali Hafizji](http://www.github.com/aliHafizji)* +*Migrated to Swift 3 by Jaap Wijnen* diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index 707e2a0a3..b341c673b 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -15,17 +15,17 @@ public enum OperatorType: CustomStringConvertible { public var description: String { switch self { - case add: + case .add: return "+" - case subtract: + case .subtract: return "-" - case divide: + case .divide: return "/" - case multiply: + case .multiply: return "*" - case percent: + case .percent: return "%" - case exponent: + case .exponent: return "^" } } @@ -39,13 +39,13 @@ public enum TokenType: CustomStringConvertible { public var description: String { switch self { - case openBracket: + case .openBracket: return "(" - case closeBracket: + case .closeBracket: return ")" - case Operator(let operatorToken): + case .Operator(let operatorToken): return operatorToken.description - case operand(let value): + case .operand(let value): return "\(value)" } } @@ -141,23 +141,23 @@ public struct Token: CustomStringConvertible { public class InfixExpressionBuilder { private var expression = [Token]() - public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder { + public func addOperator(_ operatorType: OperatorType) -> InfixExpressionBuilder { expression.append(Token(operatorType: operatorType)) return self } - public func addOperand(operand: Double) -> InfixExpressionBuilder { + public func addOperand(_ operand: Double) -> InfixExpressionBuilder { expression.append(Token(operand: operand)) return self } public func addOpenBracket() -> InfixExpressionBuilder { - expression.append(Token(tokenType: .OpenBracket)) + expression.append(Token(tokenType: .openBracket)) return self } public func addCloseBracket() -> InfixExpressionBuilder { - expression.append(Token(tokenType: .CloseBracket)) + expression.append(Token(tokenType: .closeBracket)) return self } @@ -168,7 +168,7 @@ public class InfixExpressionBuilder { } // This returns the result of the shunting yard algorithm -public func reversePolishNotation(expression: [Token]) -> String { +public func reversePolishNotation(_ expression: [Token]) -> String { var tokenStack = Stack() var reversePolishNotation = [Token]() @@ -187,14 +187,14 @@ public func reversePolishNotation(expression: [Token]) -> String { } case .Operator(let operatorToken): - for tempToken in tokenStack.generate() { + 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 { + if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { reversePolishNotation.append(tokenStack.pop()!) } else { break @@ -209,7 +209,7 @@ public func reversePolishNotation(expression: [Token]) -> String { reversePolishNotation.append(tokenStack.pop()!) } - return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ") + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } diff --git a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift index 0df342af5..a67bb9d64 100644 --- a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift +++ b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift @@ -1,41 +1,37 @@ import Foundation public struct Stack { - private var array = [T]() - + fileprivate var array = [T]() + public init() { - array = [] + } - + public var isEmpty: Bool { return array.isEmpty } - + public var count: Int { return array.count } - - public mutating func push(element: T) { + + public mutating func push(_ element: T) { array.append(element) } - + public mutating func pop() -> T? { - if isEmpty { - return nil - } else { - return array.removeLast() - } + return array.popLast() } - - public func peek() -> T? { + + public var top: T? { return array.last } } -extension Stack: SequenceType { - public func generate() -> AnyGenerator { +extension Stack: Sequence { + public func makeIterator() -> AnyIterator { var curr = self - return anyGenerator { + return AnyIterator { _ -> T? in return curr.pop() } diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index 9d31d5a58..b8f5f8e6b 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -7,213 +7,213 @@ // internal enum OperatorAssociativity { - case leftAssociative - case rightAssociative + 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 "^" - } - } + 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)" - } - } + 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 - } + 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 + return left.precedence <= right.precedence } func < (left: OperatorToken, right: OperatorToken) -> Bool { - return left.precedence < right.precedence + 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 - } + 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 - } + 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.generate() { - 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 +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) } - tokenStack.push(token) } - } - - while tokenStack.count > 0 { - reversePolishNotation.append(tokenStack.pop()!) - } - - return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ") + + while tokenStack.count > 0 { + reversePolishNotation.append(tokenStack.pop()!) + } + + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } From 9d5c990ea69bd6f0fce8747630358a8391be48c5 Mon Sep 17 00:00:00 2001 From: Jaap Date: Sat, 28 Jan 2017 01:55:24 +0100 Subject: [PATCH 0153/1039] Set Cover migrated to swift 3 --- Set Cover (Unweighted)/README.markdown | 3 ++- .../SetCover.playground/Sources/RandomArrayOfSets.swift | 2 +- .../SetCover.playground/Sources/SetCover.swift | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Set Cover (Unweighted)/README.markdown b/Set Cover (Unweighted)/README.markdown index fde032438..0b4ddfefe 100644 --- a/Set Cover (Unweighted)/README.markdown +++ b/Set Cover (Unweighted)/README.markdown @@ -30,4 +30,5 @@ If there is no cover within the group of sets, `cover` returns `nil`. [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)* \ No newline at end of file +*Written for Swift Algorithm Club by [Michael C. Rael](https://github.com/mrael2)* +*Migrated to Swift 3 by Jaap Wijnen* diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift index b64d8d70e..9454c6383 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/RandomArrayOfSets.swift @@ -18,7 +18,7 @@ public func randomArrayOfSets(covering universe: Set, while true { let randomUniverseIndex = Int(arc4random_uniform(UInt32(universe.count))) - for (setIndex, value) in universe.enumerate() { + for (setIndex, value) in universe.enumerated() { if setIndex == randomUniverseIndex { generatedSet.insert(value) break diff --git a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift index 8d40e1fda..043cf46a0 100644 --- a/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift +++ b/Set Cover (Unweighted)/SetCover.playground/Sources/SetCover.swift @@ -8,7 +8,7 @@ public extension Set { var largestSet: Set? for set in array { - let intersectionLength = remainingSet.intersect(set).count + let intersectionLength = remainingSet.intersection(set).count if intersectionLength > largestIntersectionLength { largestIntersectionLength = intersectionLength largestSet = set @@ -21,7 +21,7 @@ public extension Set { while !remainingSet.isEmpty { guard let largestSet = largestIntersectingSet() else { break } result!.append(largestSet) - remainingSet = remainingSet.subtract(largestSet) + remainingSet = remainingSet.subtracting(largestSet) } if !remainingSet.isEmpty || isEmpty { From 83dea87c62a44e8d180811e4d1b5c9da211dddeb Mon Sep 17 00:00:00 2001 From: barbara Date: Sat, 28 Jan 2017 19:29:21 +0100 Subject: [PATCH 0154/1039] Splay Tree Initial Commit --- Splay Tree/readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Splay Tree/readme.md diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md new file mode 100644 index 000000000..2282502fa --- /dev/null +++ b/Splay Tree/readme.md @@ -0,0 +1 @@ +In progress From dcd1a0a877d72a5285b56401866ea9a9a97e8017 Mon Sep 17 00:00:00 2001 From: Bo Qian Date: Sat, 28 Jan 2017 18:11:26 -0800 Subject: [PATCH 0155/1039] Updated README.markdown for the new implementation of insert and remove. Added a remove example in BinarySearchTree.playground. --- .../Images/DeleteTwoChildren.graffle | Bin 2912 -> 11233 bytes .../Images/DeleteTwoChildren.png | Bin 13760 -> 33187 bytes Binary Search Tree/README.markdown | 132 ++++-------------- .../Contents.swift | 3 +- 4 files changed, 31 insertions(+), 104 deletions(-) diff --git a/Binary Search Tree/Images/DeleteTwoChildren.graffle b/Binary Search Tree/Images/DeleteTwoChildren.graffle index a03748077e6c23fec83e473e86fd9d71ef5fe97e..a6a09877a55b170f3d9f0938099d6841e93f1af7 100644 GIT binary patch literal 11233 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 literal 2912 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 diff --git a/Binary Search Tree/Images/DeleteTwoChildren.png b/Binary Search Tree/Images/DeleteTwoChildren.png index c0a77aab1f93d9026e523e2d2439d04ef5b943a5..1d941fe3c16265e73797fa9fc8ea5b621b9d5272 100644 GIT binary patch literal 33187 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 P_@kz*tyHXV*)&wu)y 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 diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index bacb1ffe1..e8d2f58e2 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -69,21 +69,14 @@ If you traverse a binary search tree in-order, it looks at all the nodes as if t ## Deleting nodes -Removing nodes is kinda tricky. It is easy to remove a leaf node, you just disconnect it from its parent: - -![Deleting a leaf node](Images/DeleteLeaf.png) - -If the node to remove has only one child, we can link that child to the parent node. So we just pull the node out: - -![Deleting a node with one child](Images/DeleteOneChild.png) - -The gnarly part is when the node to remove has two children. To keep the tree properly sorted, we must replace this node by the smallest child that is larger than the node: +Removing nodes is also 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 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) -This is always the leftmost descendant in the right subtree. It requires an additional search of at most **O(h)** to find this child. +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) -Most of the other code involving binary search trees is fairly straightforward (if you understand recursion) but deleting nodes is a bit of a headscratcher. ## The code (solution 1) @@ -158,23 +151,19 @@ A tree node by itself is pretty useless, so here is how you would add new nodes ```swift public func insert(value: T) { - insert(value, parent: self) - } - - private func insert(value: T, parent: BinarySearchTree) { if value < self.value { if let left = left { - left.insert(value, parent: left) + left.insert(value: value) } else { left = BinarySearchTree(value: value) - left?.parent = parent + left?.parent = self } } else { if let right = right { - right.insert(value, parent: right) + right.insert(value: value) } else { right = BinarySearchTree(value: value) - right?.parent = parent + right?.parent = self } } } @@ -379,7 +368,7 @@ As an exercise for yourself, see if you can implement filter and reduce. ### Deleting nodes -You've seen that deleting nodes can be tricky. We can make the code much more readable by defining some helper functions. +We can make the code much more readable by defining some helper functions. ```swift private func reconnectParentToNode(node: BinarySearchTree?) { @@ -396,7 +385,7 @@ You've seen that deleting nodes can be tricky. We can make the code much more re Making changes to the tree involves changing a bunch of `parent` and `left` and `right` pointers. This function helps with that. It takes the parent of the current node -- that is `self` -- and connects it to another node. Usually that other node will be one of the children of `self`. -We also need a function that returns the leftmost descendent of a node: +We also need a function that returns the minimum and maximum of a node: ```swift public func minimum() -> BinarySearchTree { @@ -406,17 +395,7 @@ We also need a function that returns the leftmost descendent of a node: } return node } -``` - -To see how this works, take the following tree: - -![Example](Images/MinimumMaximum.png) - -For example, if we look at node `10`, its leftmost descendent is `7`. We get there by following all the `left` pointers until there are no more left children to look at. The leftmost descendent of the root node `6` is `1`. Therefore, `1` is the minimum value in the entire tree. - -We won't need it for deleting, but for completeness' sake, here is the opposite of `minimum()`: - -```swift + public func maximum() -> BinarySearchTree { var node = self while case let next? = node.right { @@ -424,94 +403,41 @@ We won't need it for deleting, but for completeness' sake, here is the opposite } return node } -``` -It returns the rightmost descendent of the node. We find it by following `right` pointers until we get to the end. In the above example, the rightmost descendent of node `2` is `5`. The maximum value in the entire tree is `11`, because that is the rightmost descendent of the root node `6`. +``` -Finally, we can write the code that removes a node from the tree: +The rest of the code is pretty self-explanatory: ```swift - public func remove() -> BinarySearchTree? { + @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 left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) // 1 - } else { - replacement = left // 2 - } - } else if let right = right { // 3 - replacement = right + replacement = left.maximum() + } else if let right = right { + replacement = right.minimum() } else { - replacement = nil // 4 + replacement = nil; } - reconnectParentToNode(replacement) + replacement?.remove(); + // Place the replacement on current node's position + replacement?.right = right; + replacement?.left = left; + 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 - } -``` - -It doesn't look so scary after all. ;-) There are four situations to handle: - -1. This node has two children. -2. This node only has a left child. The left child replaces the node. -3. This node only has a right child. The right child replaces the node. -4. This node has no children. We just disconnect it from its parent. - -First, we determine which node will replace the one we're removing and then we call `reconnectParentToNode()` to change the `left`, `right`, and `parent` pointers to make that happen. Since the current node is no longer part of the tree, we clean it up by setting its pointers to `nil`. Finally, we return the node that has replaced the removed one (or `nil` if this was a leaf node). - -The only tricky situation here is `// 1` and that logic has its own helper method: - -```swift - private func removeNodeWithTwoChildren(left: BinarySearchTree, _ right: BinarySearchTree) -> BinarySearchTree { - let successor = right.minimum() - successor.remove() - - successor.left = left - left.parent = successor - - if right !== successor { - successor.right = right - right.parent = successor - } else { - successor.right = nil - } - return successor + return replacement; } ``` -If the node to remove has two children, it must be replaced by the smallest child that is larger than this node's value. That always happens to be the leftmost descendent of the right child, i.e. `right.minimum()`. We take that node out of its original position in the tree and put it into the place of the node we're removing. - -Try it out: - -```swift -if let node2 = tree.search(2) { - print(tree) // before - node2.remove() - print(tree) // after -} -``` - -First you find the node that you want to remove with `search()` and then you call `remove()` on that object. Before the removal, the tree printed like this: - - ((1) <- 2 -> (5)) <- 6 -> ((9) <- 10) - -But after `remove()` you get: - - ((1) <- 5) <- 6 -> ((9) <- 10) - -As you can see, node `5` has taken the place of `2`. - -> **Note:** What would happen if you deleted the root node? In that case, `remove()` tells you which node has become the new root. Try it out: call `tree.remove()` and see what happens. - -Like most binary search tree operations, removing a node runs in **O(h)** time, where **h** is the height of the tree. - ### 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: diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift index 6d73585b5..ec9902283 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Contents.swift @@ -7,8 +7,9 @@ tree.insert(value: 10) tree.insert(value: 9) tree.insert(value: 1) +let toDelete = tree.search(value: 1) +toDelete?.remove() tree -tree.debugDescription let tree2 = BinarySearchTree(array: [7, 2, 5, 10, 9, 1]) From eb54bc8544f0d482336878e211269ea43da9a7a7 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Mon, 30 Jan 2017 11:38:32 +0100 Subject: [PATCH 0156/1039] Add Simulated annealing --- Simulated annealing/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Simulated annealing/README.md diff --git a/Simulated annealing/README.md b/Simulated annealing/README.md new file mode 100644 index 000000000..bee8ffe94 --- /dev/null +++ b/Simulated annealing/README.md @@ -0,0 +1 @@ +# Simulated annealing From a6afbc107e25b96bdb86b9186f4a5794046b004b Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Mon, 30 Jan 2017 18:18:50 +0100 Subject: [PATCH 0157/1039] Initial --- Simulated annealing/README.md | 32 ++++ Simulated annealing/simann.swift | 105 +++++++++++ Simulated annealing/simann_example.swift | 222 +++++++++++++++++++++++ 3 files changed, 359 insertions(+) create mode 100644 Simulated annealing/simann.swift create mode 100644 Simulated annealing/simann_example.swift diff --git a/Simulated annealing/README.md b/Simulated annealing/README.md index bee8ffe94..e7fe75778 100644 --- a/Simulated annealing/README.md +++ b/Simulated annealing/README.md @@ -1 +1,33 @@ # Simulated annealing + +Simulated Annealing is a nature inspired global optimization technique and a metaheuristic to approximate global maxima in a (often discrete)large search space. The name comes from the process of annealing in metallurgy where a material is heated and cooled down under controlled conditions in order to improve its strength and durabilility. The objective is to find a minimum cost solution in the search space by exploiting properties of a thermodynamic system. +Unlike hill climbing techniques which usually gets stuck in a local maxima ( downward moves are not allowed ), simulated annealing can escape local maxima. The interesting property of simulated annealing is that probability of allowing downward moves is high at the high temperatures and gradually reduced as it cools down. In other words, high temperature relaxes the acceptance criteria for the search space and triggers chaotic behavior of acceptance function in the algorithm (e.x initial/high temperature stages) which should make it possible to escape from local maxima and cooler temperatures narrows it and focuses on improvements. + +Pseucocode + + Input: initial, temperature, coolingRate, acceptance + Output: Sbest + Scurrent <- CreateInitialSolution(initial) + Sbest <- Scurrent + while temperature is not minimum: + Snew <- FindNewSolution(Scurrent) + if acceptance(Energy(Scurrent), Energy(Snew), temperature) > Rand(): + Scurrent = Snew + if Energy(Scurrent) < Energy(Sbest): + Sbest = Scurrent + temperature = temperature * (1-coolingRate) + +Common acceptance criteria : P(accept) <- exp((e-ne)/T) where + e is the current energy ( current solution ), + ne is new energy ( new solution ), + T is current temperature. + + +We use this algorithm to solve a Travelling salesman problem instance with 20 cities. The code is in `simann_example.swift` + +#See also + +[Simulated annealing on Wikipedia](https://en.wikipedia.org/wiki/Simulated_annealing) +[Travelling salesman problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) + +Written for Swift Algorithm Club by [Mike Taghavi](https://github.com/mitghi) diff --git a/Simulated annealing/simann.swift b/Simulated annealing/simann.swift new file mode 100644 index 000000000..8adfbf817 --- /dev/null +++ b/Simulated annealing/simann.swift @@ -0,0 +1,105 @@ +// The MIT License (MIT) +// Copyright (c) 2017 Mike Taghavi (mitghi[at]me.com) +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if os(OSX) + import Foundation +#elseif os(Linux) + import Glibc +#endif + +public extension Double { + public static func random(_ lower: Double, _ upper: Double) -> Double { + #if os(OSX) + return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower + #elseif os(Linux) + return (Double(random()) / 0xFFFFFFFF) * (upper - lower) + lower + #endif + } +} + +protocol Clonable { + init(current: Self) +} + +// MARK: - create a clone from instance + +extension Clonable { + func clone() -> Self { + return Self.init(current: self) + } +} + +protocol SAObject: Clonable { + var count: Int { get } + func randSwap(a: Int, b: Int) + func currentEnergy() -> Double + func shuffle() +} + +// MARK: - create a new copy of elements + +extension Array where Element: Clonable { + func clone() -> Array { + var newArray = Array() + for elem in self { + newArray.append(elem.clone()) + } + + return newArray + } +} + +typealias AcceptanceFunc = (Double, Double, Double) -> Double + +func SimulatedAnnealing(initial: T, temperature: Double, coolingRate: Double, acceptance: AcceptanceFunc) -> T { + // Step 1: + // Calculate the initial feasible solution based on a random permutation. + // Set best and current solutions to initial solution + + var temp: Double = temperature + var currentSolution = initial.clone() + currentSolution.shuffle() + var bestSolution = currentSolution.clone() + + // Step 2: + // Repeat while the system is still hot + // Randomly modify the current solution by swapping its elements + // Randomly decide if the new solution ( neighbor ) is acceptable and set current solution accordingly + // Update the best solution *iff* it had improved ( lower energy = improvement ) + // Reduce temperature + + while temp > 1 { + let newSolution: T = currentSolution.clone() + let pos1: Int = Int(arc4random_uniform(UInt32(newSolution.count))) + let pos2: Int = Int(arc4random_uniform(UInt32(newSolution.count))) + newSolution.randSwap(a: pos1, b: pos2) + let currentEnergy: Double = currentSolution.currentEnergy() + let newEnergy: Double = newSolution.currentEnergy() + + if acceptance(currentEnergy, newEnergy, temp) > Double.random(0, 1) { + currentSolution = newSolution.clone() + } + if currentSolution.currentEnergy() < bestSolution.currentEnergy() { + bestSolution = currentSolution.clone() + } + + temp *= 1-coolingRate + } + + return bestSolution +} diff --git a/Simulated annealing/simann_example.swift b/Simulated annealing/simann_example.swift new file mode 100644 index 000000000..a0dfaa19a --- /dev/null +++ b/Simulated annealing/simann_example.swift @@ -0,0 +1,222 @@ +// The MIT License (MIT) +// Copyright (c) 2017 Mike Taghavi (mitghi[at]me.com) +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#if os(OSX) + import Foundation +#elseif os(Linux) + import Glibc +#endif + +public extension Double { + + public static func random(_ lower: Double, _ upper: Double) -> Double { + #if os(OSX) + return (Double(arc4random()) / 0xFFFFFFFF) * (upper - lower) + lower + #elseif os(Linux) + return (Double(random()) / 0xFFFFFFFF) * (upper - lower) + lower + #endif + } +} + +protocol Clonable { + init(current: Self) +} + +extension Clonable { + func clone() -> Self { + return Self.init(current: self) + } +} + +protocol SAObject: Clonable { + var count: Int { get } + func randSwap(a: Int, b: Int) + func currentEnergy() -> Double + func shuffle() +} + +// MARK: - create a new copy of elements + +extension Array where Element: Clonable { + func clone() -> Array { + var newArray = Array() + for elem in self { + newArray.append(elem.clone()) + } + + return newArray + } +} + +typealias Points = [Point] +typealias AcceptanceFunc = (Double, Double, Double) -> Double + +class Point: Clonable { + var x: Int + var y: Int + + init(x: Int, y: Int) { + self.x = x + self.y = y + } + + required init(current: Point){ + self.x = current.x + self.y = current.y + } +} + +// MARK: - string representation + +extension Point: CustomStringConvertible { + public var description: String { + return "Point(\(x), \(y))" + } +} + +// MARK: - return distance between two points using operator '<->' + +infix operator <->: AdditionPrecedence +extension Point { + static func <-> (left: Point, right: Point) -> Double { + let xDistance = (left.x - right.x) + let yDistance = (left.y - right.y) + + return Double(sqrt(Double((xDistance * xDistance) + (yDistance * yDistance)))) + } +} + + +class Tour: SAObject { + var tour: Points + var energy: Double = 0.0 + var count: Int { + get { + return self.tour.count + } + } + + init(points: Points){ + self.tour = points.clone() + } + + required init(current: Tour) { + self.tour = current.tour.clone() + } +} + +// MARK: - calculate current tour distance ( energy ). + +extension Tour { + func randSwap(a: Int, b: Int) -> Void { + let (cpos1, cpos2) = (self[a], self[b]) + self[a] = cpos2 + self[b] = cpos1 + } + + func shuffle() { + for i in stride(from: self.count - 1, through: 1, by: -1) { + let j = Int(arc4random()) % (i + 1) + if i != j { + swap(&self.tour[i], &self.tour[j]) + } + } + } + + func currentEnergy() -> Double { + if self.energy == 0 { + var tourEnergy: Double = 0.0 + for i in 0..destCity + tourEnergy = tourEnergy + e + + } + self.energy = tourEnergy + } + return self.energy + } + +} + +// MARK: - subscript to manipulate elements of Tour. + +extension Tour { + subscript(index: Int) -> Point { + get { + return self.tour[index] + } + set(newValue) { + self.tour[index] = newValue + } + } +} + +func SimulatedAnnealing(initial: T, temperature: Double, coolingRate: Double, acceptance: AcceptanceFunc) -> T { + var temp: Double = temperature + var currentSolution = initial.clone() + currentSolution.shuffle() + var bestSolution = currentSolution.clone() + print("Initial solution: ", bestSolution.currentEnergy()) + + while temp > 1 { + let newSolution: T = currentSolution.clone() + let pos1: Int = Int(arc4random_uniform(UInt32(newSolution.count))) + let pos2: Int = Int(arc4random_uniform(UInt32(newSolution.count))) + newSolution.randSwap(a: pos1, b: pos2) + let currentEnergy: Double = currentSolution.currentEnergy() + let newEnergy: Double = newSolution.currentEnergy() + + if acceptance(currentEnergy, newEnergy, temp) > Double.random(0, 1) { + currentSolution = newSolution.clone() + } + if currentSolution.currentEnergy() < bestSolution.currentEnergy() { + bestSolution = currentSolution.clone() + } + + temp *= 1-coolingRate + } + + print("Best solution: ", bestSolution.currentEnergy()) + return bestSolution +} + +let points: [Point] = [ + (60 , 200), (180, 200), (80 , 180), (140, 180), + (20 , 160), (100, 160), (200, 160), (140, 140), + (40 , 120), (100, 120), (180, 100), (60 , 80) , + (120, 80) , (180, 60) , (20 , 40) , (100, 40) , + (200, 40) , (20 , 20) , (60 , 20) , (160, 20) , + ].map{ Point(x: $0.0, y: $0.1) } + +let acceptance : AcceptanceFunc = { + (e: Double, ne: Double, te: Double) -> Double in + if ne < e { + return 1.0 + } + return exp((e - ne) / te) +} + +let result: Tour = SimulatedAnnealing(initial : Tour(points: points), + temperature : 100000.0, + coolingRate : 0.003, + acceptance : acceptance) From a794dec1522cd0df09b96a2d8744b261b8185f2a Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 30 Jan 2017 18:23:23 +0100 Subject: [PATCH 0158/1039] Update README.md --- Simulated annealing/README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Simulated annealing/README.md b/Simulated annealing/README.md index e7fe75778..3a36464d7 100644 --- a/Simulated annealing/README.md +++ b/Simulated annealing/README.md @@ -17,10 +17,12 @@ Pseucocode Sbest = Scurrent temperature = temperature * (1-coolingRate) -Common acceptance criteria : P(accept) <- exp((e-ne)/T) where - e is the current energy ( current solution ), - ne is new energy ( new solution ), - T is current temperature. +Common acceptance criteria : + + P(accept) <- exp((e-ne)/T) where + e is the current energy ( current solution ), + ne is new energy ( new solution ), + T is current temperature. We use this algorithm to solve a Travelling salesman problem instance with 20 cities. The code is in `simann_example.swift` @@ -28,6 +30,7 @@ We use this algorithm to solve a Travelling salesman problem instance with 20 ci #See also [Simulated annealing on Wikipedia](https://en.wikipedia.org/wiki/Simulated_annealing) + [Travelling salesman problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem) Written for Swift Algorithm Club by [Mike Taghavi](https://github.com/mitghi) From 717794dcb7cfaba84bc5f2dbbe3f316e5b7f57f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Azevedo?= Date: Wed, 1 Feb 2017 16:05:06 +0100 Subject: [PATCH 0159/1039] Fixed the trimming of deques --- Deque/Deque-Optimized.swift | 6 ++++-- Deque/README.markdown | 12 ++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index 6326b457b..f565458c7 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -7,9 +7,11 @@ 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 } @@ -30,7 +32,7 @@ public struct Deque { if head == 0 { capacity *= 2 let emptySpace = [T?](repeating: nil, count: capacity) - array.insertContentsOf(emptySpace, at: 0) + array.insert(contentsOf: emptySpace, at: 0) head = capacity } @@ -44,7 +46,7 @@ public struct Deque { array[head] = nil head += 1 - if capacity > 10 && head >= capacity*2 { + if capacity >= originalCapacity && head >= capacity*2 { let amountToRemove = capacity + capacity/2 array.removeFirst(amountToRemove) head -= amountToRemove diff --git a/Deque/README.markdown b/Deque/README.markdown index 5858f3e6d..d156f9d97 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -119,9 +119,11 @@ 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 } @@ -267,7 +269,7 @@ Those empty spots at the front only get used when you call `enqueueFront()`. But array[head] = nil head += 1 - if capacity > 10 && head >= capacity*2 { + if capacity >= originalCapacity && head >= capacity*2 { let amountToRemove = capacity + capacity/2 array.removeFirst(amountToRemove) head -= amountToRemove @@ -279,6 +281,8 @@ Those empty spots at the front only get used when you call `enqueueFront()`. But 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:** he 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 ] @@ -288,9 +292,9 @@ For example, this: becomes after trimming: [ x, x, x, x, x, 1, 2, 3 ] - | - head - capacity + | + head + capacity This way we can strike a balance between fast enqueuing and dequeuing at the front and keeping the memory requirements reasonable. From 096eca30aa4a686f4d0839321dd99089d63c6c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Azevedo?= Date: Wed, 1 Feb 2017 16:07:50 +0100 Subject: [PATCH 0160/1039] Typo fixed --- Deque/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Deque/README.markdown b/Deque/README.markdown index d156f9d97..67a734576 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -281,7 +281,7 @@ Those empty spots at the front only get used when you call `enqueueFront()`. But 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:** he deque will keep at least its original capacity by comparing `capacity` to `originalCapacity`. +> **Note:** The deque will keep at least its original capacity by comparing `capacity` to `originalCapacity`. For example, this: From 74bbb2105111797bad57ddc795b2b44cb494bb22 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Wed, 1 Feb 2017 19:09:34 -0800 Subject: [PATCH 0161/1039] Update README.markdown Hello, My name is Parvaneh. I am taking a writing course in the field of Computer Science. For an assignment, I need to edit some relevant documents and share the result. I hope you like my revisions. --- Merge Sort/README.markdown | 72 +++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Merge Sort/README.markdown b/Merge Sort/README.markdown index 3ff69fdd5..05b90f166 100644 --- a/Merge Sort/README.markdown +++ b/Merge Sort/README.markdown @@ -2,40 +2,40 @@ Goal: Sort an array from low to high (or high to low) -Invented in 1945 by John von Neumann, merge sort is a fairly efficient sorting algorithm with a best, worst, and average time complexity of **O(n log n)**. +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 idea behind merge sort is to **divide and conquer**: to divide a big problem into smaller problems and solving many small problems instead of solving a big one. I think of merge sort as **split first** and **merge after**. +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're given an array of *n* numbers and you need to put them in the right order. The merge sort algorithm works as follows: +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 a pile. The pile is unsorted. -- Split the pile into 2. Now you have **two unsorted piles** of numbers. -- Keep splitting the resulting piles until you can't split anymore. In the end, you will have *n* piles with 1 number in each pile. -- Begin to **merge** the piles together by sequentially pairing a pile with another pile. During each merge, you put the contents in sorted order. This is fairly easy because each individual pile is already sorted. +- 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 -Let's say the numbers to sort are `[2, 1, 5, 4, 9]`. This is your unsorted pile. The goal is to keep splitting the pile until you can't split anymore. +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! +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. `[2, 1]` will split into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile. +Focus on the left pile. Split`[2, 1]` into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile. -`[5, 4, 9]` splits to `[5]` and `[4, 9]`. Unsurprisingly, `[5]` can't be split anymore, but `[4, 9]` splits into `[4]` and `[9]`. +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've split the array, you'll **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'll only be concerned at merging one pile with another. +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 can't merge it with anything during this pass. +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 since it's the odd one out. +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're left with only two piles and `[9]` finally gets its chance to merge, resulting in the sorted array `[1, 2, 4, 5, 9]`. +You are left with only two piles and `[9]`, finally gets its chance to merge, resulting in the sorted array as `[1, 2, 4, 5, 9]`. ## Top-down implementation @@ -57,15 +57,15 @@ func mergeSort(_ array: [Int]) -> [Int] { A step-by-step explanation of how the code works: -1. If the array is empty or only contains a single element, there's no way to split it into smaller pieces. You'll just return the array. +1. If the array is empty or contains a single element, there is no way to split it into smaller pieces. You must just return the array. 2. Find the middle index. 3. Using the middle index from the previous step, recursively split the left side of the array. -4. Also recursively split the right side of the array. +4. Also, recursively split the right side of the array. -5. Finally, merge all the values together, making sure that it's always sorted. +5. Finally, merge all the values together, making sure that it is always sorted. Here's the merging algorithm: @@ -109,15 +109,15 @@ func merge(leftPile: [Int], rightPile: [Int]) -> [Int] { } ``` -This method may look scary but it is quite straightforward: +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's empty right now, but you'll build it up in subsequent steps by appending elements from the other arrays. +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. -3. This while loop will compare the elements from the left and right sides, and append them to the `orderedPile` while making sure that the result stays in order. +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 `leftPile` or `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's no more to append. +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: @@ -131,13 +131,13 @@ The left index, here represented as `l`, points at the first item from the left [ 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's `3`. The situation is now: +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 `leftPile` or `rightPile` and add it to `orderedPile`: +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 ] @@ -151,13 +151,13 @@ This process repeats. At each step we pick the smallest item from either `leftPi [ 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're done. The merged pile is `[ 1, 3, 6, 7, 8, 9 ]`. +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. +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 merge sort you've seen so far is called "top-down" 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. +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: @@ -212,19 +212,19 @@ func mergeSortBottomUp(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { } ``` -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()`. +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. Merge sort needs a temporary working array because you can't merge the left and right piles and at the same time overwrite their contents. But allocating a new array for each merge is wasteful. Therefore, we're using two working arrays and we'll switch between them using the value of `d`, which is either 0 or 1. The array `z[d]` is used for reading, `z[1 - d]` is used for writing. This is called *double-buffering*. +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 1 element each, then it merges piles of 2 elements each, then piles of 4 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 2. So this outer loop determines the size of the piles being merged. And in each step, the subarrays to merge become larger. +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 is generic and you can use it to sort any kind of object you want. +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've just created. +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. @@ -237,15 +237,15 @@ mergeSortBottomUp(array, <) // [1, 2, 4, 5, 9] ## Performance -The speed of merge sort is dependent on the size of the array it needs to sort. The larger the array, the more work it needs to do. +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 doesn't affect the speed of merge sort since you'll be doing the same amount splits and comparisons regardless of the initial order of the elements. +Whether or not the initial array is sorted already doesnot 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 merge sort 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/). +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 merge sort 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. +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 From b99c037c861f295f63470d394a66b2dcaed40303 Mon Sep 17 00:00:00 2001 From: Keizar Date: Fri, 3 Feb 2017 13:20:07 -0800 Subject: [PATCH 0162/1039] update README.markdown --- Bubble Sort/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Bubble Sort/README.markdown b/Bubble Sort/README.markdown index ceb2a98cb..93d370827 100644 --- a/Bubble Sort/README.markdown +++ b/Bubble Sort/README.markdown @@ -1,14 +1,14 @@ # 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 the array is completely sorted. The smaller items slowly “bubble” up to the beginning of the array. +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. ##### Runtime: -- Average: O(N^2) +- Average: O(N^2) - Worst: O(N^2) -##### Memory: +##### Memory: - O(1) ### Implementation: -The implementation will not be shown because as you can see from the average and worst runtimes this is a very inefficient algorithm but having a grasp of the concept will help in getting to know the basics of simple sorting algorithms. +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. From c22799378133820468783a1699be31d13c0f9d29 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Feb 2017 18:22:06 +0800 Subject: [PATCH 0163/1039] left/right tree should reconnect to new node --- .../Sources/BinarySearchTree.swift | 8 +- .../Tests/BinarySearchTreeTests.swift | 87 ++++++++++--------- .../Tests/Tests.xcodeproj/project.pbxproj | 5 +- .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++ 4 files changed, 61 insertions(+), 47 deletions(-) create mode 100644 Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index 31ae99a2f..74399efef 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -109,10 +109,10 @@ extension 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 left = left { - replacement = left.maximum() - } else if let right = right { + if let right = right { replacement = right.minimum() + } else if let left = left { + replacement = left.maximum() } else { replacement = nil; } @@ -122,6 +122,8 @@ extension BinarySearchTree { // 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. diff --git a/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift b/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift index 7c7fd069b..30749d8e4 100755 --- a/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift +++ b/Binary Search Tree/Solution 1/Tests/BinarySearchTreeTests.swift @@ -17,8 +17,8 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.count, 8) XCTAssertEqual(tree.toArray(), [3, 5, 6, 8, 9, 10, 12, 16]) - XCTAssertEqual(tree.search(9)!.value, 9) - XCTAssertNil(tree.search(99)) + XCTAssertEqual(tree.search(value: 9)!.value, 9) + XCTAssertNil(tree.search(value: 99)) XCTAssertEqual(tree.minimum().value, 3) XCTAssertEqual(tree.maximum().value, 16) @@ -26,17 +26,17 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.height(), 3) XCTAssertEqual(tree.depth(), 0) - let node1 = tree.search(16) + let node1 = tree.search(value: 16) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 3) - let node2 = tree.search(12) + let node2 = tree.search(value: 12) XCTAssertNotNil(node2) XCTAssertEqual(node2!.height(), 1) XCTAssertEqual(node2!.depth(), 2) - let node3 = tree.search(10) + let node3 = tree.search(value: 10) XCTAssertNotNil(node3) XCTAssertEqual(node3!.height(), 2) XCTAssertEqual(node3!.depth(), 1) @@ -45,32 +45,32 @@ class BinarySearchTreeTest: XCTestCase { func testInsert() { let tree = BinarySearchTree(value: 8) - tree.insert(5) + tree.insert(value: 5) XCTAssertEqual(tree.count, 2) XCTAssertEqual(tree.height(), 1) XCTAssertEqual(tree.depth(), 0) - let node1 = tree.search(5) + let node1 = tree.search(value: 5) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 1) - tree.insert(10) + tree.insert(value: 10) XCTAssertEqual(tree.count, 3) XCTAssertEqual(tree.height(), 1) XCTAssertEqual(tree.depth(), 0) - let node2 = tree.search(10) + let node2 = tree.search(value: 10) XCTAssertNotNil(node2) XCTAssertEqual(node2!.height(), 0) XCTAssertEqual(node2!.depth(), 1) - tree.insert(3) + tree.insert(value: 3) XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.height(), 2) XCTAssertEqual(tree.depth(), 0) - let node3 = tree.search(3) + let node3 = tree.search(value: 3) XCTAssertNotNil(node3) XCTAssertEqual(node3!.height(), 0) XCTAssertEqual(node3!.depth(), 2) @@ -84,9 +84,9 @@ class BinarySearchTreeTest: XCTestCase { func testInsertDuplicates() { let tree = BinarySearchTree(array: [8, 5, 10]) - tree.insert(8) - tree.insert(5) - tree.insert(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]) } @@ -108,7 +108,7 @@ class BinarySearchTreeTest: XCTestCase { } func testInsertSorted() { - let tree = BinarySearchTree(array: [8, 5, 10, 3, 12, 9, 6, 16].sort(<)) + 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]) @@ -118,7 +118,7 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.height(), 7) XCTAssertEqual(tree.depth(), 0) - let node1 = tree.search(16) + let node1 = tree.search(value: 16) XCTAssertNotNil(node1) XCTAssertEqual(node1!.height(), 0) XCTAssertEqual(node1!.depth(), 7) @@ -127,15 +127,15 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveLeaf() { let tree = BinarySearchTree(array: [8, 5, 10, 4]) - let node10 = tree.search(10)! + let node10 = tree.search(value: 10)! XCTAssertNil(node10.left) XCTAssertNil(node10.right) XCTAssertTrue(tree.right === node10) - let node5 = tree.search(5)! + let node5 = tree.search(value: 5)! XCTAssertTrue(tree.left === node5) - let node4 = tree.search(4)! + let node4 = tree.search(value: 4)! XCTAssertTrue(node5.left === node4) XCTAssertNil(node5.right) @@ -158,8 +158,8 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveOneChildLeft() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9]) - let node4 = tree.search(4)! - let node5 = tree.search(5)! + let node4 = tree.search(value: 4)! + let node5 = tree.search(value: 5)! XCTAssertTrue(node5.left === node4) XCTAssertTrue(node5 === node4.parent) @@ -171,8 +171,8 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.toArray(), [4, 8, 9, 10]) - let node9 = tree.search(9)! - let node10 = tree.search(10)! + let node9 = tree.search(value: 9)! + let node10 = tree.search(value: 10)! XCTAssertTrue(node10.left === node9) XCTAssertTrue(node10 === node9.parent) @@ -188,8 +188,8 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveOneChildRight() { let tree = BinarySearchTree(array: [8, 5, 10, 6, 11]) - let node6 = tree.search(6)! - let node5 = tree.search(5)! + let node6 = tree.search(value: 6)! + let node5 = tree.search(value: 5)! XCTAssertTrue(node5.right === node6) XCTAssertTrue(node5 === node6.parent) @@ -201,8 +201,8 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.count, 4) XCTAssertEqual(tree.toArray(), [6, 8, 10, 11]) - let node11 = tree.search(11)! - let node10 = tree.search(10)! + let node11 = tree.search(value: 11)! + let node10 = tree.search(value: 10)! XCTAssertTrue(node10.right === node11) XCTAssertTrue(node10 === node11.parent) @@ -218,9 +218,9 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveTwoChildrenSimple() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 6, 9, 11]) - let node4 = tree.search(4)! - let node5 = tree.search(5)! - let node6 = tree.search(6)! + 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) @@ -241,9 +241,9 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertEqual(tree.count, 6) XCTAssertEqual(tree.toArray(), [4, 6, 8, 9, 10, 11]) - let node9 = tree.search(9)! - let node10 = tree.search(10)! - let node11 = tree.search(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) @@ -268,11 +268,12 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveTwoChildrenComplex() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9, 20, 11, 15, 13]) - let node9 = tree.search(9)! - let node10 = tree.search(10)! - let node11 = tree.search(11)! - let node15 = tree.search(15)! - let node20 = tree.search(20)! + 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) @@ -290,8 +291,8 @@ class BinarySearchTreeTest: XCTestCase { XCTAssertTrue(node11 === node9.parent) XCTAssertTrue(node11.right === node20) XCTAssertTrue(node11 === node20.parent) - XCTAssertTrue(node20.left === node15) - XCTAssertTrue(node20 === node15.parent) + XCTAssertTrue(node20.left === node13) + XCTAssertTrue(node20 === node13.parent) XCTAssertNil(node20.right) XCTAssertNil(node10.left) XCTAssertNil(node10.right) @@ -303,7 +304,7 @@ class BinarySearchTreeTest: XCTestCase { func testRemoveRoot() { let tree = BinarySearchTree(array: [8, 5, 10, 4, 9, 20, 11, 15, 13]) - let node9 = tree.search(9)! + let node9 = tree.search(value: 9)! let newRoot = tree.remove() XCTAssertTrue(newRoot === node9) @@ -319,7 +320,7 @@ class BinarySearchTreeTest: XCTestCase { func testPredecessor() { let tree = BinarySearchTree(array: [3, 1, 2, 5, 4]) - let node = tree.search(5) + let node = tree.search(value: 5) XCTAssertEqual(node!.value, 5) XCTAssertEqual(node!.predecessor()!.value, 4) @@ -331,7 +332,7 @@ class BinarySearchTreeTest: XCTestCase { func testSuccessor() { let tree = BinarySearchTree(array: [3, 1, 2, 5, 4]) - let node = tree.search(1) + let node = tree.search(value: 1) XCTAssertEqual(node!.value, 1) XCTAssertEqual(node!.successor()!.value, 2) diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj index 7ecfe593f..f4c3f65c7 100644 --- a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.pbxproj @@ -15,7 +15,7 @@ 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 = ""; }; + 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 */ @@ -88,6 +88,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -220,6 +221,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +233,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..08de0be8d --- /dev/null +++ b/Binary Search Tree/Solution 1/Tests/Tests.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + From eef96f6431477e31598e884a72d3178c9b06e8f6 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Feb 2017 17:59:53 +0800 Subject: [PATCH 0164/1039] unmark .travis.yml test for BinarySearchTree --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 80ced8b6c..2b2bafd14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - xcodebuild test -project ./AVL\ Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Boyer-Moore/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests # - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests From 78da2c7b4719f55faaa69f2ae0c0324eb3423db0 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Feb 2017 17:36:46 +0800 Subject: [PATCH 0165/1039] lint files --- .../Sources/BinarySearchTree.swift | 24 +++++++++---------- .../Contents.swift | 2 -- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift index 74399efef..8a126e950 100644 --- a/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift +++ b/Binary Search Tree/Solution 1/BinarySearchTree.playground/Sources/BinarySearchTree.swift @@ -22,7 +22,7 @@ public class BinarySearchTree { public convenience init(array: [T]) { precondition(array.count > 0) self.init(value: array.first!) - for v in array.dropFirst() { + for v in array.dropFirst() { insert(value: v) } } @@ -106,7 +106,7 @@ extension BinarySearchTree { */ @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 { @@ -114,24 +114,24 @@ extension BinarySearchTree { } else if let left = left { replacement = left.maximum() } else { - replacement = nil; + replacement = nil } - - replacement?.remove(); + + replacement?.remove() // Place the replacement on current node's position - replacement?.right = right; - replacement?.left = left; + replacement?.right = right + replacement?.left = left right?.parent = replacement left?.parent = replacement - reconnectParentTo(node: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; + + return replacement } private func reconnectParentTo(node: BinarySearchTree?) { @@ -324,7 +324,7 @@ extension BinarySearchTree: CustomStringConvertible { } return s } - + public func toArray() -> [T] { return map { $0 } } diff --git a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift index 8df69fb6a..2b5dcc341 100644 --- a/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift +++ b/Binary Search Tree/Solution 2/BinarySearchTree.playground/Contents.swift @@ -12,5 +12,3 @@ print(tree) tree.search(x: 10) tree.search(x: 1) tree.search(x: 11) - - From f47a45e967ec651b6091f1d81a352f15420fd564 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 4 Feb 2017 17:56:24 +0800 Subject: [PATCH 0166/1039] Update README.markdown --- Binary Search Tree/README.markdown | 75 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index e8d2f58e2..bd2a00c9e 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -58,7 +58,7 @@ Sometimes you don't want to look at just a single node, but at all of them. 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. +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. Once again, this happens recursively. @@ -133,7 +133,7 @@ public class BinarySearchTree { } ``` -This class describes just a single node, not the entire tree. It's 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. +This class describes just a single node, not the entire tree. It's 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's how you'd use it: @@ -258,7 +258,7 @@ Here is the implementation of `search()`: 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. -Of course, 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. +Of course, 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's very conveniently done with optional chaining; when you write `left?.search(value)` it automatically returns nil if `left` is nil. There's no need to explicitly check for this with an `if` statement. @@ -300,21 +300,21 @@ The first three lines all return the corresponding `BinaryTreeNode` object. The Remember there are 3 different ways to look at all nodes in the tree? Here they are: ```swift - public func traverseInOrder(@noescape process: T -> Void) { - left?.traverseInOrder(process) + public func traverseInOrder(process: (T) -> Void) { + left?.traverseInOrder(process: process) process(value) - right?.traverseInOrder(process) + right?.traverseInOrder(process: process) } - - public func traversePreOrder(@noescape process: T -> Void) { + + public func traversePreOrder(process: (T) -> Void) { process(value) - left?.traversePreOrder(process) - right?.traversePreOrder(process) + left?.traversePreOrder(process: process) + right?.traversePreOrder(process: process) } - - public func traversePostOrder(@noescape process: T -> Void) { - left?.traversePostOrder(process) - right?.traversePostOrder(process) + + public func traversePostOrder(process: (T) -> Void) { + left?.traversePostOrder(process: process) + right?.traversePostOrder(process: process) process(value) } ``` @@ -339,11 +339,12 @@ This prints the following: You can also add things like `map()` and `filter()` to the tree. For example, here's an implementation of map: ```swift - public func map(@noescape formula: T -> T) -> [T] { + + public func map(formula: (T) -> T) -> [T] { var a = [T]() - if let left = left { a += left.map(formula) } + if let left = left { a += left.map(formula: formula) } a.append(formula(value)) - if let right = right { a += right.map(formula) } + if let right = right { a += right.map(formula: formula) } return a } ``` @@ -365,7 +366,7 @@ tree.toArray() // [1, 2, 5, 7, 9, 10] ``` As an exercise for yourself, see if you can implement filter and reduce. - + ### Deleting nodes We can make the code much more readable by defining some helper functions. @@ -395,7 +396,7 @@ We also need a function that returns the minimum and maximum of a node: } return node } - + public func maximum() -> BinarySearchTree { var node = self while case let next? = node.right { @@ -411,30 +412,32 @@ The rest of the code is pretty 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 left = left { - replacement = left.maximum() - } else if let right = right { + if let right = right { replacement = right.minimum() + } else if let left = left { + replacement = left.maximum() } else { - replacement = nil; + replacement = nil } - - replacement?.remove(); + + replacement?.remove() // Place the replacement on current node's position - replacement?.right = right; - replacement?.left = left; - reconnectParentTo(node:replacement); - + 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; + + return replacement } ``` @@ -574,7 +577,7 @@ if let node1 = tree.search(1) { ## The code (solution 2) -We've implemented the binary tree node as a class but you can also use an enum. +We've 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. @@ -588,7 +591,7 @@ public enum BinarySearchTree { } ``` -The enum has three cases: +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. @@ -606,7 +609,7 @@ As usual, we'll implement most functionality recursively. We'll treat each case case let .Node(left, _, right): return left.count + 1 + right.count } } - + public var height: Int { switch self { case .Empty: return 0 @@ -623,7 +626,7 @@ Inserting new nodes looks like this: switch self { case .Empty: return .Leaf(newValue) - + case .Leaf(let value): if newValue < value { return .Node(.Leaf(newValue), value, .Empty) From 257e973125884983b42193d7e67d1a6155081b4c Mon Sep 17 00:00:00 2001 From: Julio Guzman Date: Mon, 6 Feb 2017 16:32:26 -0600 Subject: [PATCH 0167/1039] Change last upgrade version --- .../Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Breadth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 6 Feb 2017 16:32:42 -0600 Subject: [PATCH 0168/1039] Change last upgrade check --- Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj index 33be43391..a04c95170 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -89,7 +89,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { From c8ce274329483d25f8e3ddfb3917419dad7eb9b0 Mon Sep 17 00:00:00 2001 From: Julio Guzman Date: Mon, 6 Feb 2017 16:40:38 -0600 Subject: [PATCH 0169/1039] Add assignation to remove warning --- Breadth-First Search/Tests/Graph.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Breadth-First Search/Tests/Graph.swift b/Breadth-First Search/Tests/Graph.swift index ed71cab7c..09684da5b 100644 --- a/Breadth-First Search/Tests/Graph.swift +++ b/Breadth-First Search/Tests/Graph.swift @@ -86,7 +86,7 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + let _ = duplicated.addNode(node.label) } for node in nodes { From e0a3b634d087a3376ba2f2478effd872cbe800f1 Mon Sep 17 00:00:00 2001 From: Julio Guzman Date: Mon, 6 Feb 2017 16:51:01 -0600 Subject: [PATCH 0170/1039] Migrates Breadth First Search tests project to Swift 3 syntax --- Breadth-First Search/Tests/Graph.swift | 8 ++++---- Breadth-First Search/Tests/Queue.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Breadth-First Search/Tests/Graph.swift b/Breadth-First Search/Tests/Graph.swift index 09684da5b..5e0837160 100644 --- a/Breadth-First Search/Tests/Graph.swift +++ b/Breadth-First Search/Tests/Graph.swift @@ -39,7 +39,7 @@ public class Node: CustomStringConvertible, Equatable { } public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + neighbors.remove(at: neighbors.index { $0 === edge }!) } } @@ -56,13 +56,13 @@ public class Graph: CustomStringConvertible, Equatable { self.nodes = [] } - public func addNode(label: String) -> Node { + public func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { + public func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } @@ -78,7 +78,7 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + public func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } diff --git a/Breadth-First Search/Tests/Queue.swift b/Breadth-First Search/Tests/Queue.swift index bf462bbdd..3d98f801c 100644 --- a/Breadth-First Search/Tests/Queue.swift +++ b/Breadth-First Search/Tests/Queue.swift @@ -13,7 +13,7 @@ public struct Queue { return array.count } - public mutating func enqueue(element: T) { + public mutating func enqueue(_ element: T) { array.append(element) } diff --git a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj index a04c95170..f86abf86e 100644 --- a/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Breadth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -230,6 +231,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -242,6 +244,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; From ca8e7ff4be86d94c8f5fea31d50a74896362b0dc Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 6 Feb 2017 17:26:07 -0800 Subject: [PATCH 0171/1039] Fixed spacing. --- .../ShuntingYard.playground/Contents.swift | 174 ++++----- Shunting Yard/ShuntingYard.swift | 366 +++++++++--------- 2 files changed, 270 insertions(+), 270 deletions(-) diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index b341c673b..fa9f5745b 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -12,21 +12,21 @@ public enum OperatorType: CustomStringConvertible { 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 "^" + case .add: + return "+" + case .subtract: + return "-" + case .divide: + return "/" + case .multiply: + return "*" + case .percent: + return "%" + case .exponent: + return "^" } } } @@ -36,48 +36,48 @@ public enum TokenType: CustomStringConvertible { 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)" + 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 + 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 + case .add, .subtract, .divide, .multiply, .percent: + return .leftAssociative + case .exponent: + return .rightAssociative } } - + public var description: String { return operatorType.description } @@ -93,46 +93,46 @@ func < (left: OperatorToken, right: OperatorToken) -> Bool { 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 + case .openBracket: + return true + default: + return false } } - + var isOperator: Bool { switch tokenType { - case .Operator(_): - return true - default: - return false + case .Operator(_): + return true + default: + return false } } - + var operatorToken: OperatorToken? { switch tokenType { - case .Operator(let operatorToken): - return operatorToken - default: - return nil + case .Operator(let operatorToken): + return operatorToken + default: + return nil } } - + public var description: String { return tokenType.description } @@ -140,27 +140,27 @@ public struct Token: CustomStringConvertible { 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 @@ -169,46 +169,46 @@ public class InfixExpressionBuilder { // 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 .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 } - - case .Operator(let operatorToken): - for tempToken in tokenStack.makeIterator() { - if !tempToken.isOperator { + + if let tempOperatorToken = tempToken.operatorToken { + if operatorToken.associativity == .leftAssociative && operatorToken <= tempOperatorToken + || operatorToken.associativity == .rightAssociative && operatorToken < tempOperatorToken { + reversePolishNotation.append(tokenStack.pop()!) + } else { 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) + } + tokenStack.push(token) } } - + while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } - + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index b8f5f8e6b..97a72249d 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -7,213 +7,213 @@ // internal enum OperatorAssociativity { - case leftAssociative - case rightAssociative + 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 "^" - } - } + 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)" - } - } + 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 - } + 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 + return left.precedence <= right.precedence } func < (left: OperatorToken, right: OperatorToken) -> Bool { - return left.precedence < right.precedence + 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 - } + 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 - } + 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) + + 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 } - } - - while tokenStack.count > 0 { - reversePolishNotation.append(tokenStack.pop()!) - } - - return reversePolishNotation.map({token in token.description}).joined(separator: " ") + + 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: " ") } From 6eb7d9a172e3cded2c5be3e52c7193c9168def81 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 7 Feb 2017 18:43:38 +0100 Subject: [PATCH 0172/1039] old version with error --- Threaded Binary Tree/README.markdown | 49 +- .../Contents.swift} | 52 +- .../Sources/ThreadedBinaryTree.swift | 459 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + Threaded Binary Tree/ThreadedBinaryTree.swift | 459 ------------------ 6 files changed, 519 insertions(+), 511 deletions(-) rename Threaded Binary Tree/{ThreadedBinaryTreeTests.swift => ThreadedBinaryTree.playground/Contents.swift} (53%) create mode 100644 Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift create mode 100644 Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground create mode 100644 Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata delete mode 100644 Threaded Binary Tree/ThreadedBinaryTree.swift diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index 0c533ad63..fd05113d8 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -158,31 +158,31 @@ outlined above. We use these predecessor/successor attributes to great effect in this new algorithm for both forward and backward traversals: ```swift -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 traverseInOrderForward(_ visit: (T) -> Void) { + var n: ThreadedBinaryTree + n = minimum() + while true { + visit(n.value) + if let successor = n.successor() { + n = successor + } else { + break + } + } } - } -} -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 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 @@ -221,7 +221,7 @@ 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 +knowledge of binary search trees, so make sure you have [read this first](../Binary Search Tree/). > Note: we do allow duplicate nodes in this implementation of a threaded binary @@ -342,11 +342,12 @@ Many of these methods are inherent to binary search trees as well, so you can find [further documentation here](../Binary Search Tree/). -## See also +## 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* diff --git a/Threaded Binary Tree/ThreadedBinaryTreeTests.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift similarity index 53% rename from Threaded Binary Tree/ThreadedBinaryTreeTests.swift rename to Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift index 514c0db63..ff59f81d1 100644 --- a/Threaded Binary Tree/ThreadedBinaryTreeTests.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift @@ -1,35 +1,31 @@ -/* - TESTS - I don't have access to an Apple computer, so I can't make a Playground or any - of that fancy stuff. Here's a simple demonstration of the ThreadedBinaryTree - class. It follows the examples in the README. -*/ +//: 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.") +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 is an INVALID threaded binary tree.") + print("This tree is nil.") } - } else { - print("This tree is nil.") - } } diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift new file mode 100644 index 000000000..4ae03238d --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift @@ -0,0 +1,459 @@ +/* + 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. + */ + 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 case 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 case let next? = node.left { + node = next + } + return node + } + + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> ThreadedBinaryTree { + var node = self + while case 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 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() -> 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 } + } +} diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground b/Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Threaded Binary Tree/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.swift deleted file mode 100644 index 98a23d013..000000000 --- a/Threaded Binary Tree/ThreadedBinaryTree.swift +++ /dev/null @@ -1,459 +0,0 @@ -/* - 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 { - private(set) public var value: T - private(set) public var parent: ThreadedBinaryTree? - private(set) public var left: ThreadedBinaryTree? - private(set) public var right: ThreadedBinaryTree? - private(set) public var leftThread: ThreadedBinaryTree? - private(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) - } - - private 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. - */ - 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 case 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 case let next? = node.left { - node = next - } - return node - } - - /* - Returns the rightmost descendent. O(h) time. - */ - public func maximum() -> ThreadedBinaryTree { - var node = self - while case 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 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() -> 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(@noescape 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(@noescape 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(@noescape visit: T -> Void) { - visit(value) - left?.traversePreOrder(visit) - right?.traversePreOrder(visit) - } - - public func traversePostOrder(@noescape 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(@noescape 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 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 } - } -} From 3fc54e61b6c727323e97cc026021141966aec193 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 7 Feb 2017 18:46:27 +0100 Subject: [PATCH 0173/1039] fix --- .../Sources/ThreadedBinaryTree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift index 4ae03238d..e703d793a 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift @@ -120,7 +120,7 @@ extension ThreadedBinaryTree { Performance: runs in O(h) time, where h is the height of the tree. */ - public func remove(_ value: T) -> ThreadedBinaryTree? { + @discardableResult public func remove(_ value: T) -> ThreadedBinaryTree? { return search(value)?.remove() } From 92363b88477de2595c69924fb51c65679f9d0d85 Mon Sep 17 00:00:00 2001 From: Jaap Date: Tue, 7 Feb 2017 19:01:31 +0100 Subject: [PATCH 0174/1039] fix spaces --- .../Contents.swift | 42 +- .../Sources/ThreadedBinaryTree.swift | 752 +++++++++--------- 2 files changed, 397 insertions(+), 397 deletions(-) diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift index ff59f81d1..e4b527664 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Contents.swift @@ -3,28 +3,28 @@ // 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.") - } + 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("This tree is nil.") } } diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift index e703d793a..a4d308e77 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift @@ -14,446 +14,446 @@ 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) + 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) - } + /* + 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 - } - } + 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. + /* + 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. + 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() - } + 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? + /* + 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 - } - } + 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) + 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 + // 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 - } + 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() + 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() + // 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 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 + // 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 - } + 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 case let n? = node { - if value < n.value { - node = n.left - } else if value > n.value { - node = n.right - } else { - return node - } - } - return nil + /* + 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 case 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 - } - } - */ + /* + // 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 - } + 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 case let next? = node.left { - node = next - } - return node - } + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> ThreadedBinaryTree { + var node = self + while case let next? = node.left { + node = next + } + return node + } - /* - Returns the rightmost descendent. O(h) time. - */ - public func maximum() -> ThreadedBinaryTree { - var node = self - while case let next? = node.right { - node = next - } - return node - } + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> ThreadedBinaryTree { + var node = self + while case 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 case let parent? = node.parent { - node = parent - edges += 1 - } - return edges - } + /* + 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) - } - } + /* + 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 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 - } - } + /* + 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 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 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 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) - } + 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 - } + /* + 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 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 - } + /* + 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 + 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 var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" } - - public func toArray() -> [T] { - return map { $0 } + 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 } + } } From c1c1a55904bf2f02c426ddcda33633443fe82656 Mon Sep 17 00:00:00 2001 From: vincentngo Date: Wed, 8 Feb 2017 00:29:35 -0500 Subject: [PATCH 0175/1039] fix warning --- .../Sources/ThreadedBinaryTree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift index a4d308e77..6f438c0cf 100644 --- a/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift +++ b/Threaded Binary Tree/ThreadedBinaryTree.playground/Sources/ThreadedBinaryTree.swift @@ -176,7 +176,7 @@ extension ThreadedBinaryTree { // 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() + _ = successor.remove() // Connect our left child with the new node. successor.left = left From e149dac200ddd46d110fa94a39c539fde919adf4 Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Sat, 11 Feb 2017 16:31:04 +0100 Subject: [PATCH 0176/1039] Create big enough array for merge results --- Merge Sort/MergeSort.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Merge Sort/MergeSort.swift b/Merge Sort/MergeSort.swift index f77d1cd84..990c432fa 100644 --- a/Merge Sort/MergeSort.swift +++ b/Merge Sort/MergeSort.swift @@ -18,6 +18,9 @@ func merge(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 leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { From bfef1ee575456b66f1cb483750f2f6164dcea7a5 Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Sat, 11 Feb 2017 16:32:34 +0100 Subject: [PATCH 0177/1039] Also update workspace content --- Merge Sort/MergeSort.playground/Contents.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Merge Sort/MergeSort.playground/Contents.swift b/Merge Sort/MergeSort.playground/Contents.swift index 2952fc299..137dd19e2 100644 --- a/Merge Sort/MergeSort.playground/Contents.swift +++ b/Merge Sort/MergeSort.playground/Contents.swift @@ -12,6 +12,9 @@ func merge(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 leftIndex < leftPile.count && rightIndex < rightPile.count { if leftPile[leftIndex] < rightPile[rightIndex] { From 8f57fbb8635df485a125cad192c9685999b71b22 Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Mon, 13 Feb 2017 09:49:30 +0100 Subject: [PATCH 0178/1039] Use string interpolation for the whole description string --- Binary Tree/BinaryTree.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Tree/BinaryTree.swift b/Binary Tree/BinaryTree.swift index ad5fcfd13..61ae696c7 100644 --- a/Binary Tree/BinaryTree.swift +++ b/Binary Tree/BinaryTree.swift @@ -21,7 +21,7 @@ extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): - return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" + return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } From b68b3b9309ecea1d56e8c5bf40779156abfafbe1 Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Mon, 13 Feb 2017 09:50:24 +0100 Subject: [PATCH 0179/1039] Updated playground content --- Binary Tree/BinaryTree.playground/Contents.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Tree/BinaryTree.playground/Contents.swift b/Binary Tree/BinaryTree.playground/Contents.swift index b4d65ec1f..aa084e44d 100644 --- a/Binary Tree/BinaryTree.playground/Contents.swift +++ b/Binary Tree/BinaryTree.playground/Contents.swift @@ -18,7 +18,7 @@ extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): - return "value: \(value), left = [" + left.description + "], right = [" + right.description + "]" + return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } From 0155784b6cb0860d66f877439ebfe0acfa8ff29f Mon Sep 17 00:00:00 2001 From: Yurii Samsoniuk Date: Mon, 13 Feb 2017 09:51:23 +0100 Subject: [PATCH 0180/1039] Updated README content --- Binary Tree/README.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 52089b8e7..896116dda 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -58,8 +58,7 @@ extension BinaryTree: CustomStringConvertible { public var description: String { switch self { case let .node(left, value, right): - return "value: \(value), left = [" + left.description + "], right = [" - + right.description + "]" + return "value: \(value), left = [\(left.description)], right = [\(right.description)]" case .empty: return "" } From cb64ed6034f91f5a300d0f728f08a4c09cd3e8f0 Mon Sep 17 00:00:00 2001 From: abhisood Date: Mon, 13 Feb 2017 03:13:53 -0800 Subject: [PATCH 0181/1039] Trie - Support prefix matching Solves issue #378 --- Trie/Trie/Trie/Trie.swift | 54 ++++++++++++++++++++++++----- Trie/Trie/TrieTests/TrieTests.swift | 16 +++++++++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index 0e11a9c61..cc310b9ee 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -135,7 +135,26 @@ extension Trie { } return 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().characters { + 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. /// @@ -143,14 +162,11 @@ extension Trie { /// - Returns: the node where the search ended, nil if the /// search failed. private func findTerminalNodeOf(word: String) -> Node? { - var currentNode = root - for character in word.lowercased().characters { - guard let childNode = currentNode.children[character] else { - return nil - } - currentNode = childNode + if let lastNode = findLastNodeOf(word: word) { + return lastNode.isTerminating ? lastNode : nil } - return currentNode.isTerminating ? currentNode : nil + return nil + } /// Deletes a word from the trie by starting with the last letter @@ -201,7 +217,7 @@ extension Trie { /// - rootNode: the root node of the subtrie /// - partialWord: the letters collected by traversing to this node /// - Returns: the words in the subtrie - func wordsInSubtrie(rootNode: Node, partialWord: String) -> [String] { + fileprivate func wordsInSubtrie(rootNode: Node, partialWord: String) -> [String] { var subtrieWords = [String]() var previousLetters = partialWord if let value = rootNode.value { @@ -216,4 +232,24 @@ extension Trie { } 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]() + if let lastNode = findLastNodeOf(word: prefix) { + if lastNode.isTerminating { + words.append(prefix) + } + for childNode in lastNode.children.values { + let childWords = wordsInSubtrie(rootNode: childNode, partialWord: prefix) + words += childWords + } + } + return words + } } diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index f8e934f0d..de41663a9 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -168,4 +168,20 @@ class TrieTests: XCTestCase { XCTAssertEqual(trieCopy.count, trie.count) } + + 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, []); + } } From 9c5a98dc5f64b941f38596088fd867f601a97af7 Mon Sep 17 00:00:00 2001 From: abhisood Date: Mon, 13 Feb 2017 03:58:25 -0800 Subject: [PATCH 0182/1039] Handle uppercase prefix --- Trie/Trie/Trie/Trie.swift | 7 ++++--- Trie/Trie/TrieTests/TrieTests.swift | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index cc310b9ee..4321479c3 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -241,12 +241,13 @@ extension Trie { /// - Returns: the words in the subtrie that start with prefix func findWordsWithPrefix(prefix: String) -> [String] { var words = [String]() - if let lastNode = findLastNodeOf(word: prefix) { + let prefixLowerCased = prefix.lowercased() + if let lastNode = findLastNodeOf(word: prefixLowerCased) { if lastNode.isTerminating { - words.append(prefix) + words.append(prefixLowerCased) } for childNode in lastNode.children.values { - let childWords = wordsInSubtrie(rootNode: childNode, partialWord: prefix) + let childWords = wordsInSubtrie(rootNode: childNode, partialWord: prefixLowerCased) words += childWords } } diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index de41663a9..a75c35c62 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -183,5 +183,13 @@ class TrieTests: XCTestCase { 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"]); + } } From ba3975281965852471a40f7a58514fa1d98d1578 Mon Sep 17 00:00:00 2001 From: Adrian Date: Wed, 15 Feb 2017 18:11:12 -0500 Subject: [PATCH 0183/1039] Update CountingSort.swift to Swift 3.0 syntax Updated to Swift 3.0 syntax --- Counting Sort/CountingSort.swift | 66 ++++++++++++++++---------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/Counting Sort/CountingSort.swift b/Counting Sort/CountingSort.swift index d37bb2eff..9a1ffb373 100644 --- a/Counting Sort/CountingSort.swift +++ b/Counting Sort/CountingSort.swift @@ -6,39 +6,41 @@ // Copyright © 2016 Ali Hafizji. All rights reserved. // -enum CountingSortError: ErrorType { - case arrayEmpty +import Foundation + +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.maxElement() ?? 0 - - var countArray = [Int](count: Int(maxElement + 1), repeatedValue: 0) - 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 - var sortedArray = [Int](count: array.count, repeatedValue: 0) - for element in array { - countArray[element] -= 1 - sortedArray[countArray[element]] = element - } - return sortedArray + 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 + var sortedArray = [Int](repeating: 0, count: array.count) + for element in array { + countArray[element] -= 1 + sortedArray[countArray[element]] = element + } + return sortedArray } From 0b93a48f4dd66111fb9033e187cb4176d51d6dc0 Mon Sep 17 00:00:00 2001 From: Timur Galimov Date: Sat, 18 Feb 2017 02:20:13 +0300 Subject: [PATCH 0184/1039] Quadtree --- QuadTree/QuadTree.playground/Contents.swift | 14 + .../Sources/QuadTree.swift | 290 ++++++++++++++++++ .../QuadTree.playground/contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + QuadTree/README.md | 158 ++++++++++ .../Tests/Tests.xcodeproj/project.pbxproj | 274 +++++++++++++++++ .../contents.xcworkspacedata | 7 + QuadTree/Tests/Tests/Info.plist | 22 ++ QuadTree/Tests/Tests/Tests.swift | 85 +++++ 9 files changed, 861 insertions(+) create mode 100644 QuadTree/QuadTree.playground/Contents.swift create mode 100644 QuadTree/QuadTree.playground/Sources/QuadTree.swift create mode 100644 QuadTree/QuadTree.playground/contents.xcplayground create mode 100644 QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 QuadTree/README.md create mode 100644 QuadTree/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 QuadTree/Tests/Tests/Info.plist create mode 100644 QuadTree/Tests/Tests/Tests.swift diff --git a/QuadTree/QuadTree.playground/Contents.swift b/QuadTree/QuadTree.playground/Contents.swift new file mode 100644 index 000000000..41e73147f --- /dev/null +++ b/QuadTree/QuadTree.playground/Contents.swift @@ -0,0 +1,14 @@ + +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)))) diff --git a/QuadTree/QuadTree.playground/Sources/QuadTree.swift b/QuadTree/QuadTree.playground/Sources/QuadTree.swift new file mode 100644 index 000000000..beec4a7b7 --- /dev/null +++ b/QuadTree/QuadTree.playground/Sources/QuadTree.swift @@ -0,0 +1,290 @@ + +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 PointsContainter { + 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: PointsContainter { + + @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: PointsContainter { + + 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 + } +} diff --git a/QuadTree/QuadTree.playground/contents.xcplayground b/QuadTree/QuadTree.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/QuadTree/QuadTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata b/QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/QuadTree/QuadTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/QuadTree/README.md b/QuadTree/README.md new file mode 100644 index 000000000..77ac8b8fa --- /dev/null +++ b/QuadTree/README.md @@ -0,0 +1,158 @@ +# 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 + +Quadrees 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.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 + } + } + 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.containts(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 Atricle](https://robots.thoughtbot.com/how-to-handle-large-amounts-of-data-on-maps)) + +More info on [Wiki](https://en.wikipedia.org/wiki/Quadtree) + +*Written for Swift Algorithm Club by Timur Galimov* + diff --git a/QuadTree/Tests/Tests.xcodeproj/project.pbxproj b/QuadTree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a972bf534 --- /dev/null +++ b/QuadTree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,274 @@ +// !$*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 */; +} diff --git a/QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/QuadTree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/QuadTree/Tests/Tests/Info.plist b/QuadTree/Tests/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/QuadTree/Tests/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/QuadTree/Tests/Tests/Tests.swift b/QuadTree/Tests/Tests/Tests.swift new file mode 100644 index 000000000..b7bcda4e6 --- /dev/null +++ b/QuadTree/Tests/Tests/Tests.swift @@ -0,0 +1,85 @@ +// +// 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)]) + } +} From c1952ec2f66b4ce98d82d3e948e43af4be77809d Mon Sep 17 00:00:00 2001 From: Jaap Wijnen Date: Sat, 18 Feb 2017 02:18:53 +0100 Subject: [PATCH 0185/1039] finalize migration tests (#381) * finalize migration tests * fix * fixes * test fixes * fix bounded priority queue --- .travis.yml | 23 ++++--- .../Sources/BoundedPriorityQueue.swift | 2 +- .../BoundedPriorityQueue.swift | 30 ++++----- .../Tests/Tests.xcodeproj/project.pbxproj | 42 +++++++++++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Counting Sort/CountingSort.swift | 66 +++++++++---------- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Depth-First Search/Tests/Graph.swift | 38 +++++------ .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- Graph/Graph.xcodeproj/project.pbxproj | 5 +- Graph/GraphTests/GraphTests.swift | 24 +++---- Heap/Tests/HeapTests.swift | 12 ++-- Heap/Tests/Tests.xcodeproj/project.pbxproj | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 2 +- Quicksort/Quicksort.swift | 20 +++--- Quicksort/Tests/QuicksortTests.swift | 6 +- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- .../Tests/MaximumTests.swift | 2 +- .../Tests/MinimumMaximumPairsTests.swift | 4 +- .../Tests/MinimumTests.swift | 2 +- Select Minimum Maximum/Tests/TestHelper.swift | 2 +- .../Tests/Tests.xcodeproj/project.pbxproj | 10 ++- .../xcshareddata/xcschemes/Tests.xcscheme | 2 +- 26 files changed, 202 insertions(+), 130 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2b2bafd14..b6ff6190c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,30 +15,29 @@ script: - xcodebuild test -project ./Boyer-Moore/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Binary\ Search\ Tree/Solution\ 1/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bloom\ Filter/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Bounded\ Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Breadth-First\ Search/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Bucket\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./B-Tree/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Comb\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests -# - xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Counting\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Depth-First\ Search/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Graph/Graph.xcodeproj -scheme GraphTests +- xcodebuild test -project ./Heap/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Heap\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Insertion\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./K-Means/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Linked\ List/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Longest\ Common\ Subsequence/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Minimum\ Spanning\ Tree\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Priority\ Queue/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Queue/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Quicksort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Radix\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Rootish\ Array\ Stack/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Run-Length\ Encoding/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Select\ Minimum\ Maximum/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Selection\ Sort/Tests/Tests.xcodeproj -scheme Tests -# - xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests +- xcodebuild test -project ./Shell\ Sort/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Shortest\ Path\ \(Unweighted\)/Tests/Tests.xcodeproj -scheme Tests - xcodebuild test -project ./Single-Source\ Shortest\ Paths\ \(Weighted\)/SSSP.xcodeproj -scheme SSSPTests - xcodebuild test -project ./Stack/Tests/Tests.xcodeproj -scheme Tests diff --git a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift index fc399811d..b94863afc 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.playground/Sources/BoundedPriorityQueue.swift @@ -9,7 +9,7 @@ public class LinkedListNode { } public class BoundedPriorityQueue { - private typealias Node = LinkedListNode + fileprivate typealias Node = LinkedListNode private(set) public var count = 0 fileprivate var head: Node? diff --git a/Bounded Priority Queue/BoundedPriorityQueue.swift b/Bounded Priority Queue/BoundedPriorityQueue.swift index fbd8d5450..d882a7698 100644 --- a/Bounded Priority Queue/BoundedPriorityQueue.swift +++ b/Bounded Priority Queue/BoundedPriorityQueue.swift @@ -1,4 +1,4 @@ -public class LinkedListNode { +open class LinkedListNode { var value: T var next: LinkedListNode? var previous: LinkedListNode? @@ -8,27 +8,27 @@ public class LinkedListNode { } } -public class BoundedPriorityQueue { - private typealias Node = LinkedListNode +open class BoundedPriorityQueue { + fileprivate typealias Node = LinkedListNode - private(set) public var count = 0 - private var head: Node? - private var tail: Node? - private var maxElements: Int + 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 } - public var isEmpty: Bool { + open var isEmpty: Bool { return count == 0 } - public func peek() -> T? { + open func peek() -> T? { return head?.value } - public func enqueue(value: T) { + 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. @@ -44,7 +44,7 @@ public class BoundedPriorityQueue { } } - private func insert(value: T, after: Node?) -> Node? { + 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, @@ -78,18 +78,18 @@ public class BoundedPriorityQueue { /* 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? { + fileprivate func findInsertionPoint(_ value: T) -> Node? { var node = head var prev: Node? = nil - while let current = node where value < current.value { + while let current = node, value < current.value { prev = node node = current.next } return prev } - private func removeLeastImportantElement() { + fileprivate func removeLeastImportantElement() { if let last = tail { tail = last.previous tail?.next = nil @@ -101,7 +101,7 @@ public class BoundedPriorityQueue { // this is much slower on large lists. } - public func dequeue() -> T? { + open func dequeue() -> T? { if let first = head { count -= 1 if count == 0 { diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj index 6fd5c0b46..842c51695 100644 --- a/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -82,10 +82,11 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; TargetAttributes = { B80004B21C83E342001FE2D7 = { CreatedOnToolsVersion = 7.2.1; + LastSwiftMigration = 0820; }; }; }; @@ -132,12 +133,49 @@ 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; }; @@ -188,6 +226,7 @@ SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -230,6 +269,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 0416248f1..8bb763edd 100644 --- a/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Bounded Priority Queue/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ [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 - var sortedArray = [Int](repeating: 0, count: array.count) - for element in array { - countArray[element] -= 1 - sortedArray[countArray[element]] = element - } - return sortedArray +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 + var sortedArray = [Int](repeating: 0, count: array.count) + for element in array { + countArray[element] -= 1 + sortedArray[countArray[element]] = element + } + return sortedArray } diff --git a/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj b/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj index 6801bb587..5cbb0d4aa 100644 --- a/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Counting Sort/Tests/Tests.xcodeproj/project.pbxproj @@ -83,11 +83,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -145,8 +146,10 @@ 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 = "-"; @@ -189,8 +192,10 @@ 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 = "-"; @@ -209,6 +214,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -220,6 +226,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -231,6 +238,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Counting Sort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Bool { // MARK: - Node -public class Node: CustomStringConvertible, Equatable { - public var neighbors: [Edge] +open class Node: CustomStringConvertible, Equatable { + open var neighbors: [Edge] - public private(set) var label: String - public var distance: Int? - public var visited: Bool + open fileprivate(set) var label: String + open var distance: Int? + open var visited: Bool public init(label: String) { self.label = label @@ -27,19 +27,19 @@ public class Node: CustomStringConvertible, Equatable { visited = false } - public var description: String { + open var description: String { if let distance = distance { return "Node(label: \(label), distance: \(distance))" } return "Node(label: \(label), distance: infinity)" } - public var hasDistance: Bool { + open var hasDistance: Bool { return distance != nil } - public func remove(edge: Edge) { - neighbors.removeAtIndex(neighbors.indexOf { $0 === edge }!) + open func remove(_ edge: Edge) { + neighbors.remove(at: neighbors.index { $0 === edge }!) } } @@ -49,25 +49,25 @@ public func == (lhs: Node, rhs: Node) -> Bool { // MARK: - Graph -public class Graph: CustomStringConvertible, Equatable { - public private(set) var nodes: [Node] +open class Graph: CustomStringConvertible, Equatable { + open fileprivate(set) var nodes: [Node] public init() { self.nodes = [] } - public func addNode(label: String) -> Node { + open func addNode(_ label: String) -> Node { let node = Node(label: label) nodes.append(node) return node } - public func addEdge(source: Node, neighbor: Node) { + open func addEdge(_ source: Node, neighbor: Node) { let edge = Edge(neighbor: neighbor) source.neighbors.append(edge) } - public var description: String { + open var description: String { var description = "" for node in nodes { @@ -78,15 +78,15 @@ public class Graph: CustomStringConvertible, Equatable { return description } - public func findNodeWithLabel(label: String) -> Node { + open func findNodeWithLabel(_ label: String) -> Node { return nodes.filter { $0.label == label }.first! } - public func duplicate() -> Graph { + open func duplicate() -> Graph { let duplicated = Graph() for node in nodes { - duplicated.addNode(node.label) + _ = duplicated.addNode(node.label) } for node in nodes { diff --git a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj index 9e2872f88..dbc44ecd4 100644 --- a/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj +++ b/Depth-First Search/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -149,8 +150,10 @@ 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 = "-"; @@ -193,8 +196,10 @@ 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 = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -226,6 +232,7 @@ PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -238,6 +245,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index e5bd10d97..4462aede0 100644 --- a/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Depth-First Search/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ .Type) { + func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) @@ -71,7 +71,7 @@ class GraphTests: XCTestCase { XCTAssertEqual(edgesFromA.first?.to, b) } - func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(graphType: AbstractGraph.Type) { + func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) @@ -89,7 +89,7 @@ class GraphTests: XCTestCase { XCTAssertEqual(edgesFromB.first?.to, a) } - func testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(graphType: AbstractGraph.Type) { + func testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let a = graph.createVertex(1) @@ -99,7 +99,7 @@ class GraphTests: XCTestCase { XCTAssertEqual(graph.edgesFrom(b).count, 0) } - func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(graphType: AbstractGraph.Type) { + func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(_ graphType: AbstractGraph.Type) { let graph = graphType.init() let verticesCount = 100 var vertices: [Vertex] = [] @@ -125,34 +125,34 @@ class GraphTests: XCTestCase { } func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedMatrixGraph() { - testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyMatrixGraph) + testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedMatrixGraph() { - testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyMatrixGraph) + testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsNoInNoEdgeMatrixGraph() { - testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyMatrixGraph) + testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedMatrixGraph() { - testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyMatrixGraph) + testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyMatrixGraph.self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedListGraph() { - testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyListGraph) + testEdgesFromReturnsCorrectEdgeInSingleEdgeDirecedGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedListGraph() { - testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyListGraph) + testEdgesFromReturnsCorrectEdgeInSingleEdgeUndirectedGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsNoInNoEdgeListGraph() { - testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyListGraph) + testEdgesFromReturnsNoEdgesInNoEdgeGraphWithType(AdjacencyListGraph.self) } func testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedListGraph() { - testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyListGraph) + testEdgesFromReturnsCorrectEdgesInBiggerGraphInDirectedGraphWithType(AdjacencyListGraph.self) } } diff --git a/Heap/Tests/HeapTests.swift b/Heap/Tests/HeapTests.swift index c5b479f14..0e6c504f3 100644 --- a/Heap/Tests/HeapTests.swift +++ b/Heap/Tests/HeapTests.swift @@ -197,27 +197,27 @@ class HeapTests: XCTestCase { XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 60, 65]) //test index out of bounds - let v = h.removeAt(index: 10) + let v = h.removeAt(10) XCTAssertEqual(v, nil) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 60, 65]) - let v1 = h.removeAt(index: 5) + let v1 = h.removeAt(5) XCTAssertEqual(v1, 60) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 65]) - let v2 = h.removeAt(index: 4) + let v2 = h.removeAt(4) XCTAssertEqual(v2, 20) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 65, 70, 10, 50]) - let v3 = h.removeAt(index: 4) + let v3 = h.removeAt(4) XCTAssertEqual(v3, 50) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 65, 70, 10]) - let v4 = h.removeAt(index: 0) + let v4 = h.removeAt(0) XCTAssertEqual(v4, 100) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [70, 65, 10]) @@ -270,7 +270,7 @@ class HeapTests: XCTestCase { let m = (n + 1)/2 for k in 1...m { let i = Int(arc4random_uniform(UInt32(n - k + 1))) - let v = h.removeAt(index: i)! + let v = h.removeAt(i)! let j = a.index(of: v)! a.remove(at: j) diff --git a/Heap/Tests/Tests.xcodeproj/project.pbxproj b/Heap/Tests/Tests.xcodeproj/project.pbxproj index 9319e2089..22112fa60 100644 --- a/Heap/Tests/Tests.xcodeproj/project.pbxproj +++ b/Heap/Tests/Tests.xcodeproj/project.pbxproj @@ -88,7 +88,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0800; + LastSwiftMigration = 0820; }; }; }; diff --git a/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj b/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj index 77423c57a..0f7d84be9 100644 --- a/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj +++ b/Priority Queue/Tests/Tests.xcodeproj/project.pbxproj @@ -91,7 +91,7 @@ TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0800; + LastSwiftMigration = 0820; }; }; }; diff --git a/Quicksort/Quicksort.swift b/Quicksort/Quicksort.swift index 6448dd815..39fa27b66 100644 --- a/Quicksort/Quicksort.swift +++ b/Quicksort/Quicksort.swift @@ -3,7 +3,7 @@ import Foundation /* Easy to understand but not very efficient. */ -func quicksort(a: [T]) -> [T] { +func quicksort(_ a: [T]) -> [T] { guard a.count > 1 else { return a } let pivot = a[a.count/2] @@ -29,7 +29,7 @@ func quicksort(a: [T]) -> [T] { if the pivot value occurs more than once, its duplicates will be found in the left partition. */ -func partitionLomuto(inout a: [T], low: Int, high: Int) -> Int { +func partitionLomuto(_ a: inout [T], low: Int, high: Int) -> Int { // We always use the highest item as the pivot. let pivot = a[high] @@ -56,7 +56,7 @@ func partitionLomuto(inout a: [T], low: Int, high: Int) -> Int { /* Recursive, in-place version that uses Lomuto's partioning scheme. */ -func quicksortLomuto(inout a: [T], low: Int, high: Int) { +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) @@ -80,7 +80,7 @@ func quicksortLomuto(inout a: [T], low: Int, high: Int) { Hoare scheme is more efficient than Lomuto's partition scheme; it performs fewer swaps. */ -func partitionHoare(inout a: [T], low: Int, high: Int) -> Int { +func partitionHoare(_ a: inout [T], low: Int, high: Int) -> Int { let pivot = a[low] var i = low - 1 var j = high + 1 @@ -101,7 +101,7 @@ func partitionHoare(inout a: [T], low: Int, high: Int) -> Int { 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(inout a: [T], low: Int, high: Int) { +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) @@ -112,7 +112,7 @@ func quicksortHoare(inout a: [T], low: Int, high: Int) { // MARK: - Randomized sort /* Returns a random integer in the range min...max, inclusive. */ -public func random(min min: Int, max: Int) -> Int { +public func random(min: Int, max: Int) -> Int { assert(min < max) return min + Int(arc4random_uniform(UInt32(max - min + 1))) } @@ -121,7 +121,7 @@ public func random(min min: Int, max: Int) -> Int { Uses a random pivot index. On average, this results in a well-balanced split of the input array. */ -func quicksortRandom(inout a: [T], low: Int, high: Int) { +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) @@ -142,7 +142,7 @@ func quicksortRandom(inout a: [T], low: Int, high: Int) { 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(inout a: [T], _ i: Int, _ j: Int) { +public func swap(_ a: inout [T], _ i: Int, _ j: Int) { if i != j { swap(&a[i], &a[j]) } @@ -165,7 +165,7 @@ public func swap(inout a: [T], _ i: Int, _ j: Int) { Time complexity is O(n), space complexity is O(1). */ -func partitionDutchFlag(inout a: [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { +func partitionDutchFlag(_ a: inout [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) { let pivot = a[pivotIndex] var smaller = low @@ -195,7 +195,7 @@ func partitionDutchFlag(inout a: [T], low: Int, high: Int, pivotI /* Uses Dutch national flag partitioning and a random pivot index. */ -func quicksortDutchFlag(inout a: [T], low: Int, high: Int) { +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) diff --git a/Quicksort/Tests/QuicksortTests.swift b/Quicksort/Tests/QuicksortTests.swift index 00135b31f..c8d9a62e6 100644 --- a/Quicksort/Tests/QuicksortTests.swift +++ b/Quicksort/Tests/QuicksortTests.swift @@ -5,12 +5,12 @@ class QuicksortTests: XCTestCase { checkSortAlgorithm(quicksort) } - private typealias QuicksortFunction = (inout [Int], low: Int, high: Int) -> Void + fileprivate typealias QuicksortFunction = (inout [Int], _ low: Int, _ high: Int) -> Void - private func checkQuicksort(function: QuicksortFunction) { + fileprivate func checkQuicksort(_ function: QuicksortFunction) { checkSortAlgorithm { (a: [Int]) -> [Int] in var b = a - function(&b, low: 0, high: b.count - 1) + function(&b, 0, b.count - 1) return b } } diff --git a/Quicksort/Tests/Tests.xcodeproj/project.pbxproj b/Quicksort/Tests/Tests.xcodeproj/project.pbxproj index 8aecb59f8..2d8ee18ff 100644 --- a/Quicksort/Tests/Tests.xcodeproj/project.pbxproj +++ b/Quicksort/Tests/Tests.xcodeproj/project.pbxproj @@ -86,11 +86,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -149,8 +150,10 @@ 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 = "-"; @@ -193,8 +196,10 @@ 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 = "-"; @@ -213,6 +218,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -224,6 +230,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -235,6 +242,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Quicksort/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ [UInt32] { +func createRandomList(_ numberOfElements: Int) -> [UInt32] { return (1...numberOfElements).map {_ in arc4random()} } diff --git a/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj b/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj index e2857d2b7..fb70d6970 100644 --- a/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj +++ b/Select Minimum Maximum/Tests/Tests.xcodeproj/project.pbxproj @@ -98,11 +98,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Swift Algorithm Club"; TargetAttributes = { 7B2BBC7F1C779D720067B71D = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0820; }; }; }; @@ -165,8 +166,10 @@ 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 = "-"; @@ -209,8 +212,10 @@ 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 = "-"; @@ -229,6 +234,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; @@ -240,6 +246,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -251,6 +258,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = swift.algorithm.club.Tests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme index 8ef8d8581..dfcf6de42 100644 --- a/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme +++ b/Select Minimum Maximum/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -1,6 +1,6 @@ Date: Sun, 19 Feb 2017 14:58:50 +0100 Subject: [PATCH 0186/1039] Convex Hull algorithm --- .../Convex Hull.xcodeproj/project.pbxproj | 297 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + Convex Hull/Convex Hull/AppDelegate.swift | 57 ++++ .../AppIcon.appiconset/Contents.json | 93 ++++++ .../Base.lproj/LaunchScreen.storyboard | 27 ++ Convex Hull/Convex Hull/Info.plist | 47 +++ Convex Hull/Convex Hull/View.swift | 177 +++++++++++ Convex Hull/README.md | 41 +++ 8 files changed, 746 insertions(+) create mode 100644 Convex Hull/Convex Hull.xcodeproj/project.pbxproj create mode 100644 Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Convex Hull/Convex Hull/AppDelegate.swift create mode 100644 Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard create mode 100644 Convex Hull/Convex Hull/Info.plist create mode 100644 Convex Hull/Convex Hull/View.swift create mode 100644 Convex Hull/README.md diff --git a/Convex Hull/Convex Hull.xcodeproj/project.pbxproj b/Convex Hull/Convex Hull.xcodeproj/project.pbxproj new file mode 100644 index 000000000..2f236b013 --- /dev/null +++ b/Convex Hull/Convex Hull.xcodeproj/project.pbxproj @@ -0,0 +1,297 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 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 PBXFileReference section */ + 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 */ + 8E6D68B31E59989400161780 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8E6D68AD1E59989400161780 = { + isa = PBXGroup; + children = ( + 8E6D68B81E59989400161780 /* Convex Hull */, + 8E6D68B71E59989400161780 /* Products */, + ); + sourceTree = ""; + }; + 8E6D68B71E59989400161780 /* Products */ = { + isa = PBXGroup; + children = ( + 8E6D68B61E59989400161780 /* Convex Hull.app */, + ); + 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 */ + 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 = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = Workmoose; + TargetAttributes = { + 8E6D68B51E59989400161780 = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = 7C4LVS3ZVC; + 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 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 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 */ + 8E6D68B21E59989400161780 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8E6D68BA1E59989400161780 /* AppDelegate.swift in Sources */, + 8E6D68CC1E599CF100161780 /* View.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 8E6D68C21E59989400161780 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 8E6D68C31E59989400161780 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 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_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[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_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[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 = 7C4LVS3ZVC; + 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 = 3.0; + }; + name = Debug; + }; + 8E6D68CA1E59989400161780 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 7C4LVS3ZVC; + 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 = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 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; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8E6D68AE1E59989400161780 /* Project object */; +} diff --git a/Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..dfcd4bc52 --- /dev/null +++ b/Convex Hull/Convex Hull.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Convex Hull/Convex Hull/AppDelegate.swift b/Convex Hull/Convex Hull/AppDelegate.swift new file mode 100644 index 000000000..1901083a8 --- /dev/null +++ b/Convex Hull/Convex Hull/AppDelegate.swift @@ -0,0 +1,57 @@ +// +// AppDelegate.swift +// Convex Hull +// +// Created by Jaap Wijnen on 19/02/2017. +// Copyright © 2017 Workmoose. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> 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:. + } + + +} + diff --git a/Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json b/Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..1d060ed28 --- /dev/null +++ b/Convex Hull/Convex Hull/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,93 @@ +{ + "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard b/Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000..fdf3f97d1 --- /dev/null +++ b/Convex Hull/Convex Hull/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Convex Hull/Convex Hull/Info.plist b/Convex Hull/Convex Hull/Info.plist new file mode 100644 index 000000000..390c5347e --- /dev/null +++ b/Convex Hull/Convex Hull/Info.plist @@ -0,0 +1,47 @@ + + + + + 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 + + + diff --git a/Convex Hull/Convex Hull/View.swift b/Convex Hull/Convex Hull/View.swift new file mode 100644 index 000000000..2d7157e6f --- /dev/null +++ b/Convex Hull/Convex Hull/View.swift @@ -0,0 +1,177 @@ +// +// 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) + + generatePoints() + quickHull(points: points) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func generatePoints() { + 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 + + // calculate parameters of general line equation y = a * x + b + let a = (p1.y - p2.y) / (p1.x - p2.x) + let b = p1.y - a * p1.x + + // calculate normal line's growth factor + let a1 = -1 / a + + var maxDist: CGFloat = -1 + var maxPoint: CGPoint = pts.first! + + for p in pts { // for every point check the distance from our line + let b1 = p.y - a1 * p.x // calculate offset to line equation for given point p + let x = -(b - b1)/(a - a1) // calculate x where the two lines intersect + let y = a * x + b // calculate y value of this intersect point + + let dist = pow(x - p.x, 2) + pow(y - p.y, 2) // calculate distance squared between intersection point and point p + 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) + } + + 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) + } + } +} diff --git a/Convex Hull/README.md b/Convex Hull/README.md new file mode 100644 index 000000000..b73f66176 --- /dev/null +++ b/Convex Hull/README.md @@ -0,0 +1,41 @@ +# Convex Hull + +There are multiple Convex Hull algorithms. This particular implementation uses the Quickhull algorithm. + +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 dimention. This implementation however covers points on a plane. It essentially calculates the lines between points which together contain all points. + +## 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 pick the two points A and B with the smallest(A) and the largest(B) x coordinate. These of course have to be part of the hull. Imagine a line from point A to point B. All points to the right of this line are grouped in an array S1. Imagine now a line from point B to point A. (this is of course the same line as before just with opposite direction) Again all points to the right of this line are grouped in an array, S2 this time. +We now define the following recursive function: + +`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.* From 94c9b5f2b0306e9924c01486889b69934f34575a Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 19 Feb 2017 16:46:31 +0100 Subject: [PATCH 0187/1039] initial implementation fro Splay Trees Test in progress Debug in progress Playground in progress Documentation not started --- .../SplayTree.playground/Contents.swift | 7 + .../Sources/SplayTree.swift | 509 ++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + Splay Tree/SplayTree.swift | 552 ++++++++++++++++++ Splay Tree/Tests/Info.plist | 22 + Splay Tree/Tests/SplayTreeTests.swift | 19 + Splay Tree/Tests/Tests-Bridging-Header.h | 4 + .../Tests/Tests.xcodeproj/project.pbxproj | 279 +++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Tests.xcscheme | 101 ++++ 11 files changed, 1511 insertions(+) create mode 100644 Splay Tree/SplayTree.playground/Contents.swift create mode 100644 Splay Tree/SplayTree.playground/Sources/SplayTree.swift create mode 100644 Splay Tree/SplayTree.playground/contents.xcplayground create mode 100644 Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Splay Tree/SplayTree.swift create mode 100644 Splay Tree/Tests/Info.plist create mode 100644 Splay Tree/Tests/SplayTreeTests.swift create mode 100644 Splay Tree/Tests/Tests-Bridging-Header.h create mode 100644 Splay Tree/Tests/Tests.xcodeproj/project.pbxproj create mode 100644 Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme diff --git a/Splay Tree/SplayTree.playground/Contents.swift b/Splay Tree/SplayTree.playground/Contents.swift new file mode 100644 index 000000000..951ad4c5c --- /dev/null +++ b/Splay Tree/SplayTree.playground/Contents.swift @@ -0,0 +1,7 @@ +//: Playground - Splay Tree Implementation + + +let splayTree = SplayTree(array: [1]) +splayTree.insert(value: 2) +splayTree.insert(value: 10) +splayTree.insert(value: 6) diff --git a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift new file mode 100644 index 000000000..f0c45e831 --- /dev/null +++ b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift @@ -0,0 +1,509 @@ +/* + * Splay Tree + * + * Based on Binary Search Tree Implementation written by Nicolas Ameghino and Matthijs Hollemans for Swift Algorithms Club + * https://github.com/raywenderlich/swift-algorithm-club/blob/master/Binary%20Search%20Tree + * And extended for the specifics of a Splay Tree by Barbara Martina Rodeker + * + */ + +/** + Represent the 3 possible operations (combinations of rotations) that + could be performed during the Splay phase in Splay Trees + + - zigZag Left child of a right child OR right child of a left child + - zigZig Left child of a left child OR right child of a right child + - zig Only 1 parent and that parent is the root + + */ +public enum SplayOperation { + case zigZag + case zigZig + case zig + + + /** + Splay the given node up to the root of the tree + + - Parameters: + - node SplayTree node to move up to the root + */ + public static func splay(node: SplayTree) { + + while (node.parent != nil) { + operation(forNode: node).apply(onNode: node) + } + } + + /** + Compares the node and its parent and determine + if the rotations should be performed in a zigZag, zigZig or zig case. + + - Parmeters: + - forNode SplayTree node to be checked + - Returns + - Operation Case zigZag - zigZig - zig + */ + private static func operation(forNode node: SplayTree) -> SplayOperation { + + if let parent = node.parent, let grandParent = parent.parent { + if (node.isLeftChild && grandParent.isRightChild) || (node.isRightChild && grandParent.isLeftChild) { + return .zigZag + } + return .zigZig + } + return .zig + } + + /** + Applies the rotation associated to the case + Modifying the splay tree and briging the received node further to the top of the tree + + - Parameters: + - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent + */ + private func apply(onNode node: SplayTree) { + switch self { + case .zigZag: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node, parent: node.parent!) + rotate(child: node, parent: node.parent!) + + case .zigZig: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node.parent!, parent: node.parent!.parent!) + rotate(child: node, parent: node.parent!) + + case .zig: + assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") + rotate(child: node, parent: node.parent!) + } + } + + /** + Performs a single rotation from a node to its parent + re-arranging the children properly + */ + private func rotate(child: SplayTree, parent: SplayTree) { + + assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") + + var grandchildToMode: SplayTree? + if child.isLeftChild { + + grandchildToMode = child.right + child.right = parent + parent.left = grandchildToMode + + } else { + + grandchildToMode = child.left + child.left = parent + parent.right = grandchildToMode + } + + let grandParent = parent.parent + parent.parent = child + child.parent = grandParent + } +} + +public class SplayTree { + + fileprivate(set) public var value: T + fileprivate(set) public var parent: SplayTree? + fileprivate(set) public var left: SplayTree? + fileprivate(set) public var right: SplayTree? + + public init(value: T) { + self.value = value + } + + public convenience init(array: [T]) { + precondition(array.count > 0) + self.init(value: array.first!) + for v in array.dropFirst() { + insert(value: v) + } + } + + public var isRoot: Bool { + return parent == nil + } + + public var isLeaf: Bool { + return left == nil && right == nil + } + + public var isLeftChild: Bool { + return parent?.left === self + } + + public var isRightChild: Bool { + return parent?.right === self + } + + public var hasLeftChild: Bool { + return left != nil + } + + public var hasRightChild: Bool { + return right != nil + } + + public var hasAnyChild: Bool { + return hasLeftChild || hasRightChild + } + + public var hasBothChildren: Bool { + return hasLeftChild && hasRightChild + } + + /* How many nodes are in this subtree. Performance: O(n). */ + public var count: Int { + return (left?.count ?? 0) + 1 + (right?.count ?? 0) + } +} + +// MARK: - Adding items + +extension SplayTree { + + /* + Inserts a new element into the tree. You should only insert elements + at the root, to make to sure this remains a valid binary tree! + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func insert(value: T) { + if value < self.value { + if let left = left { + left.insert(value: value) + } else { + + left = SplayTree(value: value) + left?.parent = self + + if let left = left { + SplayOperation.splay(node: left) + self.parent = nil + self.value = left.value + self.left = left.left + self.right = left.right + } + } + } else { + + if let right = right { + right.insert(value: value) + } else { + + right = SplayTree(value: value) + right?.parent = self + + if let right = right { + SplayOperation.splay(node: right) + self.parent = nil + self.value = right.value + self.left = right.left + self.right = right.right + } + } + } + } +} + +// MARK: - Deleting items + +extension SplayTree { + /* + Deletes a node from the tree. + Returns the node that has replaced this removed one (or nil if this was a + leaf node). That is primarily useful for when you delete the root node, in + which case the tree gets a new root. + Performance: runs in O(h) time, where h is the height of the tree. + */ + @discardableResult public func remove() -> SplayTree? { + let replacement: SplayTree? + + if let left = left { + if let right = right { + replacement = removeNodeWithTwoChildren(left, right) + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + } else { + // This node has no children. We just disconnect it from its parent. + replacement = nil + } + + // Save the parent to splay before reconnecting + var parentToSplay: SplayTree? + if let replacement = replacement { + parentToSplay = replacement.parent + } else { + parentToSplay = self.parent + } + + reconnectParentTo(node: replacement) + + // performs the splay operation + if let parentToSplay = parentToSplay { + SplayOperation.splay(node: parentToSplay) + } + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil + + return replacement + } + + private func removeNodeWithTwoChildren(_ left: SplayTree, _ right: SplayTree) -> SplayTree { + // This node has two children. It must be replaced by the smallest + // child that is larger than this node's value, which is the leftmost + // descendent of the right child. + let successor = right.minimum() + + // If this in-order successor has a right child of its own (it cannot + // have a left child by definition), then that must take its place. + successor.remove() + + // Connect our left child with the new node. + successor.left = left + left.parent = successor + + // Connect our right child with the new node. If the right child does + // not have any left children of its own, then the in-order successor + // *is* the right child. + if right !== successor { + successor.right = right + right.parent = successor + } else { + successor.right = nil + } + + // And finally, connect the successor node to our parent. + return successor + } + + private func reconnectParentTo(node: SplayTree?) { + if let parent = parent { + if isLeftChild { + parent.left = node + } else { + parent.right = node + } + } + node?.parent = parent + } +} + +// MARK: - Searching + +extension SplayTree { + + /* + Finds the "highest" node with the specified value. + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func search(value: T) -> SplayTree? { + var node: SplayTree? = self + while case let n? = node { + if value < n.value { + node = n.left + } else if value > n.value { + node = n.right + } else { + + if let node = node { + SplayOperation.splay(node: node) + } + + return node + } + } + + if let node = node { + SplayOperation.splay(node: node) + } + + return nil + } + + public func contains(value: T) -> Bool { + return search(value: value) != nil + } + + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> SplayTree { + var node = self + while case let next? = node.left { + node = next + } + + SplayOperation.splay(node: node) + + return node + } + + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> SplayTree { + var node = self + while case let next? = node.right { + node = next + } + + SplayOperation.splay(node: node) + + return node + } + + /* + Calculates the depth of this node, i.e. the distance to the root. + Takes O(h) time. + */ + public func depth() -> Int { + var node = self + var edges = 0 + while case let parent? = node.parent { + node = parent + edges += 1 + } + return edges + } + + /* + Calculates the height of this node, i.e. the distance to the lowest leaf. + Since this looks at all children of this node, performance is O(n). + */ + public func height() -> Int { + if isLeaf { + return 0 + } else { + return 1 + max(left?.height() ?? 0, right?.height() ?? 0) + } + } + + /* + Finds the node whose value precedes our value in sorted order. + */ + public func predecessor() -> SplayTree? { + if let left = left { + return left.maximum() + } else { + var node = self + while case let parent? = node.parent { + if parent.value < value { return parent } + node = parent + } + return nil + } + } + + /* + Finds the node whose value succeeds our value in sorted order. + */ + public func successor() -> SplayTree? { + if let right = right { + return right.minimum() + } else { + var node = self + while case let parent? = node.parent { + if parent.value > value { return parent } + node = parent + } + return nil + } + } +} + +// MARK: - Traversal +extension SplayTree { + + public func traverseInOrder(process: (T) -> Void) { + left?.traverseInOrder(process: process) + process(value) + right?.traverseInOrder(process: process) + } + + public func traversePreOrder(process: (T) -> Void) { + process(value) + left?.traversePreOrder(process: process) + right?.traversePreOrder(process: process) + } + + public func traversePostOrder(process: (T) -> Void) { + left?.traversePostOrder(process: process) + right?.traversePostOrder(process: process) + process(value) + } + + /* + Performs an in-order traversal and collects the results in an array. + */ + public func map(formula: (T) -> T) -> [T] { + var a = [T]() + if let left = left { a += left.map(formula: formula) } + a.append(formula(value)) + if let right = right { a += right.map(formula: formula) } + return a + } +} + +/* + Is this binary tree a valid binary search tree? + */ +extension SplayTree { + + public func isBST(minValue: T, maxValue: T) -> Bool { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } +} + +// MARK: - Debugging + +extension SplayTree: CustomStringConvertible { + public var description: String { + var s = "" + if let left = left { + s += "(\(left.description)) <- " + } + s += "\(value)" + if let right = right { + s += " -> (\(right.description))" + } + return s + } +} + +extension SplayTree: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" + } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } + return s + } + + public func toArray() -> [T] { + return map { $0 } + } +} diff --git a/Splay Tree/SplayTree.playground/contents.xcplayground b/Splay Tree/SplayTree.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Splay Tree/SplayTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Splay Tree/SplayTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift new file mode 100644 index 000000000..727ff8f50 --- /dev/null +++ b/Splay Tree/SplayTree.swift @@ -0,0 +1,552 @@ +/* + * Splay Tree + * + * Based on Binary Search Tree Implementation written by Nicolas Ameghino and Matthijs Hollemans for Swift Algorithms Club + * https://github.com/raywenderlich/swift-algorithm-club/blob/master/Binary%20Search%20Tree + * And extended for the specifics of a Splay Tree by Barbara Martina Rodeker + * + */ + +/** + Represent the 3 possible operations (combinations of rotations) that + could be performed during the Splay phase in Splay Trees + + - zigZag Left child of a right child OR right child of a left child + - zigZig Left child of a left child OR right child of a right child + - zig Only 1 parent and that parent is the root + + */ +public enum SplayOperation { + case zigZag + case zigZig + case zig + + + /** + Splay the given node up to the root of the tree + + - Parameters: + - node SplayTree node to move up to the root + */ + public static func splay(node: SplayTree) { + + while (node.parent != nil) { + operation(forNode: node).apply(onNode: node) + } + } + + /** + Compares the node and its parent and determine + if the rotations should be performed in a zigZag, zigZig or zig case. + + - Parmeters: + - forNode SplayTree node to be checked + - Returns + - Operation Case zigZag - zigZig - zig + */ + private static func operation(forNode node: SplayTree) -> SplayOperation { + + if let parent = node.parent, let _ = parent.parent { + if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { + return .zigZag + } + return .zigZig + } + return .zig + } + + /** + Applies the rotation associated to the case + Modifying the splay tree and briging the received node further to the top of the tree + + - Parameters: + - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent + */ + private func apply(onNode node: SplayTree) { + switch self { + case .zigZag: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node, parent: node.parent!) + rotate(child: node, parent: node.parent!) + + case .zigZig: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node.parent!, parent: node.parent!.parent!) + rotate(child: node, parent: node.parent!) + + case .zig: + assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") + rotate(child: node, parent: node.parent!) + } + } + + /** + Performs a single rotation from a node to its parent + re-arranging the children properly + */ + private func rotate(child: SplayTree, parent: SplayTree) { + + assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") + + var grandchildToMode: SplayTree? + if child.isLeftChild { + + grandchildToMode = child.right + child.right = parent + parent.left = grandchildToMode + + } else { + + grandchildToMode = child.left + child.left = parent + parent.right = grandchildToMode + } + + let grandParent = parent.parent + parent.parent = child + child.parent = grandParent + } +} + +public class Node { + + fileprivate(set) public var value: T + fileprivate(set) public var parent: SplayTree? + fileprivate(set) public var left: SplayTree? + fileprivate(set) public var right: SplayTree? + + init(value: T){ + self.value = value + } +} + +public class SplayTree { + + + fileprivate(set) public var root: Node? + public var value: T? { + get { + return root?.value + } + set { + if let value = newValue { + root?.value = value + } + } + } + + fileprivate(set) public var parent: SplayTree? { + get { + return root?.parent + } + set { + root?.parent = newValue + } + } + + fileprivate(set) public var left: SplayTree? { + get { + return root?.left + } + set { + root?.left = newValue + } + } + fileprivate(set) public var right: SplayTree? { + get { + return root?.right + } + set { + root?.right = newValue + } + } + + //MARK: - Initializer + + public init(value: T) { + self.root = Node(value:value) + } + + public var isRoot: Bool { + return parent == nil + } + + public var isLeaf: Bool { + return left == nil && right == nil + } + + public var isLeftChild: Bool { + return parent?.left === self + } + + public var isRightChild: Bool { + return parent?.right === self + } + + public var hasLeftChild: Bool { + return left != nil + } + + public var hasRightChild: Bool { + return right != nil + } + + public var hasAnyChild: Bool { + return hasLeftChild || hasRightChild + } + + public var hasBothChildren: Bool { + return hasLeftChild && hasRightChild + } + + /* How many nodes are in this subtree. Performance: O(n). */ + public var count: Int { + return (left?.count ?? 0) + 1 + (right?.count ?? 0) + } +} + +// MARK: - Adding items + +extension SplayTree { + + /* + Inserts a new element into the tree. You should only insert elements + at the root, to make to sure this remains a valid binary tree! + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func insert(value: T) -> SplayTree? { + if let selfValue = self.value { + if value < selfValue { + if let left = left { + return left.insert(value: value) + } else { + + left = SplayTree(value: value) + left?.parent = self + + if let left = left { + SplayOperation.splay(node: left) + return left + } + } + } else { + + if let right = right { + return right.insert(value: value) + } else { + + right = SplayTree(value: value) + right?.parent = self + + if let right = right { + SplayOperation.splay(node: right) + return right + } + } + } + } else { + self.root = Node(value: value) + return self + } + return nil + } +} + +// MARK: - Deleting items + +extension SplayTree { + /* + Deletes a node from the tree. + Returns the node that has replaced this removed one (or nil if this was a + leaf node). That is primarily useful for when you delete the root node, in + which case the tree gets a new root. + Performance: runs in O(h) time, where h is the height of the tree. + */ + @discardableResult public func remove() -> SplayTree? { + let replacement: SplayTree? + + if let left = left { + if let right = right { + replacement = removeNodeWithTwoChildren(left, right) + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + } else { + // This node has no children. We just disconnect it from its parent. + replacement = nil + } + + // Save the parent to splay before reconnecting + var parentToSplay: SplayTree? + if let replacement = replacement { + parentToSplay = replacement.parent + } else { + parentToSplay = self.parent + } + + reconnectParentTo(node: replacement) + + // performs the splay operation + if let parentToSplay = parentToSplay { + SplayOperation.splay(node: parentToSplay) + } + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil + + return replacement + } + + private func removeNodeWithTwoChildren(_ left: SplayTree, _ right: SplayTree) -> SplayTree { + // This node has two children. It must be replaced by the smallest + // child that is larger than this node's value, which is the leftmost + // descendent of the right child. + let successor = right.minimum() + + // If this in-order successor has a right child of its own (it cannot + // have a left child by definition), then that must take its place. + successor.remove() + + // Connect our left child with the new node. + successor.left = left + left.parent = successor + + // Connect our right child with the new node. If the right child does + // not have any left children of its own, then the in-order successor + // *is* the right child. + if right !== successor { + successor.right = right + right.parent = successor + } else { + successor.right = nil + } + + // And finally, connect the successor node to our parent. + return successor + } + + private func reconnectParentTo(node: SplayTree?) { + if let parent = parent { + if isLeftChild { + parent.left = node + } else { + parent.right = node + } + } + node?.parent = parent + } +} + +// MARK: - Searching + +extension SplayTree { + + /* + Finds the "highest" node with the specified value. + Performance: runs in O(h) time, where h is the height of the tree. + */ + public func search(value: T) -> SplayTree? { + var node: SplayTree? = self + while case let n? = node, n.value != nil { + if value < n.value! { + node = n.left + } else if value > n.value! { + node = n.right + } else { + + if let node = node { + SplayOperation.splay(node: node) + } + + return node + } + } + + if let node = node { + SplayOperation.splay(node: node) + } + + return nil + } + + public func contains(value: T) -> Bool { + return search(value: value) != nil + } + + /* + Returns the leftmost descendent. O(h) time. + */ + public func minimum() -> SplayTree { + var node = self + while case let next? = node.left { + node = next + } + + SplayOperation.splay(node: node) + + return node + } + + /* + Returns the rightmost descendent. O(h) time. + */ + public func maximum() -> SplayTree { + var node = self + while case let next? = node.right { + node = next + } + + SplayOperation.splay(node: node) + + return node + } + + /* + Calculates the depth of this node, i.e. the distance to the root. + Takes O(h) time. + */ + public func depth() -> Int { + var node = self + var edges = 0 + while case let parent? = node.parent { + node = parent + edges += 1 + } + return edges + } + + /* + Calculates the height of this node, i.e. the distance to the lowest leaf. + Since this looks at all children of this node, performance is O(n). + */ + public func height() -> Int { + if isLeaf { + return 0 + } else { + return 1 + max(left?.height() ?? 0, right?.height() ?? 0) + } + } + + /* + Finds the node whose value precedes our value in sorted order. + */ + public func predecessor() -> SplayTree? { + if let left = left { + return left.maximum() + } else { + var node = self + while case let parent? = node.parent, parent.value != nil, value != nil { + if parent.value! < value! { return parent } + node = parent + } + return nil + } + } + + /* + Finds the node whose value succeeds our value in sorted order. + */ + public func successor() -> SplayTree? { + if let right = right { + return right.minimum() + } else { + var node = self + while case let parent? = node.parent, parent.value != nil , value != nil { + if parent.value! > value! { return parent } + node = parent + } + return nil + } + } +} + +// MARK: - Traversal +extension SplayTree { + + public func traverseInOrder(process: (T) -> Void) { + left?.traverseInOrder(process: process) + process(value!) + right?.traverseInOrder(process: process) + } + + public func traversePreOrder(process: (T) -> Void) { + process(value!) + left?.traversePreOrder(process: process) + right?.traversePreOrder(process: process) + } + + public func traversePostOrder(process: (T) -> Void) { + left?.traversePostOrder(process: process) + right?.traversePostOrder(process: process) + process(value!) + } + + /* + Performs an in-order traversal and collects the results in an array. + */ + public func map(formula: (T) -> T) -> [T] { + var a = [T]() + if let left = left { a += left.map(formula: formula) } + a.append(formula(value!)) + if let right = right { a += right.map(formula: formula) } + return a + } +} + +/* + Is this binary tree a valid binary search tree? + */ +extension SplayTree { + + public func isBST(minValue: T, maxValue: T) -> Bool { + if let value = value { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } + return false + } +} + +// MARK: - Debugging + +extension SplayTree: CustomStringConvertible { + public var description: String { + var s = "" + if let left = left { + s += "(\(left.description)) <- " + } + s += "\(value)" + if let right = right { + s += " -> (\(right.description))" + } + return s + } +} + +extension SplayTree: CustomDebugStringConvertible { + public var debugDescription: String { + var s = "value: \(value)" + if let parent = parent { + s += ", parent: \(parent.value)" + } + if let left = left { + s += ", left = [" + left.debugDescription + "]" + } + if let right = right { + s += ", right = [" + right.debugDescription + "]" + } + return s + } + + public func toArray() -> [T] { + return map { $0 } + } +} diff --git a/Splay Tree/Tests/Info.plist b/Splay Tree/Tests/Info.plist new file mode 100644 index 000000000..6c6c23c43 --- /dev/null +++ b/Splay Tree/Tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift new file mode 100644 index 000000000..35bdedb71 --- /dev/null +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -0,0 +1,19 @@ +import XCTest + +class SplayTreeTests: XCTestCase { + var tree: SplayTree! + + override func setUp() { + super.setUp() + tree = SplayTree(value: 1) + } + + func testElements() { + print(tree) + let tree1 = tree.insert(value: 10) + print(tree1!) + let tree2 = tree1!.insert(value: 2) + print(tree2!) + } + +} diff --git a/Splay Tree/Tests/Tests-Bridging-Header.h b/Splay Tree/Tests/Tests-Bridging-Header.h new file mode 100644 index 000000000..1b2cb5d6d --- /dev/null +++ b/Splay Tree/Tests/Tests-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/Splay Tree/Tests/Tests.xcodeproj/project.pbxproj b/Splay Tree/Tests/Tests.xcodeproj/project.pbxproj new file mode 100644 index 000000000..8a900fcd3 --- /dev/null +++ b/Splay Tree/Tests/Tests.xcodeproj/project.pbxproj @@ -0,0 +1,279 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 763F9E771E59DAEF00AC5031 /* SplayTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F9E761E59DAEF00AC5031 /* SplayTree.swift */; }; + 763F9E791E59DAFE00AC5031 /* SplayTreeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 056E92A21E25D04D00B30F52 /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 056E92A61E25D04D00B30F52 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 763F9E761E59DAEF00AC5031 /* SplayTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SplayTree.swift; path = ../SplayTree.swift; sourceTree = ""; }; + 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SplayTreeTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 056E929F1E25D04D00B30F52 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 056E92851E25D03300B30F52 = { + isa = PBXGroup; + children = ( + 056E92A31E25D04D00B30F52 /* Tests */, + 056E928F1E25D03300B30F52 /* Products */, + ); + sourceTree = ""; + }; + 056E928F1E25D03300B30F52 /* Products */ = { + isa = PBXGroup; + children = ( + 056E92A21E25D04D00B30F52 /* Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 056E92A31E25D04D00B30F52 /* Tests */ = { + isa = PBXGroup; + children = ( + 056E92A61E25D04D00B30F52 /* Info.plist */, + 763F9E781E59DAFE00AC5031 /* SplayTreeTests.swift */, + 763F9E761E59DAEF00AC5031 /* SplayTree.swift */, + ); + name = Tests; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 056E92A11E25D04D00B30F52 /* Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */; + buildPhases = ( + 056E929E1E25D04D00B30F52 /* Sources */, + 056E929F1E25D04D00B30F52 /* Frameworks */, + 056E92A01E25D04D00B30F52 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Tests; + productName = Tests; + productReference = 056E92A21E25D04D00B30F52 /* Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 056E92861E25D03300B30F52 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = "Swift Algorithm Club"; + TargetAttributes = { + 056E92A11E25D04D00B30F52 = { + CreatedOnToolsVersion = 8.2; + LastSwiftMigration = 0820; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 056E92851E25D03300B30F52; + productRefGroup = 056E928F1E25D03300B30F52 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 056E92A11E25D04D00B30F52 /* Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 056E92A01E25D04D00B30F52 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 056E929E1E25D04D00B30F52 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 763F9E771E59DAEF00AC5031 /* SplayTree.swift in Sources */, + 763F9E791E59DAFE00AC5031 /* SplayTreeTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 056E92991E25D03300B30F52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 056E929A1E25D03300B30F52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 056E92A81E25D04D00B30F52 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Tests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 056E92A91E25D04D00B30F52 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = Swift.Algorithm.Club.Tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Tests-Bridging-Header.h"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 056E92891E25D03300B30F52 /* Build configuration list for PBXProject "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E92991E25D03300B30F52 /* Debug */, + 056E929A1E25D03300B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 056E92A71E25D04D00B30F52 /* Build configuration list for PBXNativeTarget "Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 056E92A81E25D04D00B30F52 /* Debug */, + 056E92A91E25D04D00B30F52 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 056E92861E25D03300B30F52 /* Project object */; +} diff --git a/Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..6c0ea8493 --- /dev/null +++ b/Splay Tree/Tests/Tests.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 000000000..b3f6d696a --- /dev/null +++ b/Splay Tree/Tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 217cad58d2501c10d040fd72cbcaea96d366fc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Mon, 20 Feb 2017 10:25:31 +0800 Subject: [PATCH 0188/1039] Update README.markdown add swift version --- Shell Sort/README.markdown | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Shell Sort/README.markdown b/Shell Sort/README.markdown index 6cb682035..a2ac843c7 100644 --- a/Shell Sort/README.markdown +++ b/Shell Sort/README.markdown @@ -111,6 +111,28 @@ This is an old Commodore 64 BASIC version of shell sort that Matthijs used a lon 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] + +var n = arr.count / 2 + +repeat +{ + for index in 0.. arr[index + n]{ + + swap(&arr[index], &arr[index + n]) + } + } + + n = n / 2 + +}while n > 0 +``` + ## See also [Shellsort on Wikipedia](https://en.wikipedia.org/wiki/Shellsort) From 31b89968878506cadb76ae2a650edbe651d5f58c Mon Sep 17 00:00:00 2001 From: Timur Galimov Date: Tue, 21 Feb 2017 22:04:11 +0300 Subject: [PATCH 0189/1039] fix typo in PointsContainer protocol --- QuadTree/QuadTree.playground/Sources/QuadTree.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/QuadTree/QuadTree.playground/Sources/QuadTree.swift b/QuadTree/QuadTree.playground/Sources/QuadTree.swift index beec4a7b7..65c55d49e 100644 --- a/QuadTree/QuadTree.playground/Sources/QuadTree.swift +++ b/QuadTree/QuadTree.playground/Sources/QuadTree.swift @@ -104,7 +104,7 @@ extension Rect: CustomStringConvertible { } } -protocol PointsContainter { +protocol PointsContainer { func add(point: Point) -> Bool func points(inRect rect: Rect) -> [Point] } @@ -185,7 +185,7 @@ class QuadTreeNode { } } -extension QuadTreeNode: PointsContainter { +extension QuadTreeNode: PointsContainer { @discardableResult func add(point: Point) -> Bool { @@ -265,7 +265,7 @@ extension QuadTreeNode: CustomStringConvertible { } } -public class QuadTree: PointsContainter { +public class QuadTree: PointsContainer { let root: QuadTreeNode From 2e5a5748fdbf92bb1f7c191af7a1c7a0e8b64de6 Mon Sep 17 00:00:00 2001 From: Timur Galimov Date: Tue, 21 Feb 2017 22:28:50 +0300 Subject: [PATCH 0190/1039] Add quadtree diagram --- QuadTree/Images/quadtree.png | Bin 0 -> 110070 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 QuadTree/Images/quadtree.png diff --git a/QuadTree/Images/quadtree.png b/QuadTree/Images/quadtree.png new file mode 100644 index 0000000000000000000000000000000000000000..53af6fb082a3e6172090bd167e4178a4b8e99e36 GIT binary patch literal 110070 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 z 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 T^->+Urc~-GI?7qcEdBl;I+hf* literal 0 HcmV?d00001 From 42032b4bec864013c7e51fff3443ec602b295741 Mon Sep 17 00:00:00 2001 From: Timur Galimov Date: Wed, 22 Feb 2017 01:04:55 +0300 Subject: [PATCH 0191/1039] Update README.md --- QuadTree/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/QuadTree/README.md b/QuadTree/README.md index 77ac8b8fa..3fc682547 100644 --- a/QuadTree/README.md +++ b/QuadTree/README.md @@ -2,6 +2,8 @@ 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. From 71bfd719ce6024944e7c17847952d77094be6cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Sun, 26 Feb 2017 12:41:50 +0800 Subject: [PATCH 0192/1039] add file ShellSortExample.swift update code --- Shell Sort/ShellSortExample.swift | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Shell Sort/ShellSortExample.swift diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift new file mode 100644 index 000000000..eea80e539 --- /dev/null +++ b/Shell Sort/ShellSortExample.swift @@ -0,0 +1,33 @@ +// +// 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 index in 0.. arr[index + sublistCount]{ + swap(&arr[index], &arr[index + sublistCount]) + } + + guard sublistCount == 1 && index > 0 else { continue } + + if arr[index - 1] > arr[index]{ + swap(&arr[index - 1], &arr[index]) + } + } + sublistCount = sublistCount / 2 + } +} From 8202cf1668a535b61fbac12962ebc5a639631ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Mon, 27 Feb 2017 10:52:37 +0800 Subject: [PATCH 0193/1039] Update ShellSortExample.swift Fix my code mistakes --- Shell Sort/ShellSortExample.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index eea80e539..68cd9ead1 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -14,18 +14,18 @@ public func shellSort(_ list : inout [Int]) while sublistCount > 0 { - for index in 0.. arr[index + sublistCount]{ - swap(&arr[index], &arr[index + sublistCount]) + if list[index] > list[index + sublistCount]{ + swap(&list[index], &list[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } - if arr[index - 1] > arr[index]{ - swap(&arr[index - 1], &arr[index]) + if list[index - 1] > list[index]{ + swap(&list[index - 1], &list[index]) } } sublistCount = sublistCount / 2 From 69cb42eef48c610f2f42e6c5d51781fdb3482e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Wed, 1 Mar 2017 12:13:54 +0800 Subject: [PATCH 0194/1039] Update ShellSortExample.swift let code to suit style guide --- Shell Sort/ShellSortExample.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index 68cd9ead1..efa035da3 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -8,23 +8,23 @@ import Foundation -public func shellSort(_ list : inout [Int]) -{ - var sublistCount = list.count / 2 +public func shellSort(_ list: inout [Int]) { - while sublistCount > 0 - { - for index in 0.. 0 { + + for index in 0.. list[index + sublistCount]{ + if list[index] > list[index + sublistCount] { swap(&list[index], &list[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } - if list[index - 1] > list[index]{ + if list[index - 1] > list[index] { swap(&list[index - 1], &list[index]) } } From a69e3d84fcdc3bb8ab1d9e788f8826e5e9ab4254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Thu, 2 Mar 2017 10:47:14 +0800 Subject: [PATCH 0195/1039] Update README.markdown update sample code --- Shell Sort/README.markdown | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/Shell Sort/README.markdown b/Shell Sort/README.markdown index a2ac843c7..9c4bdf076 100644 --- a/Shell Sort/README.markdown +++ b/Shell Sort/README.markdown @@ -116,21 +116,31 @@ Here is an implementation of Shell Sort in Swift: ``` var arr = [64, 20, 50, 33, 72, 10, 23, -1, 4, 5] -var n = arr.count / 2 - -repeat -{ - for index in 0.. arr[index + n]{ +public func shellSort(_ list: inout [Int]) { + + var sublistCount = list.count / 2 + + while sublistCount > 0 { - swap(&arr[index], &arr[index + n]) + for index in 0.. list[index + sublistCount] { + swap(&list[index], &list[index + sublistCount]) + } + + guard sublistCount == 1 && index > 0 else { continue } + + if list[index - 1] > list[index] { + swap(&list[index - 1], &list[index]) + } } + sublistCount = sublistCount / 2 } - - n = n / 2 - -}while n > 0 +} + +shellSort(&arr) ``` ## See also From b4e4ef1c8095405c21e69284807095f548fea537 Mon Sep 17 00:00:00 2001 From: John Pham Date: Thu, 2 Mar 2017 17:10:59 +0700 Subject: [PATCH 0196/1039] Update dim func follow syntax change of swift 3 --- Array2D/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Array2D/README.markdown b/Array2D/README.markdown index 51e77435e..b98a09593 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -36,7 +36,7 @@ var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9) but that's just ugly. To be fair, you can hide the ugliness in a helper function: ```swift -func dim(count: Int, _ value: T) -> [T] { +func dim(_ count: Int, _ value: T) -> [T] { return [T](repeating: value, count: count) } ``` From 0837113e9e8a0fa69d2e8deb8302bb0a72c5d5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Thu, 2 Mar 2017 19:19:18 +0800 Subject: [PATCH 0197/1039] Add files via upload upload a radix sort implement,faster than original code --- Radix Sort/RadixSortExample.swift | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Radix Sort/RadixSortExample.swift diff --git a/Radix Sort/RadixSortExample.swift b/Radix Sort/RadixSortExample.swift new file mode 100644 index 000000000..7d9461c5c --- /dev/null +++ b/Radix Sort/RadixSortExample.swift @@ -0,0 +1,29 @@ +// +// 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.. Date: Fri, 3 Mar 2017 11:13:22 +0800 Subject: [PATCH 0198/1039] Update LinearSearch.swift more swift --- Linear Search/LinearSearch.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Linear Search/LinearSearch.swift b/Linear Search/LinearSearch.swift index 882795180..c5374d0a4 100644 --- a/Linear Search/LinearSearch.swift +++ b/Linear Search/LinearSearch.swift @@ -4,3 +4,7 @@ func linearSearch(_ array: [T], _ object: T) -> Int? { } return nil } + +func linearSearch1(_ array: [T], _ object: T) -> Array.Index? { + return array.index { $0 == object } +} From 12b0bdbb8488f7746edac33623b2f86c57564a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Fri, 3 Mar 2017 11:34:04 +0800 Subject: [PATCH 0199/1039] Update README.markdown update some details --- Select Minimum Maximum/README.markdown | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index 09ca97039..fa0f8fed8 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -68,6 +68,13 @@ array.minElement() // This will return 3 array.maxElement() // This will return 9 ``` +``` +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. From cc973dcb62d310f1af0d08d408c782a57e3523cb Mon Sep 17 00:00:00 2001 From: barbara Date: Fri, 3 Mar 2017 21:01:11 +0100 Subject: [PATCH 0200/1039] Fixes for connecting nodes during rotations --- Splay Tree/SplayTree.swift | 53 ++++++++++++++++++--------- Splay Tree/Tests/SplayTreeTests.swift | 41 +++++++++++++-------- 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index 727ff8f50..2e008ba50 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -44,7 +44,7 @@ public enum SplayOperation { - Returns - Operation Case zigZag - zigZig - zig */ - private static func operation(forNode node: SplayTree) -> SplayOperation { + public static func operation(forNode node: SplayTree) -> SplayOperation { if let parent = node.parent, let _ = parent.parent { if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { @@ -62,7 +62,7 @@ public enum SplayOperation { - Parameters: - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ - private func apply(onNode node: SplayTree) { + public func apply(onNode node: SplayTree) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") @@ -84,7 +84,7 @@ public enum SplayOperation { Performs a single rotation from a node to its parent re-arranging the children properly */ - private func rotate(child: SplayTree, parent: SplayTree) { + public func rotate(child: SplayTree, parent: SplayTree) { assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") @@ -95,16 +95,22 @@ public enum SplayOperation { child.right = parent parent.left = grandchildToMode + + } else { grandchildToMode = child.left child.left = parent parent.right = grandchildToMode - } + } + let grandParent = parent.parent parent.parent = child child.parent = grandParent + + grandParent?.left = child + } } @@ -210,9 +216,15 @@ public class SplayTree { extension SplayTree { /* - Inserts a new element into the tree. You should only insert elements - at the root, to make to sure this remains a valid binary tree! - Performance: runs in O(h) time, where h is the height of the tree. + Inserts a new element into the tree. + Returns the new Tree generated by the insertion. + + - Parameters: + - value T value to be inserted. Will be splayed to the root position + + - Returns + - SplayTree Containing the inserted value in the root node + */ public func insert(value: T) -> SplayTree? { if let selfValue = self.value { @@ -255,14 +267,17 @@ extension SplayTree { // MARK: - Deleting items extension SplayTree { + /* - Deletes a node from the tree. - Returns the node that has replaced this removed one (or nil if this was a - leaf node). That is primarily useful for when you delete the root node, in - which case the tree gets a new root. - Performance: runs in O(h) time, where h is the height of the tree. + Deletes the given node from the tree. + Return the new tree generated by the removal. + The removed node (not necessarily the one containing the value), will be splayed to the root. + + - Returns: + - SplayTree Resulting from the deletion and the splaying of the removed node + */ - @discardableResult public func remove() -> SplayTree? { + public func remove() -> SplayTree? { let replacement: SplayTree? if let left = left { @@ -521,11 +536,13 @@ extension SplayTree: CustomStringConvertible { public var description: String { var s = "" if let left = left { - s += "(\(left.description)) <- " + s += "left: (\(left.description)) <- " + } + if let v = value { + s += "\(v)" } - s += "\(value)" if let right = right { - s += " -> (\(right.description))" + s += " -> (right: \(right.description))" } return s } @@ -534,8 +551,8 @@ extension SplayTree: CustomStringConvertible { extension SplayTree: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" + if let parent = parent, let v = parent.value { + s += ", parent: \(v)" } if let left = left { s += ", left = [" + left.debugDescription + "]" diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift index 35bdedb71..998c6d3c4 100644 --- a/Splay Tree/Tests/SplayTreeTests.swift +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -1,19 +1,30 @@ import XCTest class SplayTreeTests: XCTestCase { - var tree: SplayTree! - - override func setUp() { - super.setUp() - tree = SplayTree(value: 1) - } - - func testElements() { - print(tree) - let tree1 = tree.insert(value: 10) - print(tree1!) - let tree2 = tree1!.insert(value: 2) - print(tree2!) - } - + + var tree: SplayTree! + var tree1: SplayTree! + + override func setUp() { + super.setUp() + tree = SplayTree(value: 1) + tree1 = tree.insert(value: 10)?.insert(value: 20)?.insert(value: 3)//?.insert(value: 6)?.insert(value: 100)?.insert(value: 44) + } + + func testInsertion() { + let tree1 = tree.insert(value: 10) + assert(tree1?.root?.value == 10) + + let tree2 = tree1!.insert(value: 2) + assert(tree2?.root?.value == 2) + } + + + func testDeleteExisting() { + print(tree1) + let tree2 = tree1.search(value: 6)?.remove() + + } + + } From 72740a17e7bd9b74716e32f1ef9ef4a92534b302 Mon Sep 17 00:00:00 2001 From: barbara Date: Sat, 4 Mar 2017 09:20:25 +0100 Subject: [PATCH 0201/1039] Test for search function + fixes for rotations --- Splay Tree/SplayTree.swift | 17 +++++++++-------- Splay Tree/Tests/SplayTreeTests.swift | 7 ++++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index 2e008ba50..bbe8491e2 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -94,7 +94,7 @@ public enum SplayOperation { grandchildToMode = child.right child.right = parent parent.left = grandchildToMode - + grandchildToMode?.parent = parent } else { @@ -102,6 +102,7 @@ public enum SplayOperation { grandchildToMode = child.left child.left = parent parent.right = grandchildToMode + grandchildToMode?.parent = parent } @@ -368,23 +369,23 @@ extension SplayTree { */ public func search(value: T) -> SplayTree? { var node: SplayTree? = self + var nodeParent: SplayTree? = self while case let n? = node, n.value != nil { if value < n.value! { + if n.left != nil { nodeParent = n.left } node = n.left } else if value > n.value! { node = n.right - } else { - - if let node = node { - SplayOperation.splay(node: node) - } - - return node + if n.right != nil { nodeParent = n.right } } } if let node = node { SplayOperation.splay(node: node) + return node + } else if let nodeParent = nodeParent { + SplayOperation.splay(node: nodeParent) + return nodeParent } return nil diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift index 998c6d3c4..042344193 100644 --- a/Splay Tree/Tests/SplayTreeTests.swift +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -8,7 +8,7 @@ class SplayTreeTests: XCTestCase { override func setUp() { super.setUp() tree = SplayTree(value: 1) - tree1 = tree.insert(value: 10)?.insert(value: 20)?.insert(value: 3)//?.insert(value: 6)?.insert(value: 100)?.insert(value: 44) + tree1 = tree.insert(value: 10)?.insert(value: 20)?.insert(value: 3)?.insert(value: 6)?.insert(value: 100)?.insert(value: 44) } func testInsertion() { @@ -20,9 +20,10 @@ class SplayTreeTests: XCTestCase { } - func testDeleteExisting() { + func testSearchNonExisting() { print(tree1) - let tree2 = tree1.search(value: 6)?.remove() + let tree2 = tree1.search(value: 5) + assert(tree2?.root?.value == 10) } From 84e75b73e246e76fe8a22c97ef49c9d5277ea35b Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:23:31 +0100 Subject: [PATCH 0202/1039] Completing implementation + debug fixes of Splay Tree --- Splay Tree/SplayTree.swift | 321 +++++++++++++++++++++---------------- 1 file changed, 186 insertions(+), 135 deletions(-) diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index bbe8491e2..f50af7349 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -28,7 +28,7 @@ public enum SplayOperation { - Parameters: - node SplayTree node to move up to the root */ - public static func splay(node: SplayTree) { + public static func splay(node: Node) { while (node.parent != nil) { operation(forNode: node).apply(onNode: node) @@ -44,7 +44,7 @@ public enum SplayOperation { - Returns - Operation Case zigZag - zigZig - zig */ - public static func operation(forNode node: SplayTree) -> SplayOperation { + public static func operation(forNode node: Node) -> SplayOperation { if let parent = node.parent, let _ = parent.parent { if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { @@ -62,7 +62,7 @@ public enum SplayOperation { - Parameters: - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ - public func apply(onNode node: SplayTree) { + public func apply(onNode node: Node) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") @@ -84,95 +84,65 @@ public enum SplayOperation { Performs a single rotation from a node to its parent re-arranging the children properly */ - public func rotate(child: SplayTree, parent: SplayTree) { + public func rotate(child: Node, parent: Node) { assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") - var grandchildToMode: SplayTree? + var grandchildToMode: Node? + if child.isLeftChild { grandchildToMode = child.right - child.right = parent parent.left = grandchildToMode grandchildToMode?.parent = parent + + let grandParent = parent.parent + child.parent = grandParent + + if parent.isLeftChild { + grandParent?.left = child + } else { + grandParent?.right = child + } + + child.right = parent + parent.parent = child } else { grandchildToMode = child.left - child.left = parent parent.right = grandchildToMode grandchildToMode?.parent = parent + let grandParent = parent.parent + child.parent = grandParent + + if parent.isLeftChild { + grandParent?.left = child + } else { + grandParent?.right = child + } + + child.left = parent + parent.parent = child + } - let grandParent = parent.parent - parent.parent = child - child.parent = grandParent - - grandParent?.left = child } } public class Node { - fileprivate(set) public var value: T - fileprivate(set) public var parent: SplayTree? - fileprivate(set) public var left: SplayTree? - fileprivate(set) public var right: SplayTree? + fileprivate(set) public var value: T? + fileprivate(set) public var parent: Node? + fileprivate(set) public var left: Node? + fileprivate(set) public var right: Node? - init(value: T){ + init(value: T) { self.value = value } -} - -public class SplayTree { - - - fileprivate(set) public var root: Node? - public var value: T? { - get { - return root?.value - } - set { - if let value = newValue { - root?.value = value - } - } - } - - fileprivate(set) public var parent: SplayTree? { - get { - return root?.parent - } - set { - root?.parent = newValue - } - } - - fileprivate(set) public var left: SplayTree? { - get { - return root?.left - } - set { - root?.left = newValue - } - } - fileprivate(set) public var right: SplayTree? { - get { - return root?.right - } - set { - root?.right = newValue - } - } - - //MARK: - Initializer - - public init(value: T) { - self.root = Node(value:value) - } public var isRoot: Bool { return parent == nil @@ -212,29 +182,66 @@ public class SplayTree { } } +public class SplayTree { + + internal var root: Node? + + var value: T? { + return root?.value + } + + //MARK: - Initializer + + public init(value: T) { + self.root = Node(value:value) + } + + public func insert(value: T) { + root = root?.insert(value: value) + } + + public func remove(value: T) { + root = root?.remove(value: value) + } + + public func search(value: T) -> Node? { + root = root?.search(value: value) + return root + } + + public func minimum() -> Node? { + root = root?.minimum(splayed: true) + return root + } + + public func maximum() -> Node? { + root = root?.maximum(splayed: true) + return root + } + +} + // MARK: - Adding items -extension SplayTree { +extension Node { /* - Inserts a new element into the tree. - Returns the new Tree generated by the insertion. + Inserts a new element into the node tree. - Parameters: - value T value to be inserted. Will be splayed to the root position - - Returns - - SplayTree Containing the inserted value in the root node - + - Returns: + - Node inserted */ - public func insert(value: T) -> SplayTree? { + public func insert(value: T) -> Node { if let selfValue = self.value { if value < selfValue { if let left = left { return left.insert(value: value) } else { - left = SplayTree(value: value) + left = Node(value: value) left?.parent = self if let left = left { @@ -248,7 +255,7 @@ extension SplayTree { return right.insert(value: value) } else { - right = SplayTree(value: value) + right = Node(value: value) right?.parent = self if let right = right { @@ -257,78 +264,104 @@ extension SplayTree { } } } - } else { - self.root = Node(value: value) - return self } - return nil + return self } } // MARK: - Deleting items -extension SplayTree { +extension Node { /* - Deletes the given node from the tree. + Deletes the given node from the nodes tree. Return the new tree generated by the removal. The removed node (not necessarily the one containing the value), will be splayed to the root. + - Parameters: + - value To be removed + - Returns: - - SplayTree Resulting from the deletion and the splaying of the removed node + - Node Resulting from the deletion and the splaying of the removed node */ - public func remove() -> SplayTree? { - let replacement: SplayTree? + public func remove(value: T) -> Node? { + let replacement: Node? - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) + if let v = self.value, v == value { + + var parentToSplay: Node? + if let left = left { + if let right = right { + + replacement = removeNodeWithTwoChildren(left, right) + + if let replacement = replacement, + let replacementParent = replacement.parent, + replacementParent.value != self.value { + + parentToSplay = replacement.parent + + } else { + parentToSplay = self.parent + } + + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + parentToSplay = parent + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + parentToSplay = parent } else { - // This node only has a left child. The left child replaces the node. - replacement = left + // This node has no children. We just disconnect it from its parent. + replacement = nil + parentToSplay = parent } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - } + + reconnectParentTo(node: replacement) + + // performs the splay operation + if let parentToSplay = parentToSplay { + SplayOperation.splay(node: parentToSplay) + } + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil - // Save the parent to splay before reconnecting - var parentToSplay: SplayTree? - if let replacement = replacement { - parentToSplay = replacement.parent + return parentToSplay + + } else if let v = self.value, value < v { + if left != nil { + return left!.remove(value: value) + } else { + let node = self + SplayOperation.splay(node: node) + return node + + } } else { - parentToSplay = self.parent - } - - reconnectParentTo(node: replacement) - - // performs the splay operation - if let parentToSplay = parentToSplay { - SplayOperation.splay(node: parentToSplay) + if right != nil { + return right?.remove(value: value) + } else { + let node = self + SplayOperation.splay(node: node) + return node + + } } - - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - - return replacement } - private func removeNodeWithTwoChildren(_ left: SplayTree, _ right: SplayTree) -> SplayTree { + private func removeNodeWithTwoChildren(_ left: Node, _ right: Node) -> Node { // This node has two children. It must be replaced by the smallest // child that is larger than this node's value, which is the leftmost // descendent of the right child. let successor = right.minimum() - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() - // Connect our left child with the new node. successor.left = left left.parent = successor @@ -347,7 +380,7 @@ extension SplayTree { return successor } - private func reconnectParentTo(node: SplayTree?) { + private func reconnectParentTo(node: Node?) { if let parent = parent { if isLeftChild { parent.left = node @@ -361,15 +394,15 @@ extension SplayTree { // MARK: - Searching -extension SplayTree { +extension Node { /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ - public func search(value: T) -> SplayTree? { - var node: SplayTree? = self - var nodeParent: SplayTree? = self + public func search(value: T) -> Node? { + var node: Node? = self + var nodeParent: Node? = self while case let n? = node, n.value != nil { if value < n.value! { if n.left != nil { nodeParent = n.left } @@ -377,6 +410,8 @@ extension SplayTree { } else if value > n.value! { node = n.right if n.right != nil { nodeParent = n.right } + } else { + break } } @@ -398,27 +433,31 @@ extension SplayTree { /* Returns the leftmost descendent. O(h) time. */ - public func minimum() -> SplayTree { + public func minimum(splayed: Bool = false) -> Node { var node = self while case let next? = node.left { node = next } - SplayOperation.splay(node: node) - + if splayed == true { + SplayOperation.splay(node: node) + } + return node } /* Returns the rightmost descendent. O(h) time. */ - public func maximum() -> SplayTree { + public func maximum(splayed: Bool = false) -> Node { var node = self while case let next? = node.right { node = next } - SplayOperation.splay(node: node) + if splayed == true { + SplayOperation.splay(node: node) + } return node } @@ -452,7 +491,7 @@ extension SplayTree { /* Finds the node whose value precedes our value in sorted order. */ - public func predecessor() -> SplayTree? { + public func predecessor() -> Node? { if let left = left { return left.maximum() } else { @@ -468,7 +507,7 @@ extension SplayTree { /* Finds the node whose value succeeds our value in sorted order. */ - public func successor() -> SplayTree? { + public func successor() -> Node? { if let right = right { return right.minimum() } else { @@ -483,7 +522,7 @@ extension SplayTree { } // MARK: - Traversal -extension SplayTree { +extension Node { public func traverseInOrder(process: (T) -> Void) { left?.traverseInOrder(process: process) @@ -518,7 +557,7 @@ extension SplayTree { /* Is this binary tree a valid binary search tree? */ -extension SplayTree { +extension Node { public func isBST(minValue: T, maxValue: T) -> Bool { if let value = value { @@ -533,7 +572,7 @@ extension SplayTree { // MARK: - Debugging -extension SplayTree: CustomStringConvertible { +extension Node: CustomStringConvertible { public var description: String { var s = "" if let left = left { @@ -549,7 +588,13 @@ extension SplayTree: CustomStringConvertible { } } -extension SplayTree: CustomDebugStringConvertible { +extension SplayTree: CustomStringConvertible { + public var description: String { + return root?.description ?? "Empty tree" + } +} + +extension Node: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(value)" if let parent = parent, let v = parent.value { @@ -568,3 +613,9 @@ extension SplayTree: CustomDebugStringConvertible { return map { $0 } } } + +extension SplayTree: CustomDebugStringConvertible { + public var debugDescription: String { + return root?.debugDescription ?? "Empty tree" + } +} From efa2f4856c6e80ccd36e8de11f3fb279974d9e3e Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:23:43 +0100 Subject: [PATCH 0203/1039] Tests for max, min, search, insert and remove --- Splay Tree/Tests/SplayTreeTests.swift | 52 ++++++++++++++++++++------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift index 042344193..0209f8afe 100644 --- a/Splay Tree/Tests/SplayTreeTests.swift +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -2,30 +2,58 @@ import XCTest class SplayTreeTests: XCTestCase { - var tree: SplayTree! var tree1: SplayTree! + var tree2: SplayTree! override func setUp() { super.setUp() - tree = SplayTree(value: 1) - tree1 = tree.insert(value: 10)?.insert(value: 20)?.insert(value: 3)?.insert(value: 6)?.insert(value: 100)?.insert(value: 44) + tree1 = SplayTree(value: 1) + + tree2 = SplayTree(value: 1) + tree2.insert(value: 10) + tree2.insert(value: 20) + tree2.insert(value: 3) + tree2.insert(value: 6) + tree2.insert(value: 100) + tree2.insert(value: 44) } func testInsertion() { - let tree1 = tree.insert(value: 10) - assert(tree1?.root?.value == 10) + tree1.insert(value: 10) + assert(tree1.value == 10) - let tree2 = tree1!.insert(value: 2) - assert(tree2?.root?.value == 2) + tree2.insert(value: 2) + assert(tree2.root?.value == 2) } - func testSearchNonExisting() { - print(tree1) - let tree2 = tree1.search(value: 5) - assert(tree2?.root?.value == 10) - + let t = tree2.search(value: 5) + assert(t?.value == 10) + } + + func testSearchExisting() { + let t = tree2.search(value: 6) + assert(t?.value == 6) + } + + func testDeleteExistingOnlyLeftChild() { + tree2.remove(value: 3) + assert(tree2.value == 6) + } + + func testDeleteExistingOnly2Children() { + tree2.remove(value: 6) + assert(tree2.value == 20) } + func testMinimum() { + let v = tree2.minimum() + assert(v?.value == 1) + } + + func testMaximum() { + let v = tree2.maximum() + assert(v?.value == 100) + } } From c27fdde75dc064f55ea7dfdcd5c7d0d4a44aaea6 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:24:22 +0100 Subject: [PATCH 0204/1039] Replacing SplayTree implementation inside Playground --- .../Sources/SplayTree.swift | 398 +++++++++++------- 1 file changed, 255 insertions(+), 143 deletions(-) diff --git a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift index f0c45e831..f50af7349 100644 --- a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift +++ b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift @@ -28,7 +28,7 @@ public enum SplayOperation { - Parameters: - node SplayTree node to move up to the root */ - public static func splay(node: SplayTree) { + public static func splay(node: Node) { while (node.parent != nil) { operation(forNode: node).apply(onNode: node) @@ -44,10 +44,10 @@ public enum SplayOperation { - Returns - Operation Case zigZag - zigZig - zig */ - private static func operation(forNode node: SplayTree) -> SplayOperation { + public static func operation(forNode node: Node) -> SplayOperation { - if let parent = node.parent, let grandParent = parent.parent { - if (node.isLeftChild && grandParent.isRightChild) || (node.isRightChild && grandParent.isLeftChild) { + if let parent = node.parent, let _ = parent.parent { + if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { return .zigZag } return .zigZig @@ -62,7 +62,7 @@ public enum SplayOperation { - Parameters: - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ - private func apply(onNode node: SplayTree) { + public func apply(onNode node: Node) { switch self { case .zigZag: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") @@ -84,49 +84,66 @@ public enum SplayOperation { Performs a single rotation from a node to its parent re-arranging the children properly */ - private func rotate(child: SplayTree, parent: SplayTree) { + public func rotate(child: Node, parent: Node) { assert(child.parent != nil && child.parent!.value == parent.value, "Parent and child.parent should match here") - var grandchildToMode: SplayTree? + var grandchildToMode: Node? + if child.isLeftChild { grandchildToMode = child.right - child.right = parent parent.left = grandchildToMode - + grandchildToMode?.parent = parent + + let grandParent = parent.parent + child.parent = grandParent + + if parent.isLeftChild { + grandParent?.left = child + } else { + grandParent?.right = child + } + + child.right = parent + parent.parent = child + + } else { grandchildToMode = child.left - child.left = parent parent.right = grandchildToMode + grandchildToMode?.parent = parent + + let grandParent = parent.parent + child.parent = grandParent + + if parent.isLeftChild { + grandParent?.left = child + } else { + grandParent?.right = child + } + + child.left = parent + parent.parent = child + } + - let grandParent = parent.parent - parent.parent = child - child.parent = grandParent } } -public class SplayTree { +public class Node { - fileprivate(set) public var value: T - fileprivate(set) public var parent: SplayTree? - fileprivate(set) public var left: SplayTree? - fileprivate(set) public var right: SplayTree? + fileprivate(set) public var value: T? + fileprivate(set) public var parent: Node? + fileprivate(set) public var left: Node? + fileprivate(set) public var right: Node? - public init(value: T) { + init(value: T) { self.value = value } - public convenience init(array: [T]) { - precondition(array.count > 0) - self.init(value: array.first!) - for v in array.dropFirst() { - insert(value: v) - } - } - public var isRoot: Bool { return parent == nil } @@ -165,114 +182,186 @@ public class SplayTree { } } +public class SplayTree { + + internal var root: Node? + + var value: T? { + return root?.value + } + + //MARK: - Initializer + + public init(value: T) { + self.root = Node(value:value) + } + + public func insert(value: T) { + root = root?.insert(value: value) + } + + public func remove(value: T) { + root = root?.remove(value: value) + } + + public func search(value: T) -> Node? { + root = root?.search(value: value) + return root + } + + public func minimum() -> Node? { + root = root?.minimum(splayed: true) + return root + } + + public func maximum() -> Node? { + root = root?.maximum(splayed: true) + return root + } + +} + // MARK: - Adding items -extension SplayTree { +extension Node { /* - Inserts a new element into the tree. You should only insert elements - at the root, to make to sure this remains a valid binary tree! - Performance: runs in O(h) time, where h is the height of the tree. + Inserts a new element into the node tree. + + - Parameters: + - value T value to be inserted. Will be splayed to the root position + + - Returns: + - Node inserted */ - public func insert(value: T) { - if value < self.value { - if let left = left { - left.insert(value: value) - } else { - - left = SplayTree(value: value) - left?.parent = self - + public func insert(value: T) -> Node { + if let selfValue = self.value { + if value < selfValue { if let left = left { - SplayOperation.splay(node: left) - self.parent = nil - self.value = left.value - self.left = left.left - self.right = left.right + return left.insert(value: value) + } else { + + left = Node(value: value) + left?.parent = self + + if let left = left { + SplayOperation.splay(node: left) + return left + } } - } - } else { - - if let right = right { - right.insert(value: value) } else { - right = SplayTree(value: value) - right?.parent = self - if let right = right { - SplayOperation.splay(node: right) - self.parent = nil - self.value = right.value - self.left = right.left - self.right = right.right + return right.insert(value: value) + } else { + + right = Node(value: value) + right?.parent = self + + if let right = right { + SplayOperation.splay(node: right) + return right + } } } } + return self } } // MARK: - Deleting items -extension SplayTree { +extension Node { + /* - Deletes a node from the tree. - Returns the node that has replaced this removed one (or nil if this was a - leaf node). That is primarily useful for when you delete the root node, in - which case the tree gets a new root. - Performance: runs in O(h) time, where h is the height of the tree. + Deletes the given node from the nodes tree. + Return the new tree generated by the removal. + The removed node (not necessarily the one containing the value), will be splayed to the root. + + - Parameters: + - value To be removed + + - Returns: + - Node Resulting from the deletion and the splaying of the removed node + */ - @discardableResult public func remove() -> SplayTree? { - let replacement: SplayTree? + public func remove(value: T) -> Node? { + let replacement: Node? - if let left = left { - if let right = right { - replacement = removeNodeWithTwoChildren(left, right) + if let v = self.value, v == value { + + var parentToSplay: Node? + if let left = left { + if let right = right { + + replacement = removeNodeWithTwoChildren(left, right) + + if let replacement = replacement, + let replacementParent = replacement.parent, + replacementParent.value != self.value { + + parentToSplay = replacement.parent + + } else { + parentToSplay = self.parent + } + + } else { + // This node only has a left child. The left child replaces the node. + replacement = left + parentToSplay = parent + } + } else if let right = right { + // This node only has a right child. The right child replaces the node. + replacement = right + parentToSplay = parent } else { - // This node only has a left child. The left child replaces the node. - replacement = left + // This node has no children. We just disconnect it from its parent. + replacement = nil + parentToSplay = parent } - } else if let right = right { - // This node only has a right child. The right child replaces the node. - replacement = right - } else { - // This node has no children. We just disconnect it from its parent. - replacement = nil - } + + reconnectParentTo(node: replacement) + + // performs the splay operation + if let parentToSplay = parentToSplay { + SplayOperation.splay(node: parentToSplay) + } + + // The current node is no longer part of the tree, so clean it up. + parent = nil + left = nil + right = nil - // Save the parent to splay before reconnecting - var parentToSplay: SplayTree? - if let replacement = replacement { - parentToSplay = replacement.parent + return parentToSplay + + } else if let v = self.value, value < v { + if left != nil { + return left!.remove(value: value) + } else { + let node = self + SplayOperation.splay(node: node) + return node + + } } else { - parentToSplay = self.parent - } - - reconnectParentTo(node: replacement) - - // performs the splay operation - if let parentToSplay = parentToSplay { - SplayOperation.splay(node: parentToSplay) + if right != nil { + return right?.remove(value: value) + } else { + let node = self + SplayOperation.splay(node: node) + return node + + } } - - // The current node is no longer part of the tree, so clean it up. - parent = nil - left = nil - right = nil - - return replacement } - private func removeNodeWithTwoChildren(_ left: SplayTree, _ right: SplayTree) -> SplayTree { + private func removeNodeWithTwoChildren(_ left: Node, _ right: Node) -> Node { // This node has two children. It must be replaced by the smallest // child that is larger than this node's value, which is the leftmost // descendent of the right child. let successor = right.minimum() - // If this in-order successor has a right child of its own (it cannot - // have a left child by definition), then that must take its place. - successor.remove() - // Connect our left child with the new node. successor.left = left left.parent = successor @@ -291,7 +380,7 @@ extension SplayTree { return successor } - private func reconnectParentTo(node: SplayTree?) { + private func reconnectParentTo(node: Node?) { if let parent = parent { if isLeftChild { parent.left = node @@ -305,31 +394,33 @@ extension SplayTree { // MARK: - Searching -extension SplayTree { +extension Node { /* Finds the "highest" node with the specified value. Performance: runs in O(h) time, where h is the height of the tree. */ - public func search(value: T) -> SplayTree? { - var node: SplayTree? = self - while case let n? = node { - if value < n.value { + public func search(value: T) -> Node? { + var node: Node? = self + var nodeParent: Node? = self + while case let n? = node, n.value != nil { + if value < n.value! { + if n.left != nil { nodeParent = n.left } node = n.left - } else if value > n.value { + } else if value > n.value! { node = n.right + if n.right != nil { nodeParent = n.right } } else { - - if let node = node { - SplayOperation.splay(node: node) - } - - return node + break } } if let node = node { SplayOperation.splay(node: node) + return node + } else if let nodeParent = nodeParent { + SplayOperation.splay(node: nodeParent) + return nodeParent } return nil @@ -342,27 +433,31 @@ extension SplayTree { /* Returns the leftmost descendent. O(h) time. */ - public func minimum() -> SplayTree { + public func minimum(splayed: Bool = false) -> Node { var node = self while case let next? = node.left { node = next } - SplayOperation.splay(node: node) - + if splayed == true { + SplayOperation.splay(node: node) + } + return node } /* Returns the rightmost descendent. O(h) time. */ - public func maximum() -> SplayTree { + public func maximum(splayed: Bool = false) -> Node { var node = self while case let next? = node.right { node = next } - SplayOperation.splay(node: node) + if splayed == true { + SplayOperation.splay(node: node) + } return node } @@ -396,13 +491,13 @@ extension SplayTree { /* Finds the node whose value precedes our value in sorted order. */ - public func predecessor() -> SplayTree? { + public func predecessor() -> Node? { if let left = left { return left.maximum() } else { var node = self - while case let parent? = node.parent { - if parent.value < value { return parent } + while case let parent? = node.parent, parent.value != nil, value != nil { + if parent.value! < value! { return parent } node = parent } return nil @@ -412,13 +507,13 @@ extension SplayTree { /* Finds the node whose value succeeds our value in sorted order. */ - public func successor() -> SplayTree? { + public func successor() -> Node? { if let right = right { return right.minimum() } else { var node = self - while case let parent? = node.parent { - if parent.value > value { return parent } + while case let parent? = node.parent, parent.value != nil , value != nil { + if parent.value! > value! { return parent } node = parent } return nil @@ -427,16 +522,16 @@ extension SplayTree { } // MARK: - Traversal -extension SplayTree { +extension Node { public func traverseInOrder(process: (T) -> Void) { left?.traverseInOrder(process: process) - process(value) + process(value!) right?.traverseInOrder(process: process) } public func traversePreOrder(process: (T) -> Void) { - process(value) + process(value!) left?.traversePreOrder(process: process) right?.traversePreOrder(process: process) } @@ -444,7 +539,7 @@ extension SplayTree { public func traversePostOrder(process: (T) -> Void) { left?.traversePostOrder(process: process) right?.traversePostOrder(process: process) - process(value) + process(value!) } /* @@ -453,7 +548,7 @@ extension SplayTree { public func map(formula: (T) -> T) -> [T] { var a = [T]() if let left = left { a += left.map(formula: formula) } - a.append(formula(value)) + a.append(formula(value!)) if let right = right { a += right.map(formula: formula) } return a } @@ -462,37 +557,48 @@ extension SplayTree { /* Is this binary tree a valid binary search tree? */ -extension SplayTree { +extension Node { public func isBST(minValue: T, maxValue: T) -> Bool { - if value < minValue || value > maxValue { return false } - let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true - let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true - return leftBST && rightBST + if let value = value { + if value < minValue || value > maxValue { return false } + let leftBST = left?.isBST(minValue: minValue, maxValue: value) ?? true + let rightBST = right?.isBST(minValue: value, maxValue: maxValue) ?? true + return leftBST && rightBST + } + return false } } // MARK: - Debugging -extension SplayTree: CustomStringConvertible { +extension Node: CustomStringConvertible { public var description: String { var s = "" if let left = left { - s += "(\(left.description)) <- " + s += "left: (\(left.description)) <- " + } + if let v = value { + s += "\(v)" } - s += "\(value)" if let right = right { - s += " -> (\(right.description))" + s += " -> (right: \(right.description))" } return s } } -extension SplayTree: CustomDebugStringConvertible { +extension SplayTree: CustomStringConvertible { + public var description: String { + return root?.description ?? "Empty tree" + } +} + +extension Node: CustomDebugStringConvertible { public var debugDescription: String { var s = "value: \(value)" - if let parent = parent { - s += ", parent: \(parent.value)" + if let parent = parent, let v = parent.value { + s += ", parent: \(v)" } if let left = left { s += ", left = [" + left.debugDescription + "]" @@ -507,3 +613,9 @@ extension SplayTree: CustomDebugStringConvertible { return map { $0 } } } + +extension SplayTree: CustomDebugStringConvertible { + public var debugDescription: String { + return root?.debugDescription ?? "Empty tree" + } +} From 4aaec9d94b5b6a5c75b07c35fd0e4def6830ac44 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:38:15 +0100 Subject: [PATCH 0205/1039] Test for root removal and multiple operations executed --- Splay Tree/Tests/SplayTreeTests.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Splay Tree/Tests/SplayTreeTests.swift b/Splay Tree/Tests/SplayTreeTests.swift index 0209f8afe..01201a108 100644 --- a/Splay Tree/Tests/SplayTreeTests.swift +++ b/Splay Tree/Tests/SplayTreeTests.swift @@ -46,6 +46,11 @@ class SplayTreeTests: XCTestCase { assert(tree2.value == 20) } + func testDeleteRoot() { + tree2.remove(value: 44) + assert(tree2.value == 100) + } + func testMinimum() { let v = tree2.minimum() assert(v?.value == 1) @@ -56,4 +61,16 @@ class SplayTreeTests: XCTestCase { assert(v?.value == 100) } + func testInsertionRemovals() { + let splayTree = SplayTree(value: 1) + splayTree.insert(value: 2) + splayTree.insert(value: 10) + splayTree.insert(value: 6) + + splayTree.remove(value: 10) + splayTree.remove(value: 6) + + assert(splayTree.value == 2) + } + } From 9da711ddf62bdc9b77d73ad64da8285a94f2b4cc Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:38:47 +0100 Subject: [PATCH 0206/1039] Fixes for root removal & insertions with nil root --- .../Sources/SplayTree.swift | 106 ++++++++++-------- Splay Tree/SplayTree.swift | 22 +++- 2 files changed, 78 insertions(+), 50 deletions(-) diff --git a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift index f50af7349..a4feda7ef 100644 --- a/Splay Tree/SplayTree.playground/Sources/SplayTree.swift +++ b/Splay Tree/SplayTree.playground/Sources/SplayTree.swift @@ -1,5 +1,5 @@ /* - * Splay Tree + * Splay Tree * * Based on Binary Search Tree Implementation written by Nicolas Ameghino and Matthijs Hollemans for Swift Algorithms Club * https://github.com/raywenderlich/swift-algorithm-club/blob/master/Binary%20Search%20Tree @@ -8,12 +8,12 @@ */ /** - Represent the 3 possible operations (combinations of rotations) that - could be performed during the Splay phase in Splay Trees + Represent the 3 possible operations (combinations of rotations) that + could be performed during the Splay phase in Splay Trees - - zigZag Left child of a right child OR right child of a left child - - zigZig Left child of a left child OR right child of a right child - - zig Only 1 parent and that parent is the root + - zigZag Left child of a right child OR right child of a left child + - zigZig Left child of a left child OR right child of a right child + - zig Only 1 parent and that parent is the root */ public enum SplayOperation { @@ -23,10 +23,10 @@ public enum SplayOperation { /** - Splay the given node up to the root of the tree + Splay the given node up to the root of the tree - - Parameters: - - node SplayTree node to move up to the root + - Parameters: + - node SplayTree node to move up to the root */ public static func splay(node: Node) { @@ -36,13 +36,13 @@ public enum SplayOperation { } /** - Compares the node and its parent and determine - if the rotations should be performed in a zigZag, zigZig or zig case. + Compares the node and its parent and determine + if the rotations should be performed in a zigZag, zigZig or zig case. - - Parmeters: - - forNode SplayTree node to be checked - - Returns - - Operation Case zigZag - zigZig - zig + - Parmeters: + - forNode SplayTree node to be checked + - Returns + - Operation Case zigZag - zigZig - zig */ public static func operation(forNode node: Node) -> SplayOperation { @@ -56,11 +56,11 @@ public enum SplayOperation { } /** - Applies the rotation associated to the case - Modifying the splay tree and briging the received node further to the top of the tree + Applies the rotation associated to the case + Modifying the splay tree and briging the received node further to the top of the tree - - Parameters: - - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent + - Parameters: + - onNode Node to splay up. Should be alwayas the node that needs to be splayed, neither its parent neither it's grandparent */ public func apply(onNode node: Node) { switch self { @@ -68,12 +68,12 @@ public enum SplayOperation { assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node, parent: node.parent!) rotate(child: node, parent: node.parent!) - + case .zigZig: assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") rotate(child: node.parent!, parent: node.parent!.parent!) rotate(child: node, parent: node.parent!) - + case .zig: assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") rotate(child: node, parent: node.parent!) @@ -81,8 +81,8 @@ public enum SplayOperation { } /** - Performs a single rotation from a node to its parent - re-arranging the children properly + Performs a single rotation from a node to its parent + re-arranging the children properly */ public func rotate(child: Node, parent: Node) { @@ -95,41 +95,41 @@ public enum SplayOperation { grandchildToMode = child.right parent.left = grandchildToMode grandchildToMode?.parent = parent - + let grandParent = parent.parent child.parent = grandParent - + if parent.isLeftChild { grandParent?.left = child } else { grandParent?.right = child } - + child.right = parent parent.parent = child - - + + } else { grandchildToMode = child.left parent.right = grandchildToMode grandchildToMode?.parent = parent - + let grandParent = parent.parent child.parent = grandParent - + if parent.isLeftChild { grandParent?.left = child } else { grandParent?.right = child } - + child.left = parent parent.parent = child - + } - + } } @@ -183,13 +183,13 @@ public class Node { } public class SplayTree { - + internal var root: Node? var value: T? { return root?.value } - + //MARK: - Initializer public init(value: T) { @@ -197,13 +197,17 @@ public class SplayTree { } public func insert(value: T) { - root = root?.insert(value: value) + if let root = root { + self.root = root.insert(value: value) + } else { + root = Node(value: value) + } } public func remove(value: T) { root = root?.remove(value: value) } - + public func search(value: T) -> Node? { root = root?.search(value: value) return root @@ -229,10 +233,10 @@ extension Node { Inserts a new element into the node tree. - Parameters: - - value T value to be inserted. Will be splayed to the root position + - value T value to be inserted. Will be splayed to the root position - Returns: - - Node inserted + - Node inserted */ public func insert(value: T) -> Node { if let selfValue = self.value { @@ -275,14 +279,14 @@ extension Node { /* Deletes the given node from the nodes tree. - Return the new tree generated by the removal. + Return the new tree generated by the removal. The removed node (not necessarily the one containing the value), will be splayed to the root. - Parameters: - - value To be removed + - value To be removed - Returns: - - Node Resulting from the deletion and the splaying of the removed node + - Node Resulting from the deletion and the splaying of the removed node */ public func remove(value: T) -> Node? { @@ -302,19 +306,29 @@ extension Node { parentToSplay = replacement.parent - } else { + } else if self.parent != nil { parentToSplay = self.parent + } else { + parentToSplay = replacement } } else { // This node only has a left child. The left child replaces the node. replacement = left - parentToSplay = parent + if self.parent != nil { + parentToSplay = self.parent + } else { + parentToSplay = replacement + } } } else if let right = right { // This node only has a right child. The right child replaces the node. replacement = right - parentToSplay = parent + if self.parent != nil { + parentToSplay = self.parent + } else { + parentToSplay = replacement + } } else { // This node has no children. We just disconnect it from its parent. replacement = nil @@ -332,7 +346,7 @@ extension Node { parent = nil left = nil right = nil - + return parentToSplay } else if let v = self.value, value < v { diff --git a/Splay Tree/SplayTree.swift b/Splay Tree/SplayTree.swift index f50af7349..a7b20743d 100644 --- a/Splay Tree/SplayTree.swift +++ b/Splay Tree/SplayTree.swift @@ -197,7 +197,11 @@ public class SplayTree { } public func insert(value: T) { - root = root?.insert(value: value) + if let root = root { + self.root = root.insert(value: value) + } else { + root = Node(value: value) + } } public func remove(value: T) { @@ -302,19 +306,29 @@ extension Node { parentToSplay = replacement.parent - } else { + } else if self.parent != nil { parentToSplay = self.parent + } else { + parentToSplay = replacement } } else { // This node only has a left child. The left child replaces the node. replacement = left - parentToSplay = parent + if self.parent != nil { + parentToSplay = self.parent + } else { + parentToSplay = replacement + } } } else if let right = right { // This node only has a right child. The right child replaces the node. replacement = right - parentToSplay = parent + if self.parent != nil { + parentToSplay = self.parent + } else { + parentToSplay = replacement + } } else { // This node has no children. We just disconnect it from its parent. replacement = nil From ecba738935641768526277d908153adc3f9d8ca6 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 5 Mar 2017 19:38:55 +0100 Subject: [PATCH 0207/1039] Playground Splay Tree --- .../SplayTree.playground/Contents.swift | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Splay Tree/SplayTree.playground/Contents.swift b/Splay Tree/SplayTree.playground/Contents.swift index 951ad4c5c..4406a759d 100644 --- a/Splay Tree/SplayTree.playground/Contents.swift +++ b/Splay Tree/SplayTree.playground/Contents.swift @@ -1,7 +1,29 @@ //: Playground - Splay Tree Implementation -let splayTree = SplayTree(array: [1]) +let splayTree = SplayTree(value: 1) splayTree.insert(value: 2) splayTree.insert(value: 10) splayTree.insert(value: 6) + +splayTree.remove(value: 10) +splayTree.remove(value: 6) + +splayTree.insert(value: 55) +splayTree.insert(value: 559) +splayTree.remove(value: 2) +splayTree.remove(value: 1) +splayTree.remove(value: 55) +splayTree.remove(value: 559) + +splayTree.insert(value: 1843000) +splayTree.insert(value: 1238) +splayTree.insert(value: -1) +splayTree.insert(value: 87) + +splayTree.minimum() +splayTree.maximum() + + + + From cae6d08a8c1ea02fdf37c6481e965b74457b0eaa Mon Sep 17 00:00:00 2001 From: vincentngo Date: Mon, 6 Mar 2017 15:15:06 -0500 Subject: [PATCH 0208/1039] Update link for radix sort --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index e2d99e2bc..dfe451478 100644 --- a/README.markdown +++ b/README.markdown @@ -80,7 +80,7 @@ Fast sorts: Special-purpose sorts: - [Counting Sort](Counting Sort/) -- Radix Sort +- [Radix Sort](Radix Sort/) - [Topological Sort](Topological Sort/) Bad sorting algorithms (don't use these!): From ce1ec8842561fb69c02f835278539f4bab287a8e Mon Sep 17 00:00:00 2001 From: "JUNYEONG.YOO" Date: Tue, 7 Mar 2017 19:31:50 +0900 Subject: [PATCH 0209/1039] Modified typo in README.md of QuickSort --- Quicksort/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Quicksort/README.markdown b/Quicksort/README.markdown index e3d284333..d359ecb5c 100644 --- a/Quicksort/README.markdown +++ b/Quicksort/README.markdown @@ -30,7 +30,7 @@ Here's how it works. When given an array, `quicksort()` splits it up into three 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 `right` array, then glues those sorted subarrays back together with the `equal` array to get the final result. +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 @@ -44,7 +44,7 @@ First, we pick the pivot element. That is `8` because it's in the middle of the equal: [ 8, 8 ] greater: [ 10, 9, 14, 27, 26 ] -This is a good split because `less` and `equal` roughly contain the same number of elements. So we've picked a good pivot that chopped the array right down the middle. +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. From 7a5700dbae300b075195842482cb74981ae5fc9e Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Wed, 8 Mar 2017 19:44:06 -0500 Subject: [PATCH 0210/1039] added ExpressibleByArrayLiteral to the Linked List and wrote test for the new initializer. --- .../LinkedList.playground/Contents.swift | 22 +++++++++++++++++-- Linked List/LinkedList.swift | 10 ++++++++- Linked List/Tests/LinkedListTests.swift | 22 +++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index a90b7180c..1f7aa7dae 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -10,7 +10,7 @@ public class LinkedListNode { } } -public class LinkedList { +public final class LinkedList { public typealias Node = LinkedListNode fileprivate var head: Node? @@ -187,7 +187,7 @@ extension LinkedList { } } -extension LinkedList { +extension LinkedList: ExpressibleByArrayLiteral { convenience init(array: Array) { self.init() @@ -195,6 +195,14 @@ extension LinkedList { self.append(element) } } + + public convenience init(arrayLiteral elements: T...) { + self.init() + + for element in elements { + self.append(element) + } + } } let list = LinkedList() @@ -255,3 +263,13 @@ list[0] // "Swift" list.remove(atIndex: 0) // "Swift" list.count // 0 + +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" diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 83f898f6c..792215a72 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -8,7 +8,7 @@ public class LinkedListNode { } } -public class LinkedList { +public final class LinkedList: ExpressibleByArrayLiteral { public typealias Node = LinkedListNode fileprivate var head: Node? @@ -203,4 +203,12 @@ extension LinkedList { self.append(element) } } + + public convenience init(arrayLiteral elements: T...) { + self.init() + + for element in elements { + self.append(element) + } + } } diff --git a/Linked List/Tests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift index 367ec8c6b..6f58d9775 100755 --- a/Linked List/Tests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -248,4 +248,26 @@ class LinkedListTest: XCTestCase { XCTAssertTrue(last === list.first) XCTAssertEqual(nodeCount, list.count) } + + func testArrayLiteralInitTypeInfer() { + let arrayLiteralInitInfer: LinkedList = [1.0, 2.0, 3.0] + + XCTAssertEqual(arrayLiteralInitInfer.count, 3) + XCTAssertEqual(arrayLiteralInitInfer.first?.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.first?.value, 1) + XCTAssertEqual(arrayLiteralInitExplicit.last?.value, 3) + XCTAssertEqual(arrayLiteralInitExplicit[1], 2) + XCTAssertEqual(arrayLiteralInitExplicit.removeLast(), 3) + XCTAssertEqual(arrayLiteralInitExplicit.count, 2) + } } From 6863590f96aa24a004af813f6c82272267c5b742 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Wed, 8 Mar 2017 19:53:20 -0500 Subject: [PATCH 0211/1039] implemented the ExpressibleByArrayLiteral for the Linked List in a new extension instead of the class declaration for readability --- .../LinkedList.playground/Contents.swift | 80 +++++++++++-------- Linked List/LinkedList.swift | 16 ++-- 2 files changed, 55 insertions(+), 41 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 1f7aa7dae..ed46331d8 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -4,7 +4,7 @@ public class LinkedListNode { var value: T var next: LinkedListNode? weak var previous: LinkedListNode? - + public init(value: T) { self.value = value } @@ -12,17 +12,19 @@ public class LinkedListNode { public final class LinkedList { 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 case let next? = node.next { @@ -33,7 +35,7 @@ public final class LinkedList { return nil } } - + public var count: Int { if var node = head { var c = 1 @@ -46,7 +48,7 @@ public final class LinkedList { return 0 } } - + public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head @@ -59,15 +61,19 @@ public final class LinkedList { } 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(_ newNode: Node) { if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode @@ -75,64 +81,68 @@ public final class LinkedList { head = newNode } } - + 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 (prev, next) = nodesBeforeAndAfter(index: index) - let newNode = Node(value: value) + self.insert(newNode, atIndex: index) + } + + public func insert(_ newNode: Node, atIndex index: Int) { + let (prev, next) = nodesBeforeAndAfter(index: index) + newNode.previous = prev newNode.next = next prev?.next = newNode next?.previous = newNode - + if prev == nil { head = newNode } } - + public func removeAll() { head = nil } - - public func remove(node: Node) -> T { + + @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 } - - public func removeLast() -> T { + + @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } - - public func remove(atIndex index: Int) -> T { + + @discardableResult public func remove(atIndex index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return remove(node: node!) @@ -173,7 +183,7 @@ extension LinkedList { } return result } - + public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head @@ -187,21 +197,23 @@ extension LinkedList { } } -extension LinkedList: ExpressibleByArrayLiteral { +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() + self.init() - for element in elements { - self.append(element) - } + for element in elements { + self.append(element) + } } } diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 792215a72..53dc77a06 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -8,7 +8,7 @@ public class LinkedListNode { } } -public final class LinkedList: ExpressibleByArrayLiteral { +public final class LinkedList { public typealias Node = LinkedListNode fileprivate var head: Node? @@ -203,12 +203,14 @@ extension LinkedList { self.append(element) } } - - public convenience init(arrayLiteral elements: T...) { - self.init() +} + +extension LinkedList: ExpressibleByArrayLiteral { + public convenience init(arrayLiteral elements: T...) { + self.init() - for element in elements { - self.append(element) - } + for element in elements { + self.append(element) } + } } From 345f8441b64003258779cd3fed692c5549a4cbd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Thu, 9 Mar 2017 18:35:26 +0800 Subject: [PATCH 0212/1039] add SelectionSamplingExample.swift --- .../SelectionSamplingExample.swift | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Selection Sampling/SelectionSamplingExample.swift diff --git a/Selection Sampling/SelectionSamplingExample.swift b/Selection Sampling/SelectionSamplingExample.swift new file mode 100644 index 000000000..66648a934 --- /dev/null +++ b/Selection Sampling/SelectionSamplingExample.swift @@ -0,0 +1,32 @@ +// +// Select.swift +// +// +// Created by Cheer on 2017/3/9. +// +// + +import Foundation + +func select(from a: [T], count requested: Int) -> [T] { + + // if requested > a.count, will throw ==> fatal error: Index out of range + + if requested < a.count { + var arr = a + for i in 0.. the range is [0...n-1] + //So: arc4random_uniform(UInt32(arr.count - i - 2)) + (i + 1) ==> [0...arr.count - (i + 1) - 1] + (i + 1) ==> the range is [(i + 1)...arr.count - 1] + //Why start index is "(i + 1)"? Because in "swap(&A,&B)", if A's index == B's index, will throw a error: "swapping a location with itself is not supported" + + let nextIndex = Int(arc4random_uniform(UInt32(arr.count - i - 2))) + (i + 1) + swap(&arr[nextIndex], &arr[i]) + } + return Array(arr[0.. Date: Mon, 13 Mar 2017 17:00:42 +0600 Subject: [PATCH 0213/1039] Egg Drop Dynamic Problem Added --- Egg Drop Problem/EggDrop.swift | 31 +++++++++++++++++++ .../contents.xcworkspacedata | 7 +++++ 2 files changed, 38 insertions(+) create mode 100644 Egg Drop Problem/EggDrop.swift diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift new file mode 100644 index 000000000..6d0aab2a1 --- /dev/null +++ b/Egg Drop Problem/EggDrop.swift @@ -0,0 +1,31 @@ +func eggDrop(_ numberOfEggs: Int, numberOfFloors: Int) -> Int { + var eggFloor: [[Int]] = [] //egg(rows) floor(cols) array to store the solutions + var attempts: Int = 0 + + for var i in (0.. k-1 + //case 2: egg doesn't break. meaning we'll still have 'i' number of eggs, and we'll go upstairs -> j-k + attempts = 1 + max(eggFloor[i-1][k-1], eggFloor[i][j-k])//we add one taking into account the attempt we're taking at the moment + + if attempts < eggFloor[i][j]{ //finding the min + eggFloor[i][j] = attempts; + } + } + } + } + + return eggFloor[numberOfEggs][numberOfFloors] +} + +func max(_ x1: Int, _ x2: Int){ + return x1 > x2 ? x1 : x2 +} diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index b2ffce836..5ac8577f5 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1,6 +1,13 @@ + + + + From 5205fc8cf7ac1091448aecd9e7680b25779c9a88 Mon Sep 17 00:00:00 2001 From: Deep Parekh Date: Thu, 23 Feb 2017 00:08:21 -0500 Subject: [PATCH 0214/1039] Added checks for subscript and fixed initializer compile error --- Array2D/Array2D.playground/Contents.swift | 69 +++++++++++++---------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 7064de59c..38d4eff23 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -1,31 +1,42 @@ /* - 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). -*/ + 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(repeatElement(initialValue, count: rows*columns)) - } - - public subscript(column: Int, row: Int) -> T { - get { - return array[row*columns + column] + public let columns: Int + public let rows: Int + public var array: [T] + + public init(columns: Int, rows: Int, initialValue: T) { + self.columns = columns + self.rows = rows + array = [T](repeating: initialValue, count: rows*columns) } - set { - array[row*columns + column] = newValue + + public subscript(column: Int, row: Int) -> T { + get { + if isValidSubscript(column: column, row: row) { + return array[row*columns + column] + } else { + fatalError("Not a valid subscript") + } + } + set { + if isValidSubscript(column: column, row: row) { + array[row*columns + column] = newValue + } else { + fatalError("Not a valid subscript") + } + } + } + + private func isValidSubscript(column: Int, row: Int) -> Bool { + return column < columns && row < rows } - } } - // initialization var matrix = Array2D(columns: 3, rows: 5, initialValue: 0) @@ -51,13 +62,13 @@ print(matrix.array) // print out the 2D array with a reference around the grid for i in 0.. Date: Wed, 15 Mar 2017 19:48:51 -0700 Subject: [PATCH 0215/1039] availability check, native array loop for signal --- DiningPhilosophers/Sources/main.swift | 46 +++++++++++++-------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/DiningPhilosophers/Sources/main.swift b/DiningPhilosophers/Sources/main.swift index deff344b9..285402d53 100755 --- a/DiningPhilosophers/Sources/main.swift +++ b/DiningPhilosophers/Sources/main.swift @@ -7,17 +7,16 @@ // -import Foundation import Dispatch let numberOfPhilosophers = 4 struct ForkPair { - static let forksSemaphore:[DispatchSemaphore] = Array(repeating: DispatchSemaphore(value: 1), count: numberOfPhilosophers) - + 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 { @@ -35,7 +34,7 @@ struct ForkPair { leftFork.wait() rightFork.wait() } - + func putDown() { //The order does not matter here leftFork.signal() @@ -47,61 +46,60 @@ struct ForkPair { 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 Philosofer: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") + print("Acquiring lock for Philosopher: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") forkPair.pickUp() print("Start Eating Philosopher: \(philosopherIndex)") //sleep(1000) - print("Releasing lock for Philosofer: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") + print("Releasing lock for Philosopher: \(philosopherIndex) Left:\(leftIndex) Right:\(rightIndex)") forkPair.putDown() } } } -// Layout of the table (P = philosopher, f = fork) for 4 Philosopher +// 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.. Date: Wed, 15 Mar 2017 19:53:29 -0700 Subject: [PATCH 0216/1039] links --- DiningPhilosophers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 29b5916e9..ec1611c65 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -1,5 +1,5 @@ # Dining Philosophers -Dining philosophers problem Algorithm implemented in Swift (concurrent algorithm design to illustrate synchronization issues and techniques for resolving them using GCD and Semaphore in Swift) +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 From a9655534e55620364e975cabb78242dca9db0c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Fri, 17 Mar 2017 11:06:13 +0800 Subject: [PATCH 0217/1039] Update ShellSortExample.swift Fix bug. Origin code probally get wrong answer.My fault. --- Shell Sort/ShellSortExample.swift | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index efa035da3..c41eb8889 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -8,24 +8,25 @@ import Foundation -public func shellSort(_ list: inout [Int]) { - +public func shellSort(_ list : inout [Int]) +{ var sublistCount = list.count / 2 - - while sublistCount > 0 { - - for index in 0.. 0 + { + for var index in 0.. list[index + sublistCount] { - swap(&list[index], &list[index + sublistCount]) + if arr[index] > arr[index + sublistCount]{ + swap(&arr[index], &arr[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } - - if list[index - 1] > list[index] { - swap(&list[index - 1], &list[index]) + + while arr[index - 1] > arr[index] && index - 1 > 0 { + swap(&arr[index - 1], &arr[index]) + index -= 1 } } sublistCount = sublistCount / 2 From beddc9a7f4dd96b9122e849ace3c7dba57caaea7 Mon Sep 17 00:00:00 2001 From: Brandon05 Date: Fri, 17 Mar 2017 13:41:49 -0400 Subject: [PATCH 0218/1039] Updated syntax for Swift 3 Hello, I was recreating this file in playground and I noticed you still had the explicit @noescape . Thought I can lend a hand by removing it. Thanks for this awesome repository! --- Binary Tree/BinaryTree.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Binary Tree/BinaryTree.swift b/Binary Tree/BinaryTree.swift index 61ae696c7..102f23e06 100644 --- a/Binary Tree/BinaryTree.swift +++ b/Binary Tree/BinaryTree.swift @@ -29,26 +29,26 @@ extension BinaryTree: CustomStringConvertible { } extension BinaryTree { - public func traverseInOrder(@noescape process: T -> Void) { + public func traverseInOrder(process: T -> Void) { if case let .node(left, value, right) = self { - left.traverseInOrder(process) + left.traverseInOrder(process: process) process(value) - right.traverseInOrder(process) + right.traverseInOrder(process: process) } } - public func traversePreOrder(@noescape process: T -> Void) { + public func traversePreOrder(process: T -> Void) { if case let .node(left, value, right) = self { process(value) - left.traversePreOrder(process) - right.traversePreOrder(process) + left.traversePreOrder(process: process) + right.traversePreOrder(process: process) } } - public func traversePostOrder(@noescape process: T -> Void) { + public func traversePostOrder(process: T -> Void) { if case let .node(left, value, right) = self { - left.traversePostOrder(process) - right.traversePostOrder(process) + left.traversePostOrder(process: process) + right.traversePostOrder(process: process) process(value) } } From 9677b8c0e6bbd32831b6eca6c69c6f09d64f9f37 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Fri, 17 Mar 2017 20:10:53 -0700 Subject: [PATCH 0219/1039] Fixed indenting, and changed a scope modifier on the array property from public to fileprivate. --- Array2D/Array2D.playground/Contents.swift | 72 +++++++++++------------ Array2D/README.markdown | 24 ++++++-- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 38d4eff23..8b18a333f 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -4,36 +4,36 @@ Performance is always O(1). */ public struct Array2D { - public let columns: Int - public let rows: Int - public var array: [T] - - public init(columns: Int, rows: Int, initialValue: T) { - self.columns = columns - self.rows = rows - array = [T](repeating: initialValue, count: rows*columns) + 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 = [T](repeating: initialValue, count: rows*columns) + } + + public subscript(column: Int, row: Int) -> T { + get { + if isValidSubscript(column: column, row: row) { + return array[row*columns + column] + } else { + fatalError("Not a valid subscript") + } } - - public subscript(column: Int, row: Int) -> T { - get { - if isValidSubscript(column: column, row: row) { - return array[row*columns + column] - } else { - fatalError("Not a valid subscript") - } - } - set { - if isValidSubscript(column: column, row: row) { - array[row*columns + column] = newValue - } else { - fatalError("Not a valid subscript") - } - } - } - - private func isValidSubscript(column: Int, row: Int) -> Bool { - return column < columns && row < rows + set { + if isValidSubscript(column: column, row: row) { + array[row*columns + column] = newValue + } else { + fatalError("Not a valid subscript") + } } + } + + private func isValidSubscript(column: Int, row: Int) -> Bool { + return column < columns && row < rows + } } @@ -62,13 +62,13 @@ print(matrix.array) // print out the 2D array with a reference around the grid for i in 0.. { public let columns: Int public let rows: Int - private var array: [T] - + 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) + array = [T](repeating: initialValue, count: rows*columns) } - + public subscript(column: Int, row: Int) -> T { get { - return array[row*columns + column] + if isValidSubscript(column: column, row: row) { + return array[row*columns + column] + } else { + fatalError("Not a valid subscript") + } } set { - array[row*columns + column] = newValue + if isValidSubscript(column: column, row: row) { + array[row*columns + column] = newValue + } else { + fatalError("Not a valid subscript") + } } } + + private func isValidSubscript(column: Int, row: Int) -> Bool { + return column < columns && row < rows + } } ``` From c4d39ec0dc41060f2ff5b5532e9fa69489c9bbef Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Fri, 17 Mar 2017 20:16:01 -0700 Subject: [PATCH 0220/1039] Updated the subscript check to use preconditions instead of a custom function. --- Array2D/Array2D.playground/Contents.swift | 22 +++++++--------------- Array2D/Array2D.swift | 9 +++++---- Array2D/README.markdown | 22 +++++++--------------- 3 files changed, 19 insertions(+), 34 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index 8b18a333f..d088c99af 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -11,29 +11,21 @@ public struct Array2D { public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = [T](repeating: initialValue, count: rows*columns) + array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { get { - if isValidSubscript(column: column, row: row) { - return array[row*columns + column] - } else { - fatalError("Not a valid subscript") - } + 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 { - if isValidSubscript(column: column, row: row) { - array[row*columns + column] = newValue - } else { - fatalError("Not a valid subscript") - } + 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 } } - - private func isValidSubscript(column: Int, row: Int) -> Bool { - return column < columns && row < rows - } } diff --git a/Array2D/Array2D.swift b/Array2D/Array2D.swift index 6d6c01902..df4822916 100644 --- a/Array2D/Array2D.swift +++ b/Array2D/Array2D.swift @@ -7,21 +7,22 @@ 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(row < rows, "Row \(row) Index is out of range. Array(columns: \(columns), rows:\(rows))") 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 } } diff --git a/Array2D/README.markdown b/Array2D/README.markdown index 6550dc943..04afb9510 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -72,29 +72,21 @@ public struct Array2D { public init(columns: Int, rows: Int, initialValue: T) { self.columns = columns self.rows = rows - array = [T](repeating: initialValue, count: rows*columns) + array = .init(repeating: initialValue, count: rows*columns) } public subscript(column: Int, row: Int) -> T { get { - if isValidSubscript(column: column, row: row) { - return array[row*columns + column] - } else { - fatalError("Not a valid subscript") - } + 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 { - if isValidSubscript(column: column, row: row) { - array[row*columns + column] = newValue - } else { - fatalError("Not a valid subscript") - } + 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 } } - - private func isValidSubscript(column: Int, row: Int) -> Bool { - return column < columns && row < rows - } } ``` From 162c3453bab7fa216cd3f11a9a45488ce9515c5c Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Tue, 21 Mar 2017 11:21:59 +0100 Subject: [PATCH 0221/1039] Exchanged old red-black tree implementation with new one, also updated redmea --- Red-Black Tree/README.markdown | 259 +++--- .../RedBlackTree.playground/Contents.swift | 22 + .../Sources/RedBlackTree.swift | 740 ++++++++++++++++++ .../contents.xcplayground | 4 + 4 files changed, 930 insertions(+), 95 deletions(-) create mode 100644 Red-Black Tree/RedBlackTree.playground/Contents.swift create mode 100644 Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift create mode 100644 Red-Black Tree/RedBlackTree.playground/contents.xcplayground diff --git a/Red-Black Tree/README.markdown b/Red-Black Tree/README.markdown index 05993f016..74fffa415 100644 --- a/Red-Black Tree/README.markdown +++ b/Red-Black Tree/README.markdown @@ -1,120 +1,189 @@ # Red-Black Tree -A Red-Black tree is a special version of a [Binary Search Tree](https://github.com/raywenderlich/swift-algorithm-club/tree/master/Binary%20Search%20Tree). Binary search trees(BSTs) can become unbalanced after a lot of insertions/deletions. The only difference between a node from a BST and a Red-Black Tree(RBT) is that RBT nodes have a color property added to them which can either be red or black. A RBT rebalances itself by making sure the following properties hold: +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. -## Properties -1. A node is either red or black -2. The root is always black -3. All leaves are black -4. If a node is red, both of its children are black -5. Every path to a leaf contains the same number of black nodes (The amount of black nodes met when going down a RBT is called the black-depth of the tree.) - -## Methods -* `insert(_ value: T)` inserts the value into the tree -* `insert(_ values: [T])` inserts an array of values into the tree -* `delete(_ value: T)` deletes the value from the tree -* `find(_ value: T) -> RBTNode` looks for a node in the tree with given value and returns it -* `minimum(n: RBTNode) -> RBTNode` looks for the maximum value of a subtree starting at the given node -* `maximum(n: RBTNode) -> RBTNode` looks for the minimum value of a subtree starting at the given node -* `func verify()` verifies if the tree is still valid. Prints warning messages if this is not the case - -## Rotation +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: -In order to rebalance their nodes RBTs use an operation known as rotation. You can either left or right rotate a node and its child. Rotating a node and its child swaps the nodes and interchanges their subtrees. Left rotation swaps the parent node with its right child. while right rotation swaps the parent node with its left child. - -Left rotation: -``` -before left rotating p after left rotating p - p b - / \ / \ - a b -> p n - / \ / \ / \ -n n n n a n - / \ - n n -``` -Right rotation: ``` -before right rotating p after right rotating p - p a - / \ / \ - a b -> n p - / \ / \ / \ -n n n n n b - / \ - n n +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: -## Insertion - -We create a new node with the value to be inserted into the tree. The color of this new node is always red. -We perform a standard BST insert with this node. Now the three might not be a valid RBT anymore. -We now go through several insertion steps in order to make the tree valid again. We call the just inserted node n. - -**Step 1**: We check if n is the rootNode, if so we paint it black and we are done. If not we go to Step 2. - -We now know that n at least has a parent as it is not the rootNode. - -**Step 2**: We check if the parent of n is black if so we are done. If not we go to Step 3. - -We now know the parent is also not the root node as the parent is red. Thus n also has a grandparent and thus also an uncle as every node has two children. This uncle may however be a nullLeaf - -**Step 3**: We check if n's uncle is red. If not we go to Step 4. If n's uncle is indeed red we recolor uncle and parent to black and n's grandparent to red. We now go back to step 1 performing the same logic on n's grandparent. - -From here there are four cases: -- **The left left case.** n's parent is the left child of its parent and n is the left child of its parent. -- **The left right case** n's parent is the left child of its parent and n is the right child of its parent. -- **The right right case** n's parent is the right child of its parent and n is the right child of its parent. -- **The right left case** n's parent is the right child of its parent and n is the left child of its parent. - -**Step 4**: checks if either the **left right** case or the **right left** case applies to the current situation. - - If we find the **left right case**, we left rotate n's parent and go to Step 5 while setting n to n's parent. (This transforms the **left right** case into the **left left** case) - - If we find the **right left case**, we right rotate n's parent and go to Step 5 while setting n to n's parent. (This transforms the **right left** case into the **right right** case) - - If we find neither of these two we proceed to Step 5. +## Properties -n's parent is now red, while n's grandparent is black. +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 -**Step 5**: We swap the colors of n's parent and grandparent. - - We either right rotate n's grandparent in case of the **left left** case - - Or we left rotate n's grandparent in case of the **right right** case +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] -Reaching the end we have successfully made the tree valid again. +## Methods -# Deletion +Nodes: +* `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 -Deletion is a little more complicated than insertion. In the following we call del the node to be deleted. -First we try and find the node to be deleted using find() -we send the result of find to del. -We now go through the following steps in order to delete the node del. +The rotation, insertion and deletion algorithms are implemented based on the pseudo-code provided in [CLRS] -First we do a few checks: -- Is del the rootNode if so set the root to a nullLeaf and we are done. -- If del has 2 nullLeaf children and is red. We check if del is either a left or a right child and set del's parent left or right to a nullLeaf. -- If del has two non nullLeaf children we look for the maximum value in del's left subtree. We set del's value to this maximum value and continue to instead delete this maximum node. Which we will now call del. +## Implementation Details -Because of these checks we now know that del has at most 1 non nullLeaf child. It has either two nullLeaf children or one nullLeaf and one regular red child. (The child is red otherwise the black-depth wouldn't be the same for every leaf) +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. -We now call the non nullLeaf child of del, child. If del has two nullLeaf children child will be a nullLeaf. This means child can either be a nullLeaf or a red node. +## Rotation -We now have three options +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). -- If del is red its child is a nullLeaf and we can just delete it as it doesn't change the black-depth of the tree. We are done +## Insertion -- If child is red we recolor it black and child's parent to del's parent. del is now deleted and we are done. +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] -- Both del and child are black we go through +``` +**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] -If both del and child are black we introduce a new variable sibling. Which is del's sibling. We also replace del with child and recolor it doubleBlack. del is now deleted and child and sibling are siblings. +``` +**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] -We now have to go through a lot of steps in order to remove this doubleBlack color. Which are hard to explain in text without just writing the full code in text. This is due the many possible combination of nodes and colors. The code is commented, but if you don't quite understand please leave me a message. Also part of the deletion is described by the final link in the Also See section. +``` +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] -## Also see +``` +**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] -* [Wikipedia](https://en.wikipedia.org/wiki/Red–black_tree) -* [GeeksforGeeks - introduction](http://www.geeksforgeeks.org/red-black-tree-set-1-introduction-2/) -* [GeeksforGeeks - insertion](http://www.geeksforgeeks.org/red-black-tree-set-2-insert/) -* [GeeksforGeeks - deletion](http://www.geeksforgeeks.org/red-black-tree-set-3-delete-2/) +``` +**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] -Important to note is that GeeksforGeeks doesn't mention a few deletion cases that do occur. The code however does implement these. +``` +**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] -*Written for Swift Algorithm Club by Jaap Wijnen. Updated from Ashwin Raghuraman's contribution.* +``` +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.* diff --git a/Red-Black Tree/RedBlackTree.playground/Contents.swift b/Red-Black Tree/RedBlackTree.playground/Contents.swift new file mode 100644 index 000000000..5b19f9bd1 --- /dev/null +++ b/Red-Black Tree/RedBlackTree.playground/Contents.swift @@ -0,0 +1,22 @@ +//: 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 _ in 0..<1000 { + let value = Double(arc4random()) / randomMax + values.append(value) + redBlackTree.insert(key: value) +} +redBlackTree.verify() + +for _ in 0..<1000 { + let rand = arc4random_uniform(UInt32(values.count)) + let index = Int(rand) + let value = values.remove(at: index) + redBlackTree.delete(key: value) +} +redBlackTree.verify() diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift new file mode 100644 index 000000000..057909b07 --- /dev/null +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -0,0 +1,740 @@ +// +// RedBlackTree.swift +// +// Created by Ute Schiehlen on 14.03.17. +// Copyright © 2017 Ute Schiehlen. All rights reserved. +// + +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: Key? + fileprivate var isNullLeaf = true + var leftChild: RBNode? + var rightChild: RBNode? + fileprivate weak var parent: RBNode? + + public init(key: Key?, 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: Key?) { + self.init(key: key, leftChild: RBNode(), rightChild: RBNode(), parent: RBNode()) + self.isNullLeaf = false + } + + // For initialising the nullLeaf + public convenience init() { + self.init(key: nil, leftChild: nil, rightChild: nil, parent: nil) + self.color = .black + self.isNullLeaf = true + } + + var isRoot: Bool { + return parent == nil + } + + var isLeaf: Bool { + return rightChild == nil && leftChild == nil + } + + var isLeftCild: Bool { + return parent?.leftChild === self + } + + var isRightChild: Bool { + return parent?.rightChild === self + } + + var grandparent: RBNode? { + return parent?.parent + } + + var sibling: RBNode? { + if isLeftCild { + return parent?.rightChild + } else { + return parent?.leftChild + } + } + + var uncle: RBNode? { + return parent?.sibling + } +} + +// MARK: - RedBlackTree + +public class RedBlackTree { + public typealias RBNode = RBTreeNode + + fileprivate(set) var root: RBNode + fileprivate(set) var size = 0 + fileprivate let nullLeaf = RBNode() + + public init() { + root = nullLeaf + } +} + +// 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: Key) -> RBNode? { + return search(key: input, node: root) + } + + /* + * Returns the node with given |key| in subtree of |node| + */ + fileprivate func search(key: Key, 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() -> Key? { + if let minNode = root.minimum() { + return minNode.key + } else { + return nil + } + } + + /* + * Returns the maximum key value of the whole tree + */ + public func maxValue() -> Key? { + if let maxNode = root.maximum() { + return maxNode.key + } else { + return nil + } + } +} + +// 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: Key) { + 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.isLeftCild && z.isRightChild { + zNew = parentZ + leftRotate(node: zNew) + } else if parentZ.isRightChild && z.isLeftCild { + 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.isLeftCild { + 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: Key) { + 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.isLeftCild { + 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.isLeftCild { + 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.isLeftCild && 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.isLeftCild { + 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.isLeftCild { + 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 \(node.key ?? nil) has red left child") + return false + } + if !rightChild.isNullLeaf && rightChild.color == .red { + print("Property-Error: Red node with key \(node.key ?? nil) 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 \(node.key ?? nil)") + 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: \(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 + } + } +} diff --git a/Red-Black Tree/RedBlackTree.playground/contents.xcplayground b/Red-Black Tree/RedBlackTree.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Red-Black Tree/RedBlackTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From cf91833f5688398045bb7b76150bc988df747580 Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Tue, 21 Mar 2017 11:23:37 +0100 Subject: [PATCH 0222/1039] Deleted old version --- .../Contents.swift | 20 - .../Sources/RBTree.swift | 521 ------------------ .../contents.xcplayground | 4 - .../contents.xcworkspacedata | 0 4 files changed, 545 deletions(-) delete mode 100644 Red-Black Tree/Red-Black Tree 2.playground/Contents.swift delete mode 100644 Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift delete mode 100644 Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground rename Red-Black Tree/{Red-Black Tree 2.playground => RedBlackTree.playground}/playground.xcworkspace/contents.xcworkspacedata (100%) diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Contents.swift b/Red-Black Tree/Red-Black Tree 2.playground/Contents.swift deleted file mode 100644 index d55c153d5..000000000 --- a/Red-Black Tree/Red-Black Tree 2.playground/Contents.swift +++ /dev/null @@ -1,20 +0,0 @@ -//: Playground - noun: a place where people can play -import Foundation - -let tree = RBTree() -let randomMax = Double(0x100000000) -var values = [Double]() -for _ in 0..<1000 { - let value = Double(arc4random()) / randomMax - values.append(value) - tree.insert(value) -} -tree.verify() - -for _ in 0..<1000 { - let rand = arc4random_uniform(UInt32(values.count)) - let index = Int(rand) - let value = values.remove(at: index) - tree.delete(value) -} -tree.verify() diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift deleted file mode 100644 index 1735798d5..000000000 --- a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift +++ /dev/null @@ -1,521 +0,0 @@ - -private enum RBTColor { - case red - case black - case doubleBlack -} - -public class RBTNode: CustomStringConvertible { - fileprivate var color: RBTColor = .red - public var value: T! = nil - public var right: RBTNode! - public var left: RBTNode! - public var parent: RBTNode! - - public var description: String { - if self.value == nil { - return "null" - } else { - var nodeValue: String - - // If the value is encapsulated by parentheses it is red - // If the value is encapsulated by pipes it is black - // If the value is encapsulated by double pipes it is double black (This should not occur in a verified RBTree) - if self.isRed { - nodeValue = "(\(self.value!))" - } else if self.isBlack{ - nodeValue = "|\(self.value!)|" - } else { - nodeValue = "||\(self.value!)||" - } - - return "(\(self.left.description)<-\(nodeValue)->\(self.right.description))" - } - } - - init(tree: RBTree) { - right = tree.nullLeaf - left = tree.nullLeaf - parent = tree.nullLeaf - } - - init() { - //This method is here to support the creation of a nullLeaf - } - - public var isLeftChild: Bool { - return self.parent.left === self - } - - public var isRightChild: Bool { - return self.parent.right === self - } - - public var grandparent: RBTNode { - return parent.parent - } - - public var sibling: RBTNode { - if isLeftChild { - return self.parent.right - } else { - return self.parent.left - } - } - - public var uncle: RBTNode { - return parent.sibling - } - - fileprivate var isRed: Bool { - return color == .red - } - - fileprivate var isBlack: Bool { - return color == .black - } - - fileprivate var isDoubleBlack: Bool { - return color == .doubleBlack - } -} - -public class RBTree: CustomStringConvertible { - public var root: RBTNode - fileprivate let nullLeaf: RBTNode - - public var description: String { - return root.description - } - - public init() { - nullLeaf = RBTNode() - nullLeaf.color = .black - root = nullLeaf - } - - public convenience init(withValue value: T) { - self.init() - insert(value) - } - - public convenience init(withArray array: [T]) { - self.init() - insert(array) - } - - public func insert(_ value: T) { - let newNode = RBTNode(tree: self) - newNode.value = value - insertNode(n: newNode) - } - - public func insert(_ values: [T]) { - for value in values { - print(value) - insert(value) - } - } - - public func delete(_ value: T) { - let nodeToDelete = find(value) - if nodeToDelete !== nullLeaf { - deleteNode(n: nodeToDelete) - } - } - - public func find(_ value: T) -> RBTNode { - let foundNode = findNode(rootNode: root, value: value) - return foundNode - } - - public func minimum(n: RBTNode) -> RBTNode { - var min = n - if n.left !== nullLeaf { - min = minimum(n: n.left) - } - - return min - } - - public func maximum(n: RBTNode) -> RBTNode { - var max = n - if n.right !== nullLeaf { - max = maximum(n: n.right) - } - - return max - } - - public func verify() { - if self.root === nullLeaf { - print("The tree is empty") - return - } - property1() - property2(n: self.root) - property3() - } - - private func findNode(rootNode: RBTNode, value: T) -> RBTNode { - var nextNode = rootNode - if rootNode !== nullLeaf && value != rootNode.value { - if value < rootNode.value { - nextNode = findNode(rootNode: rootNode.left, value: value) - } else { - nextNode = findNode(rootNode: rootNode.right, value: value) - } - } - - return nextNode - } - - private func insertNode(n: RBTNode) { - BSTInsertNode(n: n, parent: root) - insertCase1(n: n) - } - - private func BSTInsertNode(n: RBTNode, parent: RBTNode) { - if parent === nullLeaf { - self.root = n - } else if n.value < parent.value { - if parent.left !== nullLeaf { - BSTInsertNode(n: n, parent: parent.left) - } else { - parent.left = n - parent.left.parent = parent - } - } else { - if parent.right !== nullLeaf { - BSTInsertNode(n: n, parent: parent.right) - } else { - parent.right = n - parent.right.parent = parent - } - } - } - - // if node is root change color to black, else move on - private func insertCase1(n: RBTNode) { - if n === root { - n.color = .black - } else { - insertCase2(n: n) - } - } - - // if parent of node is not black, and node is not root move on - private func insertCase2(n: RBTNode) { - if !n.parent.isBlack { - insertCase3(n: n) - } - } - - // if uncle is red do stuff otherwise move to 4 - private func insertCase3(n: RBTNode) { - if n.uncle.isRed { // node must have grandparent as children of root have a black parent - // both parent and uncle are red, so grandparent must be black. - n.parent.color = .black - n.uncle.color = .black - n.grandparent.color = .red - // now both parent and uncle are black and grandparent is red. - // we repeat for the grandparent - insertCase1(n: n.grandparent) - } else { - insertCase4(n: n) - } - } - - // parent is red, grandparent is black, uncle is black - // There are 4 cases left: - // - left left - // - left right - // - right right - // - right left - - // the cases "left right" and "right left" can be rotated into the other two - // so if either of the two is detected we apply a rotation and then move on to - // deal with the final two cases, if neither is detected we move on to those cases anyway - private func insertCase4(n: RBTNode) { - if n.parent.isLeftChild && n.isRightChild { // left right case - leftRotate(n: n.parent) - insertCase5(n: n.left) - } else if n.parent.isRightChild && n.isLeftChild { // right left case - rightRotate(n: n.parent) - insertCase5(n: n.right) - } else { - insertCase5(n: n) - } - } - - private func insertCase5(n: RBTNode) { - // swap color of parent and grandparent - // parent is red grandparent is black - n.parent.color = .black - n.grandparent.color = .red - - if n.isLeftChild { // left left case - rightRotate(n: n.grandparent) - } else { // right right case - leftRotate(n: n.grandparent) - } - } - - private func deleteNode(n: RBTNode) { - var toDel = n - - if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.parent === nullLeaf { - self.root = nullLeaf - return - } - - if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.isRed { - if toDel.isLeftChild { - toDel.parent.left = nullLeaf - } else { - toDel.parent.right = nullLeaf - } - return - } - - if toDel.left !== nullLeaf && toDel.right !== nullLeaf { - let pred = maximum(n: toDel.left) - toDel.value = pred.value - toDel = pred - } - - // from here toDel has at most 1 non nullLeaf child - - var child: RBTNode - if toDel.left !== nullLeaf { - child = toDel.left - } else { - child = toDel.right - } - - if toDel.isRed || child.isRed { - child.color = .black - - if toDel.isLeftChild { - toDel.parent.left = child - } else { - toDel.parent.right = child - } - - if child !== nullLeaf { - child.parent = toDel.parent - } - } else { // both toDel and child are black - - var sibling = toDel.sibling - - if toDel.isLeftChild { - toDel.parent.left = child - } else { - toDel.parent.right = child - } - if child !== nullLeaf { - child.parent = toDel.parent - } - child.color = .doubleBlack - - while child.isDoubleBlack || (child.parent !== nullLeaf && child.parent != nil) { - if sibling.isBlack { - - var leftRedChild: RBTNode! = nil - if sibling.left.isRed { - leftRedChild = sibling.left - } - var rightRedChild: RBTNode! = nil - if sibling.right.isRed { - rightRedChild = sibling.right - } - - if leftRedChild != nil || rightRedChild != nil { // at least one of sibling's children are red - child.color = .black - if sibling.isLeftChild { - if leftRedChild != nil { // left left case - sibling.left.color = .black - let tempColor = sibling.parent.color - sibling.parent.color = sibling.color - sibling.color = tempColor - rightRotate(n: sibling.parent) - } else { // left right case - if sibling.parent.isRed { - sibling.parent.color = .black - } else { - sibling.right.color = .black - } - leftRotate(n: sibling) - rightRotate(n: sibling.grandparent) - } - } else { - if rightRedChild != nil { // right right case - sibling.right.color = .black - let tempColor = sibling.parent.color - sibling.parent.color = sibling.color - sibling.color = tempColor - leftRotate(n: sibling.parent) - } else { // right left case - if sibling.parent.isRed { - sibling.parent.color = .black - } else { - sibling.left.color = .black - } - rightRotate(n: sibling) - leftRotate(n: sibling.grandparent) - } - } - break - } else { // both sibling's children are black - child.color = .black - sibling.color = .red - if sibling.parent.isRed { - sibling.parent.color = .black - break - } - /* - sibling.parent.color = .doubleBlack - child = sibling.parent - sibling = child.sibling - */ - if sibling.parent.parent === nullLeaf { // parent of child is root - break - } else { - sibling.parent.color = .doubleBlack - child = sibling.parent - sibling = child.sibling // can become nill if child is root as parent is nullLeaf - } - //--------------- - } - } else { // sibling is red - sibling.color = .black - - if sibling.isLeftChild { // left case - rightRotate(n: sibling.parent) - sibling = sibling.right.left - sibling.parent.color = .red - } else { // right case - leftRotate(n: sibling.parent) - sibling = sibling.left.right - sibling.parent.color = .red - } - } - - // sibling check is here for when child is a nullLeaf and thus does not have a parent. - // child is here as sibling can become nil when child is the root - if (sibling.parent === nullLeaf) || (child !== nullLeaf && child.parent === nullLeaf) { - child.color = .black - } - } - } - } - - private func property1() { - - if self.root.isRed { - print("Root is not black") - } - } - - private func property2(n: RBTNode) { - if n === nullLeaf { - return - } - if n.isRed { - if n.left !== nullLeaf && n.left.isRed { - print("Red node: \(n.value), has red left child") - } else if n.right !== nullLeaf && n.right.isRed { - print("Red node: \(n.value), has red right child") - } - } - property2(n: n.left) - property2(n: n.right) - } - - private func property3() { - let bDepth = blackDepth(root: self.root) - - let leaves:[RBTNode] = getLeaves(n: self.root) - - for leaflet in leaves { - var leaf = leaflet - var i = 0 - - while leaf !== nullLeaf { - if leaf.isBlack { - i = i + 1 - } - leaf = leaf.parent - } - - if i != bDepth { - print("black depth: \(bDepth), is not equal (depth: \(i)) for leaf with value: \(leaflet.value)") - } - } - - } - - private func getLeaves(n: RBTNode) -> [RBTNode] { - var leaves = [RBTNode]() - - if n !== nullLeaf { - if n.left === nullLeaf && n.right === nullLeaf { - leaves.append(n) - } else { - let leftLeaves = getLeaves(n: n.left) - let rightLeaves = getLeaves(n: n.right) - - leaves.append(contentsOf: leftLeaves) - leaves.append(contentsOf: rightLeaves) - } - } - - return leaves - } - - private func blackDepth(root: RBTNode) -> Int { - if root === nullLeaf { - return 0 - } else { - let returnValue = root.isBlack ? 1 : 0 - return returnValue + (max(blackDepth(root: root.left), blackDepth(root: root.right))) - } - } - - private func leftRotate(n: RBTNode) { - let newRoot = n.right! - n.right = newRoot.left! - if newRoot.left !== nullLeaf { - newRoot.left.parent = n - } - newRoot.parent = n.parent - if n.parent === nullLeaf { - self.root = newRoot - } else if n.isLeftChild { - n.parent.left = newRoot - } else { - n.parent.right = newRoot - } - newRoot.left = n - n.parent = newRoot - } - - private func rightRotate(n: RBTNode) { - let newRoot = n.left! - n.left = newRoot.right! - if newRoot.right !== nullLeaf { - newRoot.right.parent = n - } - newRoot.parent = n.parent - if n.parent === nullLeaf { - self.root = newRoot - } else if n.isRightChild { - n.parent.right = newRoot - } else { - n.parent.left = newRoot - } - newRoot.right = n - n.parent = newRoot - } -} diff --git a/Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground b/Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground deleted file mode 100644 index 5da2641c9..000000000 --- a/Red-Black Tree/Red-Black Tree 2.playground/contents.xcplayground +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Red-Black Tree/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata b/Red-Black Tree/RedBlackTree.playground/playground.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Red-Black Tree/Red-Black Tree 2.playground/playground.xcworkspace/contents.xcworkspacedata rename to Red-Black Tree/RedBlackTree.playground/playground.xcworkspace/contents.xcworkspacedata From dc460542ffe226bbb0175fec35a9195eac87d9a3 Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Tue, 21 Mar 2017 11:30:51 +0100 Subject: [PATCH 0223/1039] Added licence to file --- .../Sources/RedBlackTree.swift | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift index 057909b07..a588ea6bc 100644 --- a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -1,9 +1,22 @@ +//Copyright (c) 2016 Matthijs Hollemans and contributors // -// RedBlackTree.swift +//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: // -// Created by Ute Schiehlen on 14.03.17. -// Copyright © 2017 Ute Schiehlen. All rights reserved. +//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 From 37d7300627bda5538381127db68571bf7b38f57e Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Tue, 21 Mar 2017 11:51:08 +0100 Subject: [PATCH 0224/1039] Incorporated major swiftlint warnings --- .../Sources/RedBlackTree.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift index a588ea6bc..6f3b16b86 100644 --- a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -25,7 +25,7 @@ private enum RBTreeColor { case black } -private enum rotationDirection { +private enum RotationDirection { case left case right } @@ -114,7 +114,7 @@ public class RedBlackTree { // MARK: - Equatable protocol extension RBTreeNode { - static public func ==(lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { + static public func == (lhs: RBTreeNode, rhs: RBTreeNode) -> Bool { return lhs.key == rhs.key } } @@ -309,8 +309,8 @@ extension RedBlackTree { * - case 2b -> red-black tree */ private func insertFixup(node z: RBNode) { - if(!z.isNullLeaf) { - guard let parentZ = z.parent else{ + 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 @@ -539,7 +539,6 @@ extension RedBlackTree { 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, @@ -561,7 +560,7 @@ extension RedBlackTree { * 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) { + 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 @@ -616,7 +615,6 @@ extension RedBlackTree { // 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 { @@ -746,7 +744,7 @@ extension RedBlackTree: CustomStringConvertible { public var description: String { if root.isNullLeaf { return "[]" - } else{ + } else { return root.description } } From 306ef65bd3ef8b652b1120bc8a5b6770583c3e35 Mon Sep 17 00:00:00 2001 From: kyungkoo Date: Fri, 24 Mar 2017 17:29:41 +0900 Subject: [PATCH 0225/1039] fixed broken link --- README.markdown | 100 ++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/README.markdown b/README.markdown index dfe451478..fc034f71b 100644 --- a/README.markdown +++ b/README.markdown @@ -34,31 +34,31 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Stack](Stack/) - [Queue](Queue/) -- [Insertion Sort](Insertion Sort/) -- [Binary Search](Binary Search/) and [Binary Search Tree](Binary Search Tree/) -- [Merge Sort](Merge Sort/) +- [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/) ## The algorithms ### Searching -- [Linear Search](Linear Search/). Find an element in an array. -- [Binary Search](Binary Search/). Quickly find elements in a sorted array. -- [Count Occurrences](Count Occurrences/). Count how often a value appears in an array. -- [Select Minimum / Maximum](Select Minimum Maximum). Find the minimum/maximum value in an array. -- [k-th Largest Element](Kth Largest Element/). Find the *k*-th largest element in an array, such as the median. -- [Selection Sampling](Selection Sampling/). Randomly choose a bunch of items from a collection. +- [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 String Search/). A naive method. +- [Brute-Force String Search](Brute-Force%20String%20Search/). A naive method. - [Boyer-Moore](Boyer-Moore/). 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 - [Rabin-Karp](Rabin-Karp/) Faster search by using hashing. -- [Longest Common Subsequence](Longest Common Subsequence/). Find the longest sequence of characters that appear in the same order in both strings. +- [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 @@ -67,51 +67,51 @@ It's fun to see how sorting algorithms work, but in practice you'll almost never Basic sorts: -- [Insertion Sort](Insertion Sort/) -- [Selection Sort](Selection Sort/) -- [Shell Sort](Shell Sort/) +- [Insertion Sort](Insertion%20Sort/) +- [Selection Sort](Selection%20Sort/) +- [Shell Sort](Shell%20Sort/) Fast sorts: - [Quicksort](Quicksort/) -- [Merge Sort](Merge Sort/) -- [Heap Sort](Heap Sort/) +- [Merge Sort](Merge%20Sort/) +- [Heap Sort](Heap%20Sort/) Special-purpose sorts: -- [Counting Sort](Counting Sort/) -- [Radix Sort](Radix Sort/) -- [Topological Sort](Topological Sort/) +- [Counting Sort](Counting%20Sort/) +- [Radix Sort](Radix%20Sort/) +- [Topological Sort](Topological%20Sort/) Bad sorting algorithms (don't use these!): -- [Bubble Sort](Bubble Sort/) -- [Slow Sort](Slow Sort/) +- [Bubble Sort](Bubble%20Sort/) +- [Slow Sort](Slow%20Sort/) ### Compression -- [Run-Length Encoding (RLE)](Run-Length Encoding/). Store repeated values as a single byte and a count. -- [Huffman Coding](Huffman Coding/). Store more common elements using a smaller number of bits. +- [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 Sort/). An improve upon the Bubble Sort algorithm. +- [Comb Sort](Comb%20Sort/). An improve upon the Bubble Sort algorithm. ### Mathematics - [Greatest Common Divisor (GCD)](GCD/). Special bonus: the least common multiple. - [Permutations and Combinations](Combinatorics/). Get your combinatorics on! -- [Shunting Yard Algorithm](Shunting Yard/). Convert infix expressions to postfix. +- [Shunting Yard Algorithm](Shunting%20Yard/). Convert infix expressions to postfix. - Statistics -- [Karatsuba Multiplication](Karatsuba Multiplication/). Another take on elementary multiplication. +- [Karatsuba Multiplication](Karatsuba%20Multiplication/). Another take on elementary multiplication. - [Haversine Distance](HaversineDistance/). Calculating the distance between 2 points from a sphere. ### Machine learning - [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. - k-Nearest Neighbors -- [Linear Regression](Linear Regression/) +- [Linear Regression](Linear%20Regression/) - Logistic Regression - Neural Networks - PageRank @@ -129,33 +129,33 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Variations on arrays - [Array2D](Array2D/). A two-dimensional array with fixed dimensions. Useful for board games. -- [Bit Set](Bit Set/). A fixed-size sequence of *n* bits. -- [Fixed Size Array](Fixed Size Array/). 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 Array/). An array that is always sorted. -- [Rootish Array Stack](Rootish Array Stack/). A space and time efficient variation on Swift arrays. +- [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 Queue). A queue where the most important element is always at the front. -- [Ring Buffer](Ring Buffer/). Also known as a circular buffer. An array of a certain size that conceptually wraps around back to the beginning. +- [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 List/). A sequence of data items connected through links. Covers both singly and doubly linked 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 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. ### Trees - [Tree](Tree/). A general-purpose tree structure. -- [Binary Tree](Binary Tree/). A tree where each node has at most two children. -- [Binary Search Tree (BST)](Binary Search Tree/). A binary tree that orders its nodes in a way that allows for fast queries. +- [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 - Splay Tree - Threaded Binary Tree -- [Segment Tree](Segment Tree/). Can quickly compute a function over a portion of an array. +- [Segment Tree](Segment%20Tree/). Can quickly compute a function over a portion of an array. - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. - Fibonacci Heap @@ -164,33 +164,33 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types ### Hashing -- [Hash Table](Hash Table/). Allows you to store and retrieve objects by a key. This is how the dictionary type is usually implemented. +- [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 Filter/). A constant-memory data structure that probabilistically tests whether an element is in a set. -- [Hash Set](Hash Set/). A set implemented using a hash table. +- [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 -- [Ordered Set](Ordered Set/). A set where the order of items matters. +- [Ordered Set](Ordered%20Set/). A set where the order of items matters. ### Graphs - [Graph](Graph/) -- [Breadth-First Search (BFS)](Breadth-First Search/) -- [Depth-First Search (DFS)](Depth-First Search/) -- [Shortest Path](Shortest Path %28Unweighted%29/) on an unweighted tree -- [Single-Source Shortest Paths](Single-Source Shortest Paths (Weighted)/) -- [Minimum Spanning Tree](Minimum Spanning Tree %28Unweighted%29/) on an unweighted tree -- [All-Pairs Shortest Paths](All-Pairs Shortest Paths/) +- [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 +- [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) ## 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 Problem/) -- [Fizz Buzz](Fizz Buzz/) -- [Monty Hall Problem](Monty Hall Problem/) +- [Two-Sum Problem](Two-Sum%20Problem/) +- [Fizz Buzz](Fizz%20Buzz/) +- [Monty Hall Problem](Monty%20Hall%20Problem/) - [Finding Palindromes](Palindromes/) - [Dining Philosophers](DiningPhilosophers/) From 943ad7e48fe966f7679c4addfafa7baa5fb81fb2 Mon Sep 17 00:00:00 2001 From: kyungkoo Date: Fri, 24 Mar 2017 18:25:24 +0900 Subject: [PATCH 0226/1039] fixed important links section link --- README.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.markdown b/README.markdown index fc034f71b..023f151fb 100644 --- a/README.markdown +++ b/README.markdown @@ -16,17 +16,17 @@ This is a work in progress. More algorithms will be added soon. :-) ## Important links -[What are algorithms and data structures?](What are Algorithms.markdown) Pancakes! +[What are algorithms and data structures?](What%20are%20Algorithms.markdown) Pancakes! -[Why learn algorithms?](Why Algorithms.markdown) Worried this isn't your cup of tea? Then read this. +[Why learn algorithms?](Why%20Algorithms.markdown) Worried this isn't your cup of tea? Then read this. -[Big-O notation](Big-O Notation.markdown). We often say things like, "This algorithm is **O(n)**." If you don't know what that means, read this first. +[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 Design.markdown). How do you create your own algorithms? +[Algorithm design techniques](Algorithm%20Design.markdown). How do you create your own algorithms? -[How to contribute](How to Contribute.markdown). Report an issue to leave feedback, or submit a pull request. +[How to contribute](How%20to%20Contribute.markdown). Report an issue to leave feedback, or submit a pull request. -[Under construction](Under Construction.markdown). Algorithms that are under construction. +[Under construction](Under%20Construction.markdown). Algorithms that are under construction. ## Where to start? From a54e722b035ffc5eeba63fcd5b1648e56f732ec0 Mon Sep 17 00:00:00 2001 From: Jake Romer Date: Fri, 24 Mar 2017 07:58:19 -0700 Subject: [PATCH 0227/1039] Fix links to related articles Fixes links to Linked List, Ring Buffer, and Priority Queue directories. --- Queue/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Queue/README.markdown b/Queue/README.markdown index f8259c31c..9efce66b9 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -255,8 +255,8 @@ The `nil` objects at the front have been removed and the array is no longer wast ## See also -There are many other ways to create a queue. Alternative implementations use a [linked list](../Linked List/), a [circular buffer](../Ring Buffer/), or a [heap](../Heap/). +There are many other 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 Queue/), a sorted queue where the "most important" item is always at the front. +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* From 3d033740b0d3b727d488a14121da68f822b578a2 Mon Sep 17 00:00:00 2001 From: Jake Romer Date: Sat, 25 Mar 2017 07:47:49 -0700 Subject: [PATCH 0228/1039] URL encode links in Markdown files There are a ton of broken markdown links in the READMEs throughout this repo because the files and directories they refer to have spaces in their names but these aren't HTML encoded in their links. This commit just replaces spaces with %20 to fix these. --- AVL Tree/README.markdown | 8 ++++---- Big-O Notation.markdown | 2 +- Binary Search Tree/README.markdown | 10 +++++----- Binary Search/README.markdown | 2 +- Binary Tree/README.markdown | 2 +- Bloom Filter/README.markdown | 2 +- Bounded Priority Queue/README.markdown | 2 +- Boyer-Moore/README.markdown | 2 +- Breadth-First Search/README.markdown | 4 ++-- Count Occurrences/README.markdown | 4 ++-- Hash Set/README.markdown | 2 +- How to Contribute.markdown | 2 +- Ordered Array/README.markdown | 2 +- Ordered Set/README.markdown | 2 +- Selection Sort/README.markdown | 6 +++--- Shell Sort/README.markdown | 2 +- Shortest Path (Unweighted)/README.markdown | 8 ++++---- Threaded Binary Tree/README.markdown | 10 +++++----- Topological Sort/README.markdown | 2 +- Tree/README.markdown | 4 ++-- Under Construction.markdown | 20 ++++++++++---------- 21 files changed, 49 insertions(+), 49 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index 355204587..a9218203a 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -1,6 +1,6 @@ # AVL Tree -An AVL tree is a self-balancing form of a [binary search tree](../Binary Search Tree/), in which the height of subtrees differ at most by only 1. +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. @@ -8,7 +8,7 @@ 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 List/). 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. +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: @@ -78,7 +78,7 @@ Insertion never needs more than 2 rotations. Removal might require up to __log(n Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary search tree](../Binary Search Tree/) 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 Search Tree/). It will make the rest of the AVL tree easier to understand. +> **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. @@ -86,6 +86,6 @@ The interesting bits are in the `balance()` method which is called after inserti [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 Tree/) seems to be more popular. +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 and Matthijs Hollemans* diff --git a/Big-O Notation.markdown b/Big-O Notation.markdown index 8cb988168..09fbb04aa 100644 --- a/Big-O Notation.markdown +++ b/Big-O Notation.markdown @@ -19,6 +19,6 @@ Big-O | Name | Description 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 Sort/) algorithm is **O(n^2)**. In theory that is worse than the running time for [merge sort](Merge Sort/), 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! +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 Sort/), 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. diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index bd2a00c9e..a3a84c03d 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -1,6 +1,6 @@ # Binary Search Tree (BST) -A binary search tree is a special kind of [binary tree](../Binary Tree/) (a tree in which each node has at most two children) that performs insertions and deletions such that the tree is always sorted. +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. If you don't know what a tree is or what it is for, then [read this first](../Tree/). @@ -49,7 +49,7 @@ If we were looking for the value `5` in the example, it would go as follows: ![Searching the tree](Images/Searching.png) -Thanks to the structure of the tree, searching is really fast. 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 Search) in an array.) +Thanks to the structure of the tree, searching is really fast. 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 @@ -535,7 +535,7 @@ The code for `successor()` works the exact same way but mirrored: Both these methods run in **O(h)** time. -> **Note:** There is a cool variation called a ["threaded" binary tree](../Threaded Binary Tree) where "unused" left and right pointers are repurposed to make direct links between predecessor and successor nodes. Very clever! +> **Note:** There is a cool 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? @@ -713,11 +713,11 @@ The root node is in the middle; a dot means there is no child at that position. A binary search tree is *balanced* when its left and right subtrees contain roughly the same number of nodes. In that case, the height of the tree is *log(n)*, where *n* is the number of nodes. That's the ideal situation. -However, if one branch is significantly longer than the other, searching becomes very slow. We end up checking way more values than we'd ideally have to. In the worst case, the height of the tree can become *n*. Such a tree acts more like a [linked list](../Linked List/) than a binary search tree, with performance degrading to **O(n)**. Not good! +However, if one branch is significantly longer than the other, searching becomes very slow. We end up checking way more values than we'd ideally have to. In the worst case, the height of the tree can become *n*. Such a tree acts more 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 quite nicely. But it 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. See [AVL tree](../AVL Tree) and [red-black tree](../Red-Black Tree) for examples. +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. See [AVL tree](../AVL%20Tree) and [red-black tree](../Red-Black%20Tree) for examples. ## See also diff --git a/Binary Search/README.markdown b/Binary Search/README.markdown index c65d0b5fd..09b141e04 100644 --- a/Binary Search/README.markdown +++ b/Binary Search/README.markdown @@ -12,7 +12,7 @@ let numbers = [11, 59, 3, 2, 53, 17, 31, 7, 19, 67, 47, 13, 37, 61, 29, 43, 5, 4 numbers.indexOf(43) // returns 15 ``` -The built-in `indexOf()` function performs a [linear search](../Linear Search/). In code that looks something like this: +The built-in `indexOf()` function performs a [linear search](../Linear%20Search/). In code that looks something like this: ```swift func linearSearch(_ a: [T], _ key: T) -> Int? { diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 896116dda..8ce398804 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -8,7 +8,7 @@ The child nodes are usually called the *left* child and the *right* child. If a 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 Search Tree/). 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. +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))`: diff --git a/Bloom Filter/README.markdown b/Bloom Filter/README.markdown index a85d71be4..3fff0a379 100644 --- a/Bloom Filter/README.markdown +++ b/Bloom Filter/README.markdown @@ -18,7 +18,7 @@ An advantage of the Bloom Filter over a hash table is that the former maintains ## Inserting objects into the set -A Bloom Filter is essentially a fixed-length [bit vector](../Bit Set/), 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. +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. diff --git a/Bounded Priority Queue/README.markdown b/Bounded Priority Queue/README.markdown index 8d47adefb..4e4c89272 100644 --- a/Bounded Priority Queue/README.markdown +++ b/Bounded Priority Queue/README.markdown @@ -1,6 +1,6 @@ # Bounded Priority queue -A bounded priority queue is similar to a regular [priority queue](../Priority Queue/), 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. +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 diff --git a/Boyer-Moore/README.markdown b/Boyer-Moore/README.markdown index e821b812e..5b3841eca 100644 --- a/Boyer-Moore/README.markdown +++ b/Boyer-Moore/README.markdown @@ -24,7 +24,7 @@ animals.indexOf(pattern: "🐮") > **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 String Search/) 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 [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. diff --git a/Breadth-First Search/README.markdown b/Breadth-First Search/README.markdown index 084f4611a..2ef92fd73 100644 --- a/Breadth-First Search/README.markdown +++ b/Breadth-First Search/README.markdown @@ -148,7 +148,7 @@ This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]` Breadth-first search can be used to solve many problems. A small selection: -* Computing the [shortest path](../Shortest Path/) between a source node and each of the other nodes (only for unweighted graphs). -* Calculating the [minimum spanning tree](../Minimum Spanning Tree (Unweighted)/) on an unweighted graph. +* Computing the [shortest path](../Shortest%20Path/) 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* diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index 90a9ec2f3..4c65c4219 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -2,9 +2,9 @@ Goal: Count how often a certain value appears in an array. -The obvious way to do this is with a [linear search](../Linear Search/) 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. +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 Search/). +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: diff --git a/Hash Set/README.markdown b/Hash Set/README.markdown index 368920a1c..fb829c313 100644 --- a/Hash Set/README.markdown +++ b/Hash Set/README.markdown @@ -196,7 +196,7 @@ difference2.allElements() // [5, 6] 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 Table), but one that just stores the keys and doesn't associate them with anything. So you wouldn't need the `Bool` values anymore. +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. diff --git a/How to Contribute.markdown b/How to Contribute.markdown index 258357e8b..1235f07ff 100644 --- a/How to Contribute.markdown +++ b/How to Contribute.markdown @@ -6,7 +6,7 @@ Want to help out with the Swift Algorithm Club? Great! Take a look at the [list](README.markdown). Any algorithms or data structures that don't have a link yet are up for grabs. -Algorithms in the [Under construction](Under Construction.markdown) area are being worked on. Suggestions and feedback is welcome! +Algorithms in the [Under construction](Under%20Construction.markdown) area are being worked on. Suggestions and feedback is welcome! New algorithms and data structures are always welcome (even if they aren't on the list). diff --git a/Ordered Array/README.markdown b/Ordered Array/README.markdown index ca088c325..974a42cae 100644 --- a/Ordered Array/README.markdown +++ b/Ordered Array/README.markdown @@ -83,7 +83,7 @@ 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 Search) to find the insertion point. +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: diff --git a/Ordered Set/README.markdown b/Ordered Set/README.markdown index 0525a31ed..1c0d5a8ac 100644 --- a/Ordered Set/README.markdown +++ b/Ordered Set/README.markdown @@ -115,7 +115,7 @@ The next function is `indexOf()`, which takes in an object of type `T` and retur } ``` -> **Note:** If you are not familiar with the concept of binary search, we have an [article that explains all about it](../Binary Search). +> **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. diff --git a/Selection Sort/README.markdown b/Selection Sort/README.markdown index c583b47ea..e95749d14 100644 --- a/Selection Sort/README.markdown +++ b/Selection Sort/README.markdown @@ -6,7 +6,7 @@ You are given an array of numbers and need to put them in the right order. The s [ ...sorted numbers... | ...unsorted numbers... ] -This is similar to [insertion sort](../Insertion Sort/), but the difference is in how new numbers are added to the sorted portion. +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: @@ -108,9 +108,9 @@ The source file [SelectionSort.swift](SelectionSort.swift) has a version of this ## Performance -Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion Sort/) but better than [bubble sort](../Bubble Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. +Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. -[Heap sort](../Heap Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. +[Heap sort](../Heap%20Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. ## See also diff --git a/Shell Sort/README.markdown b/Shell Sort/README.markdown index 9c4bdf076..c21c29685 100644 --- a/Shell Sort/README.markdown +++ b/Shell Sort/README.markdown @@ -39,7 +39,7 @@ As you can see, each sublist contains only every 4th item from the original arra We now call `insertionSort()` once on each sublist. -This particular version of [insertion sort](../Insertion Sort/) 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. +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: diff --git a/Shortest Path (Unweighted)/README.markdown b/Shortest Path (Unweighted)/README.markdown index a16519260..4c3c34d9c 100644 --- a/Shortest Path (Unweighted)/README.markdown +++ b/Shortest Path (Unweighted)/README.markdown @@ -12,11 +12,11 @@ If the [graph is unweighed](../Graph/), then finding the shortest path is easy: ## Unweighted graph: breadth-first search -[Breadth-first search](../Breadth-First Search/) is a method for traversing a tree or graph data structure. It starts at a source node and explores the immediate neighbor nodes first, before moving to the next level neighbors. As a convenient side effect, it automatically computes the shortest path between a source node and each of the other nodes in the tree or graph. +[Breadth-first search](../Breadth-First%20Search/) is a method for traversing a tree or graph data structure. It starts at a source node and explores the immediate neighbor nodes first, before moving to the next level neighbors. As a convenient side effect, it automatically computes the shortest path between a source node and each of the other nodes in the tree or graph. The result of the breadth-first search can be represented with a tree: -![The BFS tree](../Breadth-First Search/Images/TraversalTree.png) +![The BFS tree](../Breadth-First%20Search/Images/TraversalTree.png) The root of the tree is the node you started the breadth-first search from. To find the distance from node `A` to any other node, we simply count the number of edges in the tree. And so we find that the shortest path between `A` and `F` is 2. The tree not only tells you how long that path is, but also how to actually get from `A` to `F` (or any of the other nodes). @@ -57,7 +57,7 @@ queue.enqueue(element: G) G.distance = C.distance + 1 // result: 2 ``` -This continues until the queue is empty and we've visited all the nodes. Each time we discover a new node, it gets the `distance` of its parent plus 1. As you can see, this is exactly what the [breadth-first search](../Breadth-First Search/) algorithm does, except that we now also keep track of the distance travelled. +This continues until the queue is empty and we've visited all the nodes. Each time we discover a new node, it gets the `distance` of its parent plus 1. As you can see, this is exactly what the [breadth-first search](../Breadth-First%20Search/) algorithm does, except that we now also keep track of the distance travelled. Here's the code: @@ -97,6 +97,6 @@ This will output: 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 Spanning Tree (Unweighted)/) on how you can convert the graph into a tree by removing edges. +> **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* diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index fd05113d8..8a1c518f1 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -1,6 +1,6 @@ # Threaded Binary Tree -A threaded binary tree is a special kind of [binary tree](../Binary Tree/) (a +A threaded binary tree is a special kind of [binary tree](../Binary%20Tree/) (a tree in which each node has at most two children) that maintains a few extra variables to allow cheap and fast **in-order traversal** of the tree. We will explore the general structure of threaded binary trees, as well as @@ -17,7 +17,7 @@ The main motivation behind using a threaded binary tree over a simpler and smaller standard binary tree is to increase the speed of an in-order traversal of the tree. An in-order traversal of a binary tree visits the nodes in the order in which they are stored, which matches the underlying ordering of a -[binary search tree](../Binary Search Tree/). This means most threaded binary +[binary search tree](../Binary%20Search%20Tree/). This means most threaded binary trees are also binary search trees. The idea is to visit all the left children of a node first, then visit the node itself, and then visit the right children last. @@ -47,7 +47,7 @@ tree, to **O(n)** to a very unbalanced tree. A threaded binary tree fixes this problem. -> For more information about in-order traversals [see here](../Binary Tree/). +> For more information about in-order traversals [see here](../Binary%20Tree/). ## Predecessors and successors @@ -222,7 +222,7 @@ 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 Search Tree/). +[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. @@ -339,7 +339,7 @@ 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 Search Tree/). +find [further documentation here](../Binary%20Search%20Tree/). ## See also diff --git a/Topological Sort/README.markdown b/Topological Sort/README.markdown index 4429a0754..5659dc3fd 100644 --- a/Topological Sort/README.markdown +++ b/Topological Sort/README.markdown @@ -22,7 +22,7 @@ The following is not a valid topological sort for this graph, since **X** and ** 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 Search/) 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... +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: diff --git a/Tree/README.markdown b/Tree/README.markdown index 529a68cf1..440d9c9a4 100644 --- a/Tree/README.markdown +++ b/Tree/README.markdown @@ -16,7 +16,7 @@ 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 List/) is a simple version of a tree. Think about it!) +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. @@ -119,7 +119,7 @@ We often use the following definitions when talking about trees: - **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 Tree/). A very common type of tree is the [binary search tree](../Binary Search Tree/) (or BST), a stricter version of a binary tree where the nodes are ordered in a particular way to speed up searches. +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. diff --git a/Under Construction.markdown b/Under Construction.markdown index 0c59d90c1..be53e01b0 100644 --- a/Under Construction.markdown +++ b/Under Construction.markdown @@ -5,27 +5,27 @@ Here you'll find algorithms that are currently under construction. Suggestions a ### Sorting Special-purpose sorts: - - [Radix Sort](Radix Sort/) + - [Radix Sort](Radix%20Sort/) ### Special-purpose sorts: -- [Bucket Sort](Bucket Sort/) +- [Bucket Sort](Bucket%20Sort/) ### Queues -- [Bounded Priority Queue](Bounded Priority Queue). A queue that is bounded to have a limited number of elements. +- [Bounded Priority Queue](Bounded%20Priority%20Queue). A queue that is bounded to have a limited number of elements. ### Trees -- [AVL Tree](AVL Tree/). A binary search tree that balances itself using rotations. -- [Red-Black Tree](Red-Black Tree/) -- [Threaded Binary Tree](Threaded Binary Tree/) -- [Ternary Search Tree](Ternary Search Tree/) +- [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 Tree/) +- [Radix Tree](Radix%20Tree/) ### Miscellaneous -- [Minimum Edit Distance](Minimum Edit Distance/). Measure the similarity of two strings by counting the number of operations required to transform one string into the other. +- [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 Cover (Unweighted)/) +- [Set Cover (Unweighted)](Set%20Cover%20(Unweighted)/) From bd35ff8f1bb984bf5cf5eeb8375539dfcdd248ad Mon Sep 17 00:00:00 2001 From: Hunter Maximillion Monk Date: Sat, 25 Mar 2017 21:57:12 -0500 Subject: [PATCH 0229/1039] Fix binary search tree link Just need to convert spaces into %20 for relative URLs with spaces to work. --- Binary Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Tree/README.markdown b/Binary Tree/README.markdown index 896116dda..8ce398804 100644 --- a/Binary Tree/README.markdown +++ b/Binary Tree/README.markdown @@ -8,7 +8,7 @@ The child nodes are usually called the *left* child and the *right* child. If a 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 Search Tree/). 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. +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))`: From eb68b1d69836d3d2d1bb1cba269466a94f837aea Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 26 Mar 2017 15:38:26 -0700 Subject: [PATCH 0230/1039] updated readme --- .../README.markdown | 459 +++++++++++++++++- .../Contents.swift | 2 + .../Sources/Matrix.swift | 180 ++++--- .../Sources/MatrixSize.swift | 19 +- .../Sources/Number.swift | 12 +- 5 files changed, 571 insertions(+), 101 deletions(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index d07004bad..e4222b4f4 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -1 +1,458 @@ -## TODO: Examples & Explanation +# 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| + |3 4| + + matrix B = |5 6| + |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 48| + +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/) \ No newline at end of file diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift index 50af60a6f..5d82244a3 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift @@ -8,9 +8,11 @@ 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) diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift index eba49ce9a..77ced4632 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift @@ -40,23 +40,26 @@ public struct Matrix { self.columns = size self.grid = Array(repeating: initialValue, count: rows * columns) } -} - -// MARK: - Public Functions - -public extension Matrix { - subscript(row: Int, column: Int) -> T { + + // 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 { + } set { assert(indexIsValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } - subscript(type: RowOrColumn, value: Int) -> [T] { + public subscript(type: RowOrColumn, value: Int) -> [T] { get { switch type { case .row: @@ -64,15 +67,11 @@ public extension Matrix { return Array(grid[(value * columns)..<(value * columns) + columns]) case .column: assert(indexIsValid(row: 0, column: value), "Index out of range") - var columns: [T] = [] - for row in 0.. T in + let currentColumnIndex = currentRow * columns + value + return grid[currentColumnIndex] } - return columns + return column } } set { switch type { @@ -90,59 +89,84 @@ public extension Matrix { } } - func strassenMatrixMultiply(by B: Matrix) -> Matrix { + // 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(of: n) + let m = nextPowerOfTwo(after: n) var APrep = Matrix(size: m) var BPrep = Matrix(size: m) - A.size.forEach { (i, j) in + A.forEach { (i, j) in APrep[i,j] = A[i,j] } - B.size.forEach { (i, j) in + 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.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.. Bool { - return row >= 0 && row < rows && column >= 0 && column < columns - } - func strassenR(by B: Matrix) -> Matrix { + private func strassenR(by B: Matrix) -> 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 } @@ -150,42 +174,49 @@ fileprivate extension Matrix { let n = A.rows let nBy2 = n / 2 - var a11 = Matrix(size: nBy2) - var a12 = Matrix(size: nBy2) - var a21 = Matrix(size: nBy2) - var a22 = Matrix(size: nBy2) - var b11 = Matrix(size: nBy2) - var b12 = Matrix(size: nBy2) - var b21 = Matrix(size: nBy2) - var b22 = Matrix(size: nBy2) + /* + 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 { + private func nextPowerOfTwo(after n: Int) -> Int { return Int(pow(2, ceil(log2(Double(n))))) } } - // Term-by-term Matrix Math extension Matrix: Addable { diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift index f4a604ade..e0d957607 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift @@ -8,26 +8,13 @@ import Foundation -public struct MatrixSize: Equatable { +public struct MatrixSize { let rows: Int let columns: Int - - public init(rows: Int, columns: Int) { - self.rows = rows - self.columns = columns - } - - public func forEach(_ body: (Int, Int) throws -> Void) rethrows { - for row in 0.. Bool { +extension MatrixSize: Equatable { + public static func ==(lhs: MatrixSize, rhs: MatrixSize) -> Bool { return lhs.columns == rhs.columns && lhs.rows == rhs.rows } } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift index 9f4c7f4ab..7da1eee60 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift @@ -22,21 +22,15 @@ public protocol Multipliable { } extension Int: Number { - public static var zero: Int { - return 0 - } + public static var zero: Int { return 0 } } extension Double: Number { - public static var zero: Double { - return 0.0 - } + public static var zero: Double { return 0.0 } } extension Float: Number { - public static var zero: Float { - return 0.0 - } + public static var zero: Float { return 0.0 } } extension Array where Element: Number { From c94fbab56dcd0b3f483ec8a1fec718de7ef97ba2 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 26 Mar 2017 15:53:58 -0700 Subject: [PATCH 0231/1039] added authorship to readme --- Strassen Matrix Multiplication/README.markdown | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index e4222b4f4..6949f906c 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -405,7 +405,6 @@ extension Matrix { } ``` - ## Appendix ### Number Protocol @@ -455,4 +454,6 @@ extension Array where Element: Number { + [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/) \ No newline at end of file ++ [Strassens Algorithm | Geeks for Geeks](http://www.geeksforgeeks.org/strassens-matrix-multiplication/) + +*Written for Swift Algorithm Club by Richard Ash* \ No newline at end of file From 09848a79e92c266b3e33006781732c1e288d7f6f Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 26 Mar 2017 15:55:13 -0700 Subject: [PATCH 0232/1039] fixed the display of the resources header --- Strassen Matrix Multiplication/README.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index 6949f906c..713ab1801 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -449,7 +449,8 @@ extension Array where Element: Number { } ``` -##Resources +## 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) From ab37359616c210f84363b885ef0308b17cadc202 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 26 Mar 2017 16:05:27 -0700 Subject: [PATCH 0233/1039] fixed layout of code in readme --- .../README.markdown | 142 +++++++++--------- 1 file changed, 75 insertions(+), 67 deletions(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index 713ab1801..fa822d310 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -11,17 +11,16 @@ Before we begin, you may ask what is matrix multiplication? Great question! It i ### Example: Matrix Multiplication - matrix A = |1 2| - |3 4| - - matrix B = |5 6| - |7 8| - - A * B = C +``` +matrix A = |1 2|, matrix B = |5 6| + |3 4| |7 8| - |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 48| +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 48| +``` + 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. @@ -66,14 +65,14 @@ Next, we loop over A's columns and B's rows. Because we know both A's columns & ```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) + 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.. Date: Mon, 27 Mar 2017 16:33:26 +0800 Subject: [PATCH 0234/1039] Delete SelectionSamplingExample.swift --- .../SelectionSamplingExample.swift | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 Selection Sampling/SelectionSamplingExample.swift diff --git a/Selection Sampling/SelectionSamplingExample.swift b/Selection Sampling/SelectionSamplingExample.swift deleted file mode 100644 index 66648a934..000000000 --- a/Selection Sampling/SelectionSamplingExample.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Select.swift -// -// -// Created by Cheer on 2017/3/9. -// -// - -import Foundation - -func select(from a: [T], count requested: Int) -> [T] { - - // if requested > a.count, will throw ==> fatal error: Index out of range - - if requested < a.count { - var arr = a - for i in 0.. the range is [0...n-1] - //So: arc4random_uniform(UInt32(arr.count - i - 2)) + (i + 1) ==> [0...arr.count - (i + 1) - 1] + (i + 1) ==> the range is [(i + 1)...arr.count - 1] - //Why start index is "(i + 1)"? Because in "swap(&A,&B)", if A's index == B's index, will throw a error: "swapping a location with itself is not supported" - - let nextIndex = Int(arc4random_uniform(UInt32(arr.count - i - 2))) + (i + 1) - swap(&arr[nextIndex], &arr[i]) - } - return Array(arr[0.. Date: Tue, 28 Mar 2017 15:54:51 +0800 Subject: [PATCH 0235/1039] Update ShellSortExample.swift fix code. And apologize for my carelessness. --- Shell Sort/ShellSortExample.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index c41eb8889..0beac00a3 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -14,18 +14,18 @@ public func shellSort(_ list : inout [Int]) while sublistCount > 0 { - for var index in 0.. arr[index + sublistCount]{ - swap(&arr[index], &arr[index + sublistCount]) + if list[index] > list[index + sublistCount]{ + swap(&list[index], &list[index + sublistCount]) } guard sublistCount == 1 && index > 0 else { continue } - - while arr[index - 1] > arr[index] && index - 1 > 0 { - swap(&arr[index - 1], &arr[index]) + + while list[index - 1] > list[index] && index - 1 > 0 { + swap(&list[index - 1], &list[index]) index -= 1 } } From 14fe78745ccceb2de88ed2a3dc05835d99317e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Tue, 28 Mar 2017 15:55:45 +0800 Subject: [PATCH 0236/1039] Update ShellSortExample.swift --- Shell Sort/ShellSortExample.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index 0beac00a3..05ab2518b 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -14,11 +14,11 @@ public func shellSort(_ list : inout [Int]) while sublistCount > 0 { - for var index in 0.. list[index + sublistCount]{ + if list[index] > list[index + sublistCount] { swap(&list[index], &list[index + sublistCount]) } From cf1561f885c414d8c4bb260cd21720c109468b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A9=98=E5=AD=90?= <726451484@qq.com> Date: Tue, 28 Mar 2017 15:56:26 +0800 Subject: [PATCH 0237/1039] Update ShellSortExample.swift --- Shell Sort/ShellSortExample.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index 05ab2518b..9174b935b 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -8,12 +8,10 @@ import Foundation -public func shellSort(_ list : inout [Int]) -{ +public func shellSort(_ list : inout [Int]) { var sublistCount = list.count / 2 - while sublistCount > 0 - { + while sublistCount > 0 { for var index in 0.. Date: Tue, 28 Mar 2017 20:01:36 -0700 Subject: [PATCH 0238/1039] Update How to Contribute link Super simple but just something I noticed while getting started. Cheers! --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 023f151fb..5e6cfbfe4 100644 --- a/README.markdown +++ b/README.markdown @@ -227,7 +227,7 @@ The Swift Algorithm Club was originally created by [Matthijs Hollemans](https:// It is now maintained by [Vincent Ngo](https://www.raywenderlich.com/u/jomoka) and [Kelvin Lau](https://github.com/kelvinlauKL). -The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/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](How to Contribute.markdown)? :] +The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/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](How%20to%20Contribute.markdown)? :] ## License From edee6981d7e77ff88186439b2536b8cc212354c5 Mon Sep 17 00:00:00 2001 From: Richard Date: Tue, 28 Mar 2017 21:31:33 -0700 Subject: [PATCH 0239/1039] =?UTF-8?q?updated=20syntax=20for=20Swift=203.1!?= =?UTF-8?q?=20=F0=9F=98=81=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contents.swift | 1 - .../Sources/Matrix.swift | 31 ++++++++++++------- .../Sources/MatrixSize.swift | 20 ------------ 3 files changed, 19 insertions(+), 33 deletions(-) delete mode 100644 Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift index 5d82244a3..9e11cb6a1 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Contents.swift @@ -1,5 +1,4 @@ //: Playground - noun: a place where people can play -// Reference - http://mathworld.wolfram.com/StrassenFormulas.html import Foundation diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift index 77ced4632..c13b3eeee 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift @@ -8,37 +8,44 @@ import Foundation -public enum RowOrColumn { - case row, column -} - 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 } - var size: MatrixSize { - return MatrixSize(rows: rows, columns: 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.rows = size - self.columns = size - self.grid = Array(repeating: initialValue, count: rows * columns) + self.init(rows: size, columns: size, initialValue: initialValue) } // MARK: - Private Functions @@ -59,7 +66,7 @@ public struct Matrix { } } - public subscript(type: RowOrColumn, value: Int) -> [T] { + public subscript(type: Matrix.Index, value: Int) -> [T] { get { switch type { case .row: diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift deleted file mode 100644 index e0d957607..000000000 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/MatrixSize.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// MatrixSize.swift -// -// -// Created by Richard Ash on 10/28/16. -// -// - -import Foundation - -public struct MatrixSize { - let rows: Int - let columns: Int -} - -extension MatrixSize: Equatable { - public static func ==(lhs: MatrixSize, rhs: MatrixSize) -> Bool { - return lhs.columns == rhs.columns && lhs.rows == rhs.rows - } -} From 4d1b9ff02cb46640b55f8b462be8d4536ca182bf Mon Sep 17 00:00:00 2001 From: Jim Rhoades Date: Wed, 29 Mar 2017 18:02:32 -0400 Subject: [PATCH 0240/1039] Update Big-O Notation.markdown Fixed the link to "merge sort". --- Big-O Notation.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Big-O Notation.markdown b/Big-O Notation.markdown index 09fbb04aa..746cba8a3 100644 --- a/Big-O Notation.markdown +++ b/Big-O Notation.markdown @@ -19,6 +19,6 @@ Big-O | Name | Description 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 Sort/), 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! +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. From 6d4a1eec73c92713e2e4e880b486694da545dbf9 Mon Sep 17 00:00:00 2001 From: darrellhz Date: Thu, 30 Mar 2017 14:30:01 +0900 Subject: [PATCH 0241/1039] Update README.markdown updated to swift 3 syntax --- Binary Search Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index a3a84c03d..b3b955c61 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -195,7 +195,7 @@ For convenience, let's add an init method that calls `insert()` for all the elem precondition(array.count > 0) self.init(value: array.first!) for v in array.dropFirst() { - insert(v, parent: self) + insert(value: v) } } ``` From da0be01444b4dfc2cdbd2259a3e5c524e9d37434 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Sat, 1 Apr 2017 14:29:56 -0700 Subject: [PATCH 0242/1039] Update README.markdown Hello, I have revised one of your documents for my assignment. I still need to revise more documents (10 in total). I hope it will be fine if I choose some documents from your account. Thanks, Parvaneh --- Heap/README.markdown | 116 +++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index 88ea25eeb..3935950a6 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -1,19 +1,19 @@ # Heap -A heap is a [binary tree](../Binary Tree/) that lives inside an array, so it doesn't use parent/child pointers. The tree is partially sorted according to something called the "heap property" that determines the order of the nodes in the tree. +A heap is a [binary tree](../Binary Tree/) inside an array, so it doesn't 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: -- For building [priority queues](../Priority Queue/). -- The heap is the data structure supporting [heap sort](../Heap Sort/). -- Heaps are fast for when you often need to compute the minimum (or maximum) element of a collection. -- Impressing your non-programmer friends. +- To build [priority queues](../Priority Queue/). +- To support [heap sorts](../Heap Sort/). +- 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*. They are identical, except that the order in which they store the tree nodes is opposite. +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 must always have a greater value than each of their children. For a min-heap it's the other way around: 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. +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: @@ -21,33 +21,33 @@ An example: 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. That is very useful because heaps are often used as a [priority queue](../Priority Queue/) where you want to quickly access the "most important" element. +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 Queue/)to access the "most important" element quickly. -> **Note:** You can't really say anything else about the sort order of the heap. For example, in a max-heap the maximum element is always at index 0 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. +> **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 heap compare to regular trees? +## How does a heap can be compared to regular trees? -A heap isn't intended to be a replacement for a binary search tree. But there are many similarities between the two and also some differences. Here are some of the bigger differences: +A heap is not a replacement for a binary search tree, and there are similarities and differnces between them. Here are some main differences: -**Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), the left child must always be smaller than its parent and the right child must be greater. This is not true for a heap. In max-heap both children must be smaller; in a min-heap they both must be greater. +**Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), 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; 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 Tree/) or [red-black tree](../Red-Black Tree/). But with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, and so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. +**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 Tree/) or [red-black tree](../Red-Black Tree/), 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.** Searching a binary tree is really fast -- that's its whole purpose. In a heap, searching is slow. The purpose of a heap is to always put the largest (or smallest) node at the front, and to allow relatively fast inserts and deletes. Searching isn't a top priority. +**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 that lived in an array +## The tree inside an array -An array may seem like an odd way to implement a tree-like structure but it is very efficient in both time and space. +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're going to store the tree from the above example: +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're 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. +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: @@ -69,7 +69,7 @@ Let's use these formulas on the example. Fill in the array index and we should g Verify for yourself that these array indices indeed correspond to the picture of the tree. -> **Note:** The root node `(10)` doesn't have a parent because `-1` is not a valid array index. Likewise, nodes `(2)`, `(5)`, and `(1)` don't 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. +> **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`: @@ -79,27 +79,27 @@ array[parent(i)] >= array[i] Verify that this heap property holds for the array from the example heap. -As you can see, these equations let us find the parent or child index for any node without the need for pointers. True, it's slightly more complicated than just dereferencing a pointer but that's the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. +As you can see, these equations allow us to find the parent or child index for any node without the need for pointers. It is 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's important to understand this relationship between array index and position in the tree. Here's a slightly larger heap, this tree has 15 nodes divided over four levels: +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 aren't the values of the nodes but the array indices that store the nodes! Those array indices correspond to the different levels of the tree like this: +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 always appear before child nodes in the array. You can see that in the above picture. +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’t start a new level unless the current lowest level is completely full. So heaps always have this kind of shape: +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:** Technically speaking you *could* emulate a regular binary tree with a heap, but it would waste a lot of space and you’d need some way to mark array indices as being empty. +> **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: @@ -111,15 +111,15 @@ Is this a valid heap? The answer is yes! A sorted array from low-to-high is a va 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 Sort/). +> **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 Sort/). ## More math! -In case you are curious, here are a few more formulas that describe certain properties of a heap. You don't need to know these by heart but they come in handy sometimes. Feel free to skip this section! +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. +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 and therefore has 4 levels: +This heap has height 3, so it has 4 levels: ![Large heap](Images/LargeHeap.png) @@ -145,31 +145,31 @@ There are two primitive operations necessary to make sure the heap is a valid ma Shifting up or down is a recursive procedure that takes **O(log n)** time. -The other operations are built on these primitives. They are: +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 that's 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".) +- `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()` except it lets you 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. +- `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".) +- `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 the most expensive thing they do. There are also a few operations that take more time: +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 aren't built for efficient searches but the `replace()` and `removeAtIndex()` operations require the array index of the node, so you need to find that index somehow. Time: **O(n)**. +- `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’re smart about this, it can be done in **O(n)** time. +- `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 Sort/). Since the heap is really an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** +- [Heap sort](../Heap Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** 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'll 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've been added to the queue. +> **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 insertion to see in more detail how this works. We'll insert the value `16` into this 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) @@ -185,13 +185,13 @@ This corresponds to the following tree: 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.) +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're going to swap `(16)` and `(2)`. +To restore the heap property, we are going to swap `(16)` and `(2)`. ![The heap before insertion](Images/Insert2.png) -We're 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. +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: @@ -199,7 +199,7 @@ Finally, we get: 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 doesn't slow it down.) +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 @@ -211,7 +211,7 @@ 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'll do the opposite: we're going to take the last object we have, stick it up on top of the tree, and restore the heap property. +When inserting, we put the new value at the end of the array. Here, we will do the opposite: we are going to 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) @@ -219,19 +219,19 @@ Let's look at how to **shift-down** `(1)`. To maintain the heap property for thi ![The last node goes to the root](Images/Remove3.png) -Keep shifting down until the node doesn't 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: +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 so it takes **O(log n)** time. +The time required for shifting all the way down is proportional to the height of the tree, so it 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'll be removing the object at the root of the heap because that's what heaps are designed for. +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 more general version of `remove()` and may involve either `shiftDown()` or `shiftUp()`. +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)`: @@ -241,13 +241,13 @@ 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're removing with the last element: +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'll return; we'll call `removeLast()` to remove it from the heap. The `(1)` is now out-of-order because it's smaller than its child, `(5)`, but sits higher in the tree. We call `shiftDown()` to repair this. +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: +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) @@ -267,7 +267,7 @@ In code it would look like this: } ``` -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. +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. @@ -286,9 +286,9 @@ Here, `elements` is the heap's own array. We walk backwards through this array, ## Searching the heap -Heaps aren't 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 somehow. Searching is one way to do this but it's kind of slow. +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 Search Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently and so a binary search won't work. You'll potentially have to look at every node in the tree. +In a [binary search tree](../Binary Search Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently, so a binary search will not work. You need to look at every node in the tree. Let's take our example heap again: @@ -296,9 +296,9 @@ Let's take our example heap again: 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. -But even though the heap property wasn't 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're looking for. +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 obviously not what we're 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's 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)`. +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. @@ -308,9 +308,9 @@ Despite this small optimization, searching is still an **O(n)** operation. 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've 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. +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've probably seen this before because it's also how Swift's `sort()` works. +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: From 52855ccbd3fb95704cd6375d44f1fa22512d04e1 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Sat, 1 Apr 2017 19:38:22 -0700 Subject: [PATCH 0243/1039] Update README.markdown For an assignment in technical writings, I have revised this document. Thanks, Parvaneh --- Hash Table/README.markdown | 69 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/Hash Table/README.markdown b/Hash Table/README.markdown index 4399b0f86..958c3595a 100644 --- a/Hash Table/README.markdown +++ b/Hash Table/README.markdown @@ -2,13 +2,13 @@ A hash table allows you to store and retrieve objects by a "key". -Also called dictionary, map, associative array. There are other ways to implement these, such as with a tree or even a plain array, but hash table is the most common. +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, just like the one you'll learn about here. +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 -At its most basic, 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, like so: +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" @@ -48,33 +48,33 @@ hashTable["hobbies"] = "Programming Swift" +--------------+ ``` -The trick is in how the hash table calculates those array indices. That's where the hashing comes in. When you write, +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. That's why keys must be `Hashable`. +the hash table takes the key `"firstName"` and asks it for its `hashValue` property. Hence, keys must be `Hashable`. -When you do `"firstName".hashValue`, it returns a big integer: -4799450059917011053. Likewise, `"hobbies".hashValue` has the hash value 4799450060928805186. (The values you see may vary.) +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.) -Of course, these numbers are way too big to be used as indices into our array. One of them is even negative! A common way to make these big numbers more suitable is to first make the hash positive and then take the modulo with the array size. +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 for yourself that the array index for `"hobbies"` is 1. +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 so efficient: to find an element in the hash table you only have to 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)**. +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:** As you can see, it's hard to predict where in the array your objects end up. That's why dictionaries do not guarantee any particular order of the elements in the hash table. +> **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 very large array. That 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 some way to handle them. +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 so small it's easy to show a collision. For example, the array index for the key `"lastName"` is also 3. That's a problem, as we don't want to overwrite the value that's already at this array index. +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. -There are a few ways to handle collisions. A common one is to use chaining. The array now looks as follows: +A common way to handle collisions is to use chaining. The array looks as follows: ```swift buckets: @@ -91,25 +91,25 @@ There are a few ways to handle collisions. A common one is to use chaining. The +-----+ ``` -With chaining, keys and their values are not stored directly in the array. Instead, each array element is really a list of zero or more key/value pairs. The array elements are usually called the *buckets* and the lists are called the *chains*. So here we have 5 buckets and two of these buckets have chains. The other three buckets are empty. +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 now write the following to retrieve an item from the hash table, +If we write the following statement to retrieve an item from the hash table, ```swift let x = hashTable["lastName"] ``` -then this first hashes the key `"lastName"` to calculate the array index, which is 3. Bucket 3 has a chain, so we step through that list to find the value with the key `"lastName"`. That is done by comparing the keys, so here that involves a string comparison. The hash table sees that this key belongs to the last item in the chain and returns the corresponding value, `"Jobs"`. +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. Technically speaking the order of the items in the chain doesn't matter, so you also 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.) +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.) -It's important that chains do not become too long or looking up items in the hash table becomes really slow. 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 and by using high-quality hash functions. +Chains should not become long becasuse the slow process of looking up items in the hash table. 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. Of course, this approach has its own upsides and downsides. +> **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'll build it up step-by-step. +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 { @@ -127,9 +127,9 @@ public struct HashTable { } ``` -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 use in a chain and `Bucket` is an array of such `Elements`. +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 useing 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're also keeping track of how many items have been added to the hash table using the `count` variable. +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: @@ -137,7 +137,7 @@ An example of how to create a new hash table object: var hashTable = HashTable(capacity: 5) ``` -Currently the hash table doesn't do anything yet, so let's add the remaining functionality. First, add a helper method that calculates the array index for a given key: +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 { @@ -145,9 +145,9 @@ Currently the hash table doesn't do anything yet, so let's add the remaining fun } ``` -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've put this in a function of its own because it gets used in a few different places. +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'll do with a hash table or dictionary: +There are four common things you will do with a hash table or dictionary: - insert a new element - look up an element @@ -180,7 +180,7 @@ We can do all these things with a `subscript` function: } ``` -This calls three helper functions to do the actual work. Let's take a look at `value(forKey:)` first, which retrieves an object from the hash table. +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? { @@ -193,10 +193,9 @@ This calls three helper functions to do the actual work. Let's take a look at `v 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`. -First it calls `index(forKey:)` to convert the key into an array index. That gives us the bucket number, but if there were collisions this bucket may be used by more than one key. So `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:)`. It's a little bit more complicated: +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? { @@ -218,9 +217,9 @@ The code to insert a new element or update an existing element lives in `updateV } ``` -Again, the first thing we do is 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, it means 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. +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's important that chains are kept short (by making the hash table large enough). Otherwise, you spend a lot of time in these `for`...`in` loops and the performance of the hash table will no longer be **O(1)** but more like **O(n)**. +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: @@ -246,16 +245,16 @@ Try this stuff out in a playground. It should work just like a standard Swift `D ## Resizing the hash table -This version of `HashTable` always uses an array of a fixed size or capacity. That's fine if you've got a good idea of many items you'll be storing in the hash table. For the capacity, choose a prime number that is greater than the maximum number of items you expect to store and you're good to go. +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 too small and the chains are long, the load factor can become greater than 1. That's not a good idea. +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 too high, say > 75%, you can resize the hash table. Adding the code for this 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! To account for this, you'll have to insert all the elements again after resizing the array. +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 fun to integrate it better with the Swift standard library by making it a `SequenceType`, for example. +`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* From 7010d4ff4e28871cd06067aad15dcde031e745c8 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Sun, 2 Apr 2017 18:28:48 -0400 Subject: [PATCH 0244/1039] Fixed an issue with links that has spaces in the address --- Graph/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index 1ff1a82ac..a2531e808 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -28,7 +28,7 @@ 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 List/). Both can be considered graphs, but in a simpler form. After all, they have vertices (nodes) and edges (links). +On the left is a [tree](../Tree/) structure, on the right a [linked list](../Linked%20List/). Both can be considered graphs, but in a simpler form. After all, they have vertices (nodes) and edges (links). The very first graph I showed you contained *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. @@ -42,7 +42,7 @@ Like a tree this does not have any cycles in it (no matter where you start, ther Maybe you're shrugging your shoulders and thinking, what's the big deal? Well, it turns out that graphs are an extremely useful data structure. -If you have some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, then you can draw your problem as a graph and use well-known graph algorithms such as [breadth-first search](../Breadth-First Search/) or [depth-first search](../Depth-First Search) to find a solution. +If you have some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, 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, let's say 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: @@ -50,7 +50,7 @@ For example, let's say you have a list of tasks where some tasks have to wait on Each vertex represents a task. Here, an edge between two vertices means that the source task must be completed before the destination task can start. So 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 Sort/). 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.) +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're 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 "relationship". From 79255d2bb83cfbbcab0fb3f983bdc96e25c0bd4b Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Sun, 2 Apr 2017 19:43:48 -0400 Subject: [PATCH 0245/1039] Fixed white-space encoding in markdown links --- Heap/README.markdown | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index 88ea25eeb..1bcb05e1b 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -1,11 +1,11 @@ # Heap -A heap is a [binary tree](../Binary Tree/) that lives inside an array, so it doesn't use parent/child pointers. The tree is partially sorted according to something called the "heap property" that determines the order of the nodes in the tree. +A heap is a [binary tree](../Binary%20Tree/) that lives inside an array, so it doesn't use parent/child pointers. The tree is partially sorted according to something called the "heap property" that determines the order of the nodes in the tree. Common uses for heap: -- For building [priority queues](../Priority Queue/). -- The heap is the data structure supporting [heap sort](../Heap Sort/). +- For building [priority queues](../Priority%20Queue/). +- The heap is the data structure supporting [heap sort](../Heap%20Sort/). - Heaps are fast for when you often need to compute the minimum (or maximum) element of a collection. - Impressing your non-programmer friends. @@ -21,7 +21,7 @@ An example: 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. That is very useful because heaps are often used as a [priority queue](../Priority Queue/) where you want to quickly access the "most important" element. +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. That is very useful because heaps are often used as a [priority queue](../Priority%20Queue/) where you want to quickly access the "most important" element. > **Note:** You can't really say anything else about the sort order of the heap. For example, in a max-heap the maximum element is always at index 0 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. @@ -29,11 +29,11 @@ As a result of this heap property, a max-heap always stores its largest item at A heap isn't intended to be a replacement for a binary search tree. But there are many similarities between the two and also some differences. Here are some of the bigger differences: -**Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), the left child must always be smaller than its parent and the right child must be greater. This is not true for a heap. In max-heap both children must be smaller; in a min-heap they both must be greater. +**Order of the nodes.** In a [binary search tree (BST)](../Binary%20Search%20Tree/), the left child must always be smaller than its parent and the right child must be greater. This is not true for a heap. In max-heap both children must be smaller; 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 Tree/) or [red-black tree](../Red-Black Tree/). But with heaps we don't actually need the entire tree to be sorted. We just want the heap property to be fulfilled, and so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. +**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, and so balancing isn't an issue. Because of the way the heap is structured, heaps can guarantee **O(log n)** performance. **Searching.** Searching a binary tree is really fast -- that's its whole purpose. In a heap, searching is slow. The purpose of a heap is to always put the largest (or smallest) node at the front, and to allow relatively fast inserts and deletes. Searching isn't a top priority. @@ -54,7 +54,7 @@ If `i` is the index of a node, then the following formulas give the array indice 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: @@ -63,7 +63,7 @@ Let's use these formulas on the example. Fill in the array index and we should g |------|-------------|--------------|------------|-------------| | 10 | 0 | -1 | 1 | 2 | | 7 | 1 | 0 | 3 | 4 | -| 2 | 2 | 0 | 5 | 6 | +| 2 | 2 | 0 | 5 | 6 | | 5 | 3 | 1 | 7 | 8 | | 1 | 4 | 1 | 9 | 10 | @@ -76,7 +76,7 @@ Recall that in a max-heap, the parent's value is always greater than (or equal t ```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 let us find the parent or child index for any node without the need for pointers. True, it's slightly more complicated than just dereferencing a pointer but that's the tradeoff: we save memory space but pay with extra computations. Fortunately, the computations are fast and only take **O(1)** time. @@ -104,14 +104,14 @@ You can’t start a new level unless the current lowest level is completely full 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 Sort/). +> **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! @@ -129,7 +129,7 @@ If the lowest level is completely full, then that level contains *2^h* nodes. Th 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. +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. ;-) @@ -141,7 +141,7 @@ There are two primitive operations necessary to make sure the heap is a valid ma - `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". +- `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. @@ -161,7 +161,7 @@ All of the above take time **O(log n)** because shifting up or down is the most - `buildHeap(array)`: Converts an (unsorted) array into a heap by repeatedly calling `insert()`. If you’re smart about this, it can be done in **O(n)** time. -- [Heap sort](../Heap Sort/). Since the heap is really an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** +- [Heap sort](../Heap%20Sort/). Since the heap is really an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg 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)**. @@ -187,7 +187,7 @@ 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're going to swap `(16)` and `(2)`. +To restore the heap property, we're going to swap `(16)` and `(2)`. ![The heap before insertion](Images/Insert2.png) @@ -211,7 +211,7 @@ 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'll do the opposite: we're going to take the last object we have, stick it up on top of the tree, and restore the heap property. +When inserting, we put the new value at the end of the array. Here, we'll do the opposite: we're going to 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) @@ -223,7 +223,7 @@ Keep shifting down until the node doesn't have any children or it is larger than ![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 so it takes **O(log n)** time. +The time required for shifting all the way down is proportional to the height of the tree so it 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. @@ -269,7 +269,7 @@ In code it would look like this: 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. +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: @@ -288,7 +288,7 @@ Here, `elements` is the heap's own array. We walk backwards through this array, Heaps aren't 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 somehow. Searching is one way to do this but it's kind of slow. -In a [binary search tree](../Binary Search Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently and so a binary search won't work. You'll potentially have to look at every node in the tree. +In a [binary search tree](../Binary%20Search%20Tree/) you can depend on the order of the nodes to guarantee a fast search. A heap orders its nodes differently and so a binary search won't work. You'll potentially have to look at every node in the tree. Let's take our example heap again: @@ -302,7 +302,7 @@ Let's say we want to see if the heap contains the value `8` (it doesn't). We sta Despite this small optimization, searching is still an **O(n)** operation. -> **Note:** There is away 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 Queue/) that's built on a heap. +> **Note:** There is away 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 From bdb1b157cc2698b3e211069475399ef19958261e Mon Sep 17 00:00:00 2001 From: Jacopo Date: Mon, 3 Apr 2017 21:26:14 +0100 Subject: [PATCH 0246/1039] Minimum Coin Change Problem - Dynamic Programming in Swift --- MinimumCoinChange/LICENSE | 201 ++++++++++++++++++ MinimumCoinChange/Package.swift | 7 + MinimumCoinChange/README.md | 41 ++++ .../Sources/MinimumCoinChange.swift | 76 +++++++ MinimumCoinChange/Tests/LinuxMain.swift | 6 + .../MinimumCoinChangeTests.swift | 21 ++ MinimumCoinChange/eurocoins.gif | Bin 0 -> 90051 bytes 7 files changed, 352 insertions(+) create mode 100755 MinimumCoinChange/LICENSE create mode 100644 MinimumCoinChange/Package.swift create mode 100755 MinimumCoinChange/README.md create mode 100644 MinimumCoinChange/Sources/MinimumCoinChange.swift create mode 100644 MinimumCoinChange/Tests/LinuxMain.swift create mode 100644 MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift create mode 100644 MinimumCoinChange/eurocoins.gif diff --git a/MinimumCoinChange/LICENSE b/MinimumCoinChange/LICENSE new file mode 100755 index 000000000..8dada3eda --- /dev/null +++ b/MinimumCoinChange/LICENSE @@ -0,0 +1,201 @@ + 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. diff --git a/MinimumCoinChange/Package.swift b/MinimumCoinChange/Package.swift new file mode 100644 index 000000000..749073782 --- /dev/null +++ b/MinimumCoinChange/Package.swift @@ -0,0 +1,7 @@ +// swift-tools-version:3.1 + +import PackageDescription + +let package = Package( + name: "MinimumCoinChange" +) diff --git a/MinimumCoinChange/README.md b/MinimumCoinChange/README.md new file mode 100755 index 000000000..c9cd71cd1 --- /dev/null +++ b/MinimumCoinChange/README.md @@ -0,0 +1,41 @@ +# 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. + diff --git a/MinimumCoinChange/Sources/MinimumCoinChange.swift b/MinimumCoinChange/Sources/MinimumCoinChange.swift new file mode 100644 index 000000000..db7edecbe --- /dev/null +++ b/MinimumCoinChange/Sources/MinimumCoinChange.swift @@ -0,0 +1,76 @@ +// +// Minimum Coin Change Problem +// Compare Greedy Algorithm and Dynamic Programming Algorithm in Swift +// +// Created by Jacopo Mangiavacchi on 04/03/17. +// + +import Foundation + +public struct MinimumCoinChange { + private let sortedCoinSet: [Int] + private var cache: [Int : [Int]] + + public init(coinSet: [Int]) { + self.sortedCoinSet = coinSet.sorted(by: { $0 > $1} ) + self.cache = [:] + } + + //Greedy Algorithm + public func changeGreedy(_ value: Int) -> [Int] { + var change: [Int] = [] + var newValue = value + + for coin in sortedCoinSet { + while newValue - coin >= 0 { + change.append(coin) + newValue -= coin + } + + if newValue == 0 { + break + } + } + + return change + } + + //Dynamic Programming Algorithm + public mutating func changeDynamic(_ value: Int) -> [Int] { + if value <= 0 { + return [] + } + + if let cached = cache[value] { + return cached + } + + var change: [Int] = [] + + var potentialChangeArray: [[Int]] = [] + + for coin in sortedCoinSet { + if value - coin >= 0 { + var potentialChange: [Int] = [] + potentialChange.append(coin) + let newPotentialValue = value - coin + + if value > 0 { + potentialChange.append(contentsOf: changeDynamic(newPotentialValue)) + } + + //print("value: \(value) coin: \(coin) potentialChange: \(potentialChange)") + potentialChangeArray.append(potentialChange) + } + } + + if potentialChangeArray.count > 0 { + let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) + change = sortedPotentialChangeArray[0] + } + + cache[value] = change + return change + } +} + diff --git a/MinimumCoinChange/Tests/LinuxMain.swift b/MinimumCoinChange/Tests/LinuxMain.swift new file mode 100644 index 000000000..db61c6011 --- /dev/null +++ b/MinimumCoinChange/Tests/LinuxMain.swift @@ -0,0 +1,6 @@ +import XCTest +@testable import MinimumCoinChangeTests + +XCTMain([ + testCase(MinimumCoinChangeTests.allTests), +]) diff --git a/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift b/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift new file mode 100644 index 000000000..86c9007ba --- /dev/null +++ b/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift @@ -0,0 +1,21 @@ +import XCTest +@testable import MinimumCoinChange + +class MinimumCoinChangeTests: XCTestCase { + func testExample() { + var mcc = MinimumCoinChange(coinSet: [1, 2, 5, 10, 20, 25]) + + for i in 0..<100 { + let greedy = mcc.changeGreedy(i) + let dynamic = mcc.changeDynamic(i) + + if greedy.count != dynamic.count { + print("\(i): greedy = \(greedy) dynamic = \(dynamic)") + } + } + } + + static var allTests = [ + ("testExample", testExample), + ] +} diff --git a/MinimumCoinChange/eurocoins.gif b/MinimumCoinChange/eurocoins.gif new file mode 100644 index 0000000000000000000000000000000000000000..2d9e81e559071eb0b63dc82d35801e5809447612 GIT binary patch literal 90051 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

CP-d(QUGY&)`KEg`5L-~O% zJZKpT&p!R|I|PS(j#J6ykc-lE5l}|A4>qY%^e}*TE3GMB(U%1ZZ~(Z0xSzR*5Ebe2 z$(qY`y*^!KvN}ijl<5pRh(0UL!fZTgRi+-Zb^-sg6?bsDgO7=fj_ab)&HCy{^#fY ze=hXKkbx&_@=cM3scz%}3GM)f0);X!>we%re>WiEgN$-T9(fPod6(WQE&7myijI11 z=YVk?i*m&d*ulbgHYZF9rt-L9Pn^Ds)p z=4>{ms`_?dLSI?7V+hw{-z9{w4k7#OpVTbu86VaEPJ0GdN#PjJ^H`8eXD9)c&+2P$d@a@eSuJcvYq z<3gL>%2UTbmAZ+x3s?Ec%lEyks71T3?BIaOS|1iDyl`4K%Q`U%e`pXNaARcJPhMu2)6}Jt&g|Q#7l0#WP;^v;(8CkY$bn>>`sDG~=i*+emkP064 z(!cI}z3|M(XPX}k$-B$CN!Kv`LEHY8A%&bDqa6rE^(SF$(2oTojh?{&p7y%^rWgIM3Y^LXgR{H?a<8fyI-QpJMMbMUu*arMWw>i(xa#` z-z`*jChknEy_l$3-9V;jeQ8##~Jw~`@Gof;aTn8 ze=z^}S;yVq%w9Q~7J@bUL6kviA+qvzz9vUy2@WS2!FO-j=Jn9^@S9dft@x zNcd(v?zJ%wHf;`Z-FvSL|G}$~aOQ)}?>nJq2sD>OXB+9N@P4bJEIk2RR9am**1Lzj z%Eeg}J&xty(Irbbh)HQa0TfedJ$Ccn9xEkP2TUn!KCn_UQZ?IV(`b2#yc@S2|Dbtf z<<~uBk$?w;tk0`Oa24P6-s+=FFBKV`u4WES%MTo!v!;1VqRo^U?fgVXOaR|H%SyduJoe)j{O$QT>Gd{J)q zRtu9mvB-mgF~xnF-e|oNhLZR2w2LY=G1BF<5Jv2#U=_j~hg<1!<<<1vQvg}%4-7p} zuA~E!4G0NYjH0PmtRFD`KtReiXH3B061{Fpam3~WO4x1>?uc0W#SORkXsrA=Mx}0r zi0i$q-VHY~$08)Ge{4YTC_a75>B{{}JJR_g0LV{yV zGw5Rw0sUCj^j}4`o2sTB+f_C&ppC1R_G96w)q9Q^URm=Q50u==QKxdn`T^R=&k#}x zLiC3EDh@dM!&zom$VibKnc=>Fg1iPik~!d-;dL?;-BL_8$RdnZSzJcQ-`#$_`gM8G z-e?SKE-YE`l=g=SiEZxu66I3AU*9E~?$3v= z$Ohm?aMqYn81_uR)YgvkH4VSwFGid5Co#lfHbFL>@IPBtGvk9Yk+`y+lHe{qE@u2g z)C1nG`My}*B0YsG8mfi$%p~m>%M*-75?$)d6EQLshs&2<cS4NTNt2}`$&LMwetmr-iux$YYd`#6iIA52awoD z8KhOWfLoNs0)+WB=B?0mRQ9RWm0Nl?^S9F z5D9w)*is5%ofRZyEfWzpmlbh(JNQ~J1+<;N44JTxWh4raAO9q0)m>~ia3`7X&+3M6 zV>6_yTrOW8<^hgWCxuN0Qt~1d=@){(`3@=Z@5zTMh6*D>P2?@iARH+c&-x|$1S}RR zy78jbjt&%T8V;TRmwVQ%nt@nLk*IZ85{< z!4g!f;cl8`EMBdOW78qiDWc@%Q!HhbV!yhf6=W^E(2M-4#JZW3W@PWI z}gmdTN0(g$#u^2z3M81&`T+e%^ILHS)y*1DzYm#@Htq4?CAW_QM zt6a}F5am+iYkS*6AO31@e#J+#`C6c*KuobN!P}hqQ0+;p<)8mnw4S~^bMq6@Ax)4f zn$3;2$t(x=e%ow7rj5uA=xK<-q7aU;1xEKR}R(Bm!!&e{G-*I3e zIi-Fr$3T4Whk_HSk=c{}F*28RT=LbJbS+`N0gU>05^-; zoV@bf>;nVwzEG-&pIex8HDZhJHSsPI_Med7>+l;sBO!y&XE9{o$vX&f6e3nXxcisz z4&rQm15+;sHf+u4324(F%M?qxU;Z@x$h6#UV$H5^#4YC8qmh2jO1v zmrd`rcbIG8x7z^f=*r$wgx2>tOD)5=mK&wLJ8@+z$W(=yyWpV{4N;DZuybe;q}c-o zOqwv_`StF8dsYjk=k>o{EdaQ^@e|VHQpUxZ^*O1Ak&fstad_Fy5HJ&p6a9j&fde>xoy;=AX$FCHKPYk>t@!vUrHKX=vE3oUet*6yR;_wT1Y$N*)jKbE%Eo6el$m3w`0?&cXp_<9?$W;Nw!Wzh7n-@#!f z>XdeEGmHA2)avjS%lOPx=@$ge7dS|px=*pgh0KO72f@g)2`LL!#`HtCg3z!`rQhSQ zWG>R0pp;5h8B>Q9^RjMlBw8ZDVVeK26!L5RFj*5GOn;t6pBTVvQ1US3 z=qdS>UtGYEjYKjO$iS{J0DC+G4$XlR4KO2uw15bR6d=Qhu%J?%7f$e40(9Q(h$zwW zP3e&gOCP&AO}VHov!#^Xs(1F>{EEE&6)}>L@4P_z^=9X8cHCA#M$LqYsehb#e_HK< zNWC`|8!m8nxa_a_SX==mE~UhqW%8vOWyA+DYr7Ptz=LfrI9|c&7XR~eRyTtRf4{QL zoZN3M+$_r-%JWyLm1pkOI&@4r@$)Ms9RM^TA}^+b0R)w&nb1cClnKEyhGw3gtv=Osm9t@f@`PF+ca;m~~4NBbDHLMFtxMxO1xs-)FjQ2m1T|_b$hLF z<&o?y;W@e7IlV-6+EhBgr~lOvQlXh`npS&bTw#61_ki@MMk!q|))!Va2@if=sNo8O zC!7FeXN4_&^Pl}%R{bVt+7Y3QNL41~(5qefY@{d!G;T$1wo0cKAY<9cH^opW{^(^0 zdD+=-q4DUg31BhnP%;(PBDKANzF(Sk$e5+H)p#fxt2|zq)MMgK!Z(dah*SZ}(FF8T z|8|BJ`l|xmgkW1pfk@iPx1>;MX~os^IavK>tvWL_ugs(Xa7zmtaK-$Jks+|;w!N*! zE7pw2m(J9o>Z9{^L1Dfnl2N>Zq5@ZAKs}1v@I;vI%7mZkGxq0}YU5!(Zd(!>bhtJf zE1VWR=+)XIBWKQssjL_oaKYCLbw1hBl(&W-7n=V)w@q&jR+5Ra6r`Om%kLhH^ruNd z)QqQ2b;;M$kFDpM1EQXf&aOn%pH4@lUJnZ88cH_84}HZP4n<}Yr1KdF11^GC@2L{$jm;BlL(TmLo1SmQMp-pc?a)N~@lG-r9mDq-ifDUg02CPO$ zQRLCjRJ-W*>k!g~QkX+T`rx+LI&V*k>eveF2(9SYGjzO1AFcTWdY~>cNCWS$Ak$gN zGbEIdFVZyt`xk1aU+D3qp$IHMk1Urw9Uf^N46$>s{Hi`ORB|<-tFR9^>)NGr-dit@ zQ2a>I6c0D!llMJ zNG$7|SdQ5{bFCZEEgli7xC<56b1*k%Vr5&j2N*yc1-BF!2~Ur!?Kiw=Ky?-NQ(Wmn_~{_P`I zD59K}9h`bB6~lnvhq+%_5`GKps_4+-g!^7TG9t`Cm+PL;1Z=H!D*x{M;s$#?;^CTB zy?3Q~k^`Te&b>)K%|Ub-dU>hg!GCJK5?Rq}p#+($ibW&9PrQk=v*Yswq$Zep=L<@B zmyyT=O?KePmA#&)u;nRR8DwmqJE70|-360|BWbKYS@RQnPmz}AVrU7NlLr9Y%!yAp ziU=EFEw^{+YtQo6-P5)8F(W~iF>rI9{0YeE;B{D@m$t{kNM#B$CtAhczCeTe&3 z55a9JknTL)HTk1;zb`lBUdf?eIrJS2W`Q|xuD45fT$3AeuIlJGl~jr|2w#S-RT@nB zLF#gFITmLs6=bd{%XWigMo;L}jZwwiiRpp()@H3eMwUG1xg}!!p!h%Z19Q1iT0dci z{0T5J`l*<@F;-ur6|$|AeC{Rr{3$}3;aF<{)@PhoV|ytIu?0e+F%KLII17ymW0I)G zUyK1dVoPM}P9Pn%v3em!Z=ZIx^zR#e@;KbPcA0(wdz(v%4M%lPTI*(%>GH-VIw1`X+Kb~$8 z_0?gfFEzsxy6pa=!lT+5JCA+meO^9g3cNEcKk!_Vwlm zOxD;yOUKr)!d7^4(|2goAm^Ric)v2-Nw4z=7HN$SILJrtWy4YYw#XAbh`l`D)_Yi( zOq>AwW{mf`W`1&qF0tQKb0c@lclLVkX-H}k?KCOb;Go2EECbI=M9it^nix_*Pdehq zXV~x;m=TMPphv4wraf}2te>~eyK1`=pd^2!HXE>_-#)45L%ziB{IGS~S_YuLpTEO6 zxSO7T+cw|t8YZDQ?ttID$w=+URHvp+24zLe$3HUp57n?dSvUM6*TO<}?kB2x z-m27hsrXbNl{{A$a16Em?o-IBCKY`%+z7uafN2xJ%x1}R*Yr&Rq(40qM^*o`Pg3W< zt8#_jpE-a{=+yKWJtwv5UO4Ek?08thX==#RfY290kSD~fr}4n$=Jn3ub@6w*!9)yx zzFW4bd%XLfX@=@jv<^N>DrtHkp;e(t?%mXkymDScbjp_bEl#>QE6%M=xPP4gC9!Ad zJ|b(j;ZU(-pa3}EyP)wLmLR{{@cVt{BoH8!CknYuRg0u&tH+)%cFyh?Zs|C+0CkT( zOo;)ncE7A(xo<8ad*Vc75@15D+OCG>71e_;|L!q+VzMU*ZYn5GdknMJk^l7f)AqX) z_m#U|^QSb}RYrXK7d%j(0=`gGHzvTN7TjsIPM;P_3arkvrCjch_od^f4!hAnO zsA*S0$^beKy^UgON-Qg{sH{-QDN|9YjF$7V#+aQnt5#_`a}v|i+ScA$?JE&OI(V?L zD=A&~DhU%6uy>#RkbQ!2f&^YJX;{}66P*<9`RTLgFBV*2 zmbo|_nm|C~;w<;`G6fr%pFV!tZ)xY4P0jl6ZdPS+^DFdv! zkd{y+B6*Cr*>-&LIDY>hit~X|B?Esp(6brY?#aTRnyRyD9jlX6b9?rK+9BeC6PF*F z%6>V4KJ9uC8$URiOHcb< z%J4+0E@NjdkE*rKP`~^SJ^7W$8M5&unlhpF(-ISZpDh7tc$M_%k_xZe=zVC(bD1u& zhj`JQ^s(?lgHSye!~3X8P!9Q*A-+T7o*F31d&V_$8aa)U>_wBVjhLKts;bdl_>7*? zan0#cDU*3soAJKm>T%m*IO-BbWuG;p?{(4Hpy=dR%Y74)a8yb3A zIt-(n;qm!C10fg7XRK5?!^C%Uc_XU#=gky$W-T!#Wq$vGvxso103J!CM+)ccXg}}d zs%k40;iMLu!jvV9d>P$BTYY35N2qxSm!l+C5;h{7VGS&T<^zAQl~nY_2Ro#s$I=&@Px3q+%>j~oN~xXKs@gm>y#XV zK|>_ba4kqB(GQyOBHSLrGpUKMdgZBuU`wf1v!2s5Okz0YIme7}t~9fQe$G?xWZ4_Q zWdvwHWGKj$8D_mQwt7^N4ckKE6}M_Nz1&+NV#T>5gfPYV$D8>m`aAvNoJ12uOVy z4+V_2X!7E7EyC#VQQhf^(qiXaEPsR-KM)QAO zebqVSqQG)Ptvo9Z25pEpbx+GUERNWJTu%szUEev&j;bbw$;Laie{(^_|2lsjoAf<6 z)F!otxhy5}%w}9|^rWwog4|JUkROXz-=lDu25SZ*y)TSB?SFltS(Ejw0u7%_NdbGt zm39pEOf|KV6|FDMit3oLSBdbeE<0f8`LL%iL?q_S2@GfXa1}P#mVf#8 zr>)I<15fK=A{Uv*_K|n?{QI@^c^f3Ne^v(@icm`@m1$o7^Jqf!cpyPJ?HPA=Ow~l- zT%)8jG`%DBHYf}N6TP9W#2~=shE&L?T~?T_wbnX_8nWNHD_2A zkE2I3K5j5S5P3*j&ZNCHKgcNgTxIaZ6@|UR*j|7z@Y|)YblFCrv&|5hfMq!dYH+w3t!$bjG z=;#!nxuf}_?k-^>i9Xj}Z+#v>SkI_!Vy}q~)dD^q&JqsV=Vj6AMVbaHjXq_gxHBDb zN%1sbdtigg&`Xir>*@>d5SDN}*RP(oRK=dzAs5$tt?uo~Uqc^J% zp;vKYj@V=n;tC5yFN=>dN)M}w$3=UnE8c<@8T|q=hdOoVkJaaQCW)6~T&tEGq7^k} z{4BthG{5ORqL zzeXigFob-xmh0+{5a*hrLS#G389|$E(CT0Mary(Y{XewgJZsOqCqF8R%CNlo6TG-O zCVoIm*Y2o!G1^Dq@#&8R_n4Dx!{iVPUEAq8qkJ_nmce@t1u$o8a(jtJrfJ>6;u?X+)DXJ z!A?Sfn_KFedm4>(?A@%>u6m<>!jh}Qx_7aL(Pjy>_}8`Jr}bx(y&zEX%ikP5hQC5Hbai+?XeYu6X4dQ)NB5wPdWFr<2*WQA$- zh{8QvNJ5GGIA|C^C2U++M0T!P%h6;GoT)eH^%hxB7rx>+DQ$C2@JRUE8#B zPFR{Qc9Q>3&xH)!`ntzUK0M$}`dKGgccPVgUHH|443D;q)0TT5BPClQT>=%jSQ35Y zs$y&mWk1KcqFUdVw6!mU2^?&bFP_wYK=)!@#Vf9Rdg2kD9Qh%gtOL&QGd=h((SE9U zHzx+-u7$Eg%=Z6?Num%rH2`U^X~PsG<>8Va__{w(hlK;+S!Rx2X2frQD4HnN`dJv@ z%JHSD-FgX}N;e#C@EGJpI`l&hnGl|fl%seI(ZL)nVw$7YF_!o6dnr#>;vH8n4V4g@ z8UK6LSaCD!`FAgF9rl>EH*qD-hd@B8gP%Ubcd?J0(stBY@eZSa!fB@&AT36OzAb2x z8e$Q={Ct`4-zbt5h2+|UyYrk8zDozOe+(DO}4n%f<1)=9M)LV7-mu4Q>%urd^ z6$iI6lWUx#WAuH-NFips4@X+Q;Na&05`hC@& zHd?0krffv3e5DS1BDTD7O6t^9xxg865Lnv4vZQi7YWSFYFOmigq2nUndcyM6c z$Hd=Foxq6x0=wNuMG#2=t!66oinaYk2rP7NGdxPYzzD0cx1p-FGbP??%aXAG<27c+ ze@9A6%brMesWg!cEV3LUmBsqMc(0xiF3tBylogZN&*W<9|AC~QAUbq7J=G!Qp$TuZJ)X1 z)6cT|4wSDxs?|hEiI9%yqDpjTY`X}_?E}A(Jokkl`yuhkGhqkI{k$dy}yrLHx9}?8_MWQvM zEpHrvXUAB2_rlg!kLqtfcKmu<-H1!GpVF}nCr`ot)26#M=^;3pxi=g4eqM6lh_xs+ zTND6PDJsto?6_I8;~oj&pS9y45oybZ2Ftg#0nNdI?$w+fHx!YPAy9M{NaCYz^8smM zHJ2TzLj`-~5vxvy$z8TQMbsd>df_edDi0bNg{5QRYpK9%;LNJx`A2|mdyvE%_Wt9L zxI*cfchmO2=gSb+H2CsIqJyk&7L|X$4!j*WYe*ez>Fl!XgbY?ao#5JhQ~Q#h*E z)V5kCXOI*9i5MS}W*M8tJQ?A-QQTJABA>e2I3H|zj+RKKYNw4H+Uiiu6~Hry%Dn}o z-KIMGdi+!7{eub+y@kMJLC5I<74laakqhXs;Uk5~EolaR8SXb)QBf2~nzt=E2NdT4 zbTo+PL+X|At8w6+@~aX=)b%$d^*97?8p-tRdbxtM0K^Ug2ys^4u?m2-{rsxO`8B#x zT8y?Sr(it}{$4RjgNmT`hiGV&JDK#Ul?so;p%-V$PfY=q4WYXPa7(0{CmZRKny<}3 zYOr8x6ddik)TbYAA(X8>E$CKFE?996`7Ba-Bn0UXD78OPoN(<}52&Xy%qOf{MS6f8 z@5~va#!+u{V?Q_Mx9(kwS4R_Fc-s>RN?BDKm#a4P3N=zVYmK8N5^tyU$ma6nP@V>^r5$%WgtM%V0`UAS=l{i@cjnZYkZ-_=tAXsYi|q76n8oco_^Ss^Z^w;+9U` zz80j{eYL9?J~7>?!??PaZFgV9$d`z;?zXchqR!VE+OpvmY+E87bn+_0EabU8t$A46 zt6w(sGXh=0G2Q_BZnW11{w@oy?320B7my1xBp^MB{jSp&x|KB1I8mDsNQ^DhQ-*YB zBSHkIA68pPDjy`zf*)keb`{|8%b+I1Ukz_=Q4n4=K@D)~Me`Juu^EvBNUIn3MWI1o z>%#KPC7!k9r{zYw3k7k(wLGR$t#o3Gi9Bm19(G_zdZCb?bLUNKTX&_z_Zncgz=a%; zSi1?oMpNFkG17U}KSVI_xD$wAg=eHU0q;1#b@Y|;;oLDGnFZ6Yj{`5?^vQrRoVR{D>+R*q@oEr3{YJ+;JB2F2(FJ03~~g_T`84b>Vr&{w!#UdDgy%80C(el zmGYRAibi#={3p@NH6~Z~`%|74N3Ri>6VSx6byjGNQm3*~W!&}Z0*ZtAl{-3FHVple za+e1P9igQ6(@TwP09)mpaV-R8r%jV&AVm^7PN9mcSd&vXY=k$c`6^RIe}>Ocr!I0t zG5B-)`-GYQb6lJ11c6-uaoXlE=va@L(-%8!aLc|Q^5sLVy@<7qYrgp2jxTCmV>2sn zXHJsf5>AIj7`mSc>ivI^@qDW2@ZI5^7lf((L`wNSH>~l+{vq3~k^R4=#CHlGCs7y` z)+Rn+h$*~RN-qVMZ-#0NIq~5OY_S%Z>!L^*MnLjJe7cM^DlZ4vzQ_@GnZ6o0& zRLWBeNomFtyPsYH#k1Nmh$?q%!?+YbYT?jFDKTn)7-Nh4Z9wv6I-E9b()TsdW&|Pf zZNz?Zap2uzJ}W$gS6_b^?(iM(x*!ZW;QSest`)_(U;f{F)3Yhoq2y)pdGLVDvBuoP z_oo`Wx3$T3rMwzKImi3`b!F~5{qVvr%kKA$M^_ZmOkUSZ$04!M$sqGikb`(HYZ?fo z{vmlXn#OiK=SlUH2|Dhcdahb8QjmBmCTGWs`=T{C`jzkCMe6#Dh|%{Ilr9lvw5P;T zh`$!RIKhU0c@8gohFp1i?RvvML;;k<{b#)3aXOOE2(f@4K^&*?KM?K)%SrxCK<|N; z<1Rg6EryJ)#ia?N<@w;xu5z=U6%%Q#(-~(2^|$I}3%b>)tGgmjl-8o$IPLe1z;muR zH(0p$LjA~B)IKS*Fa~11ZXyp*KP^oyT6hrLf{Rw%J6pW=`;Dw4M?q0f(dX|P`C^-$ zs3OCow=nfihpz;&DeC7vUc-%{kQys}*VmY{dbY=2ySXxT+~ZD`e{9#B|7{aTJj70>Z_U}TAG~`7VUn`{t5JZBiADL z+LxPlf*b$LpuE!hX1b09Ur>Ffg0xa;m&*@T-=MtT`jt`{=peoVM)+bs%5?0o`Y?7Y zj1)n1WM?IawK^BDO=s`j|3oCbtjB*?m8NWINe7r_)8Vf4@7_dg7GNDYhNG^fH?8Qh zrd?E)@8k<$OWVijcfo~zoIl`OX!En~-^}{_pY;d#xdtd*&s6x9{4es#!{2B27sdF# z#!g@y<>T32+sO5fY z2c{K~mcQ4Nc#w`VQl=bk@)RyXMCwo=-8(PDd674G@VzWLGya;aUC`o4cntY6>B zl-7=F;_OEBBUo+QnmU4!?o6q(n$&qWs^ehv*VoUFb<8zo{?p$Vx6~aa_aAh;U47u% z!-Jo{N@Bxq7r@08%oo*ZrMei!*KD?y7!ra07BU>WL2e}UHjd3OUA;u)LN*yTB03la zov>b9SK;^_1#{0IT}vdWLRCVA@#D{1|KqA>cOG_wRf8z_8ShiJ(YBfw=DRQ#j9wAi z;#o2YPh7G;>y#~8SS<54lsfJyqI8yfO;$QFaL$pzZ-T-Fuj8sI0S4z&G|EJ_nZ&Qz z59^>=dV38FY*>;d;&!ky>flzD&9&F}o9%M{Vr+Y3F|ZE`Sy@`*7=>-AJl3D_V;`1! z6P~^mlzJ#gxry4Cq|?GnR>pi4$kijR|Gv0=U;X4&eC-#n27_HSm)|;H-rd$&#|4j! zl}TO-V<@HHdpW5#=$C}sc;lw3^X9K$bgt4PH~LV>@OG*r0x)j|%*XmA zXKqGU`iQ_;!sY{wCK0E_rGe&oXpORM$EIi{ItK>HD8!{H4HD{R7th@M!z@oGSBvHB zdOy5TT`j+;Wq+=EQ8ijx6wC1QRDRAbR(Kn$UW5&8&-C|kg?+81xR?Y&=oELt9sh__ zE?3Mrz~V$e&_|co;af-2zsiP0AW5ZgafIAhSbB2-9IfMyCt(lHXMn*8JYOa)_c5Iz zn$m0%Ld$u6qKlR=3>ya|v{+PM~XT^i)4suiI$2wW~9wZbLLi#aFRJKO{ za#NJBrbF$)))Y6~9_8i7E&KF_f>oqcu+AzedO2YGiJTODta#$``S`P8LGddkYM++Q zOC|}FFc6*y2gMd_pI+=;W+W(N-7}dyD4+MDdjxfZfJ$qtVkAKi9p)0>KRm#`i=rx2 zPom>lo6aIHQ-0r(yj~7K*S$SkTyuX+7k)zP>b4atB6&{4+`-s_&o{SR%)|>!TWD7c zHL%_f=-8`H&p^tUTlTL$uf>j8BW`~vYsgs$y%X^H|+dc49-k;#WzLirCkz|!tWgo)u<5SMh z0FkgCfN0Rd5Yg5v)CfD0U4<=4jC&8y|4}gDKmfx{V3IT-*sHFEv0DDVS`8hdKsN#9 z+-b_*W%~+iMyw?=h!C);AkN|!$o}zC_Wr?OqAhQQ8xixi3eFmD<-fgE{_zf8?04Z& z!DB+HN81sFM%hQ|9AbF(`cZTv z1!U?9c>TAM=7PrI`D0Q zS@>P4ZX`C%!%IHhS+om_$bL|(kFkc$`cP%fJ&JXWt<{6~>D8C4@(rTjSBR8BAZlm2 zcw&OGOD=xQCA&pT-@QOof`=SF(c%@(nSTUD&cUre`x_)($u*I2Q)VB~=)UT14DY@L zAQ+gQ#%*-sn@4NtQLAji6LdJWxm7hoIz%Z-M~>K{mL4f_7N|o^5i5N23hk}1u)fqg z5Kh4F9$0)mQ$a!UIwOv^eR0oQ%LuL9+R0RdDN%0o7)O(E>X?B%meKnzj-`a9@XtFX zAJXS2(E**D-sv8tom+$mc;X~CYw*B94BFRxvF6P$XLMAF#C-DDDWo;oHn9ZKqLdfP zxilr_OCz_hbH#&~4Cfj*OC*}`=#l5=DBXvus%8GQl9r` z6t_A>MF{nENLd#ysB}VI;xc_e{}v3P{c1kvBX|7!h2_eP)Bmal1y=uFt}}%Vo|q9; zpXAS*DELqxsFbuY)Iw+(PeSQh_u5gRKi6!JG6cF@UbAFKBko+Ilih_DK&Na~MvM=W zG!noJv)H+xXYZ?VYuVCz;Fd&omzI$yUQ%?pY3gDt@phCcgvgf6OUH126dIgT-+yJw z?bg1(`z!>qfgh&7dF^smHPyr!Yo3S1{{xjOgjtwO; z;4z%?_$Ni?X!v$f6TQBi{q`pVuH<|u7JDiGjVqD8W33TJYdZpG*gWSerQ2JC za56hidmmve9wqc^X$hFy&}Z(eG>(Z)5lfJH$r9ZPXJsv6URqo~^paeuSPA@-atK_+ zPftX!NkL?ts8OJ8*-u~Z;lQ-@Xw$F(7>0ckY2FB%R2_tc-Qg87i+87Ef4z@Fc!d;x zkDS_MN}08Ihn8qj;W+;6frHeIy$rIp72eGxVD$2vqbEf|VyPl@1BAIdO*GK++`Z_# zwH>tO*hp~Z-fljLe_8*{&W#qf((%Ih{IYW zfg;Eq`5ppsG(dT8qlmn(k4)}sMb8Ytl$h!`3Rr879;Sy;i9o{_RA)o+$9}B?LBeJw zV5WY=k^~vENTHzlE~)?3JEOQVwv!dM3pflP(5Hewal*S3*{=(-d9R%v4}s#0|KA9+ z<$jmOrE@8nJ@WH?>5Hzuhos;-JV00w6jtWE_;Sg!$fZSO-W@=i;-}MxsQ!#$&lS8< z*zQ76LSqXFUlH<;Omxc%J9^-~0F;I&|7U6YVy@6&R>X+T9DlN9aE=3Ds71zr2tveT z6;>2aryW>jYSIygv(h!X)t(HYmO^;F7Z(H0x?($kJQBOQF7TMl#Z2J6$Q$Khr%0vwx^L8 zxEM<1h^s}mhCFk$ayZsG`dYq?3o?a|oD6Z9{*iV!OI~yx$dZCf5gIpBP|xV8Z}#(_gks7q(i^?1)$O$9l}z82e+5x*mzFr5d_ZKs7G3lY`tthvgHi z2N`N=0%cvP)G$Gj*$5e47bKnSv3UT<%(Bik#QS4f z-5p)J=m33kp$>47GUw#juwfkmCl=GCx!0tiH4pt1cmy5_qyX-`a-q`2-34ifuTW~2 zactQW|F-@wqJavRJ9OP#PH3Em+Ja5szC80FW`6N1>LAtGrihYEwMrK_V;{>VIx~p9 zjr*KY-svupSeT;gN$>eBxcyM9P6yKO$;k**(_Yd29R(pD=m`B9EXKsjbsaAqzQW>bw{+hgWcpwG&j3UJ5V6?fYIELG?Yjm|cY@}am7)#myZSYO` zx~-pC-^U%`7u-Db%Vx&BEmrGrDVm!EP?-cs<(#+{iP(QaG&q}hqE5niC9L}#(oaB= z9fRqLBJMoK`N1p>PPZD1w&_q|5|p;U>LUpZxG%eHc#0C(B8MK=P2t8J8kH4i2!&mh zKjQaRu5MYF%p;RifJmXz9LuQ-g$u3b;W4m|*YrK_I;2i1wl2Z$b4o-wnY*b#@71PX z+R6z^fGOd4hM+TLJDN#B(+*tp)m+a;!9_qMg(adynnds>yX&Ng)+=>GX z$Em!q6gA}9eDK2yxgd**7~LD^iGBd4J;<((PQJDBD9+?Kb3 z!vF{LuYp47KnewVTa@-TrgHnjrT7Th)ry8RkAlrZ4Zb5XTImqgSPh6>T zzna+9+4oGEpmUXg()UFb2?8}uz(m3Ei!W^z1vW>1!4FfBuT!pBRW`regeT)+XBoEc zc!VnN<|K`vfwia6VP<;SAp%$s7y5nU{F;c?Azt=*LiyOEo#`i#7tUp#i_6>10z4Uz zDkIXj%t(xijIQjD^@5HlIKpSTp`kiVuqMVZ9aKHi|7aX3ARnfi~Fv^v_>SZ^hn-~+K~8qDKot zLKyD%euA3x_kFq-5i%>Gnp9J{hUlRbX?3bWrsvJhz&jI4mrjMGVs=V7au9OV25Wf> zlS45L31h#sEXZc?04mHgrGW|?Qeo+Su+{U;b0QJ8_9eorBzU?h)T-ahfM>9tI9;yH z)YsE<0#BW&wmF%EJsp&=i-a9KvE_b(GFS$KYSffKag&sRR z7HL{e3_d^s1KChEMl+^P1K(_XF%{7h1KDKbRYxKZ?6AFE^<=EQ`^HQuE{%PA=H4qU zTA0p#B%)j)2Jrzrd@gZtR#Y1x+}`+xuw#K<)XS7KbBDIYk6N;o|H+V8UtvRfbs%PZs#JG^<3r33T%a0 z7*@x}AIR~ivuS?{XhS6rfPu6BN6}e0G}ZQDc)ii1YryE1(XFFX7^Rdrx?!Z0IJ%LP z#tozqM@fh}I>n)=h^Qk}%y(dc#kcQ2Se)~m^ZcIszAnE<@_!S}@nC5jG!}jCVOUH% z(REqsaT&E^N)qIP2CAVuPro$m+`q^D1I$p4VzLK>@%QgoV#c0^OU{F;Qos*kMjq#6 zJP_h9pKZkw0bjrB37T@3R;%fwx%iAy4LqvZS|&xkt(d7q32%F;h^o7uQv|VRBFyWr z|Cz^a(Kz%1zlf1+*|xGtbv|3V);1>w0CgqZas3A3!NJHOa_Xmc^R0HZPVK6fI_&f9 zI$`_dh%+Bmn1Ltw?i)uZZ$ZEE@n7#~jc>i>NIF)VCpE{mpxNsfNZ@c@&EV+Zv~eVO^{^ep}UCwjQo%6;>x#bT27BPErHm}J0?VmW#U z1F}aW7SNv60X)y+d)LBXO(8p4$V^A{fZ%7iCQUXm4tkz;;dL_zf9lI_6p$YEJC50L)Z(UXd}Jg^a)0nM`9!N-@)6vV(%8uLb5Bt)&w}Y{#^p8cPjJ!{Wbr;=P;G0 zP|WkDH!mOzlchGiul8xT+azcddMLtYJ-REh=yptoKEv;-5}Kgqs!__DLA2&W%iy#gpXIcfyG)d?qq_u zBlz@n5-(oFXld!Q@Y#k~Tl@R7LhO@O&(#SxG}JX;Cy~zu1pFU!+tJp2 zG%O~D8N)bEAi~Zh``Wu-!OzXlNvl|kyW``0b!F`r=C8Q9L!qn{%HpDhsi`b17qLuy<$GwYddM(Oh?Y6HN@aL?Qy z*V%q|cBJ)!0!4?40> zMDar0544_aoXff5PC?HIDU-Pa727EZ|D3I`lm7`Yi8YbZ zK+c%5+|)GVGn^nvSqL^EXN}~0g&vv%o)0=&9l6Jwf-wnBt{grxEH3s2A(D$gi`l&# zBRO}HnWG(!0%y0=9)41T&s7Yny>QtV3-T2!heCtaG6lQ{FkHT5^mEdz7}t6=+$Z_L zws}~Vq};x5Yq{J8+{K#iE>WZiEZ}h=$N_^IhZ&PxE+Oi(ptF2SmKTYfa#LVPKJrDx zz{%%8dvOR72@~@DbPXOYt3U#_PYI?sg}*J%-xD(*a}`Z_X8 zKno23OA<;#zdv!$QtaSJJ+hq+xbyTd$18g3y?{#SqHHeeT6TX8w}Ur!gOqt95cV_V ztX6*ko3#DGRLfcX?<@gptikN|)OX_?9`TTaEdEPZ=fGT5shxBtt?V%|0><==e$Ud)(}79+g*YgJBLzozX4jF%8%T%7_er-Y7#Fd)Zj8;IW4kThR7iTp(j%s*R+HHiP;1@ zuhm@fAt5>SzDpo!kS~IckAMAKl?Rp3IiHL4xjb-9c>D z^DQWDc?@lgshED_7s~CMX5kF{E-$LY zSCq$;1^HlYDo%kMWQO--jSD7uezk#43EhOVdV4-DZaI-{!vyB)taO~7T<14ze2=)d zG{p^r-RZAB>i|}6L4rxSJg#I!)C-iTis0;o$F~+IRLLa`VwXSwcTqs?R4eMcg32Ef z)ODi47tm(8O4eYPB21$2+R6blVWk!d840C~?EQl)_ z@fDfG2S`g47&$0#dEHQeepB&i^a^pVB!vQb|4z;PnOH*L(Zri8barWGn%R8;EN(8? zGp6BtO|~{LF{&V!V}BqKW^B%hL=xk$i+*#(LZ+oQ>T10i7QzOTHmn24;+UBL1|z6c zX7oX7(hqT+k7&KXw>jn66gFlcUofBrta!4;W2=ysC3=mNrIWNB>eL|O$ryY1>en@8 zFEb^s>ar~3B|KSgD~oIKHf;z`XG5Ri` zx>^d95I%W9C7q%8k`P&mTg-d;|h?t?7ZLJ~lRMzlMlZ3jo<3=ca&!0{Ce5R93N zrV&A+m_62w!UhapD%v$+&$sGbO>f0^51Lb5*yyn^lYd?LY&nadG6|7O>vNk$PI~PY z!Vjw-3LPI_y|O}BhGqCuT>Nc4SK?7%z&2DsD9EoUv_&%ssDS8K5fgX!;B1_P#BbCV zw%fGw+RxNWAAbtI-?dqnQ+dJ}nQz99B6-$QXF%LSW{~{cP4Od1))@CGqpNIkHHNVH~=7sFa2xUHj4{&ii6YYy`ug2qw-a^9j)p24ldo!&68CkL(4Cn zYYbW|vp7h&Cu2rhchsgM)A8JjNs@#V$O*J$GO`j?KTrUWa8>r@XF^oy*YGJHF!7UJDi>NrRo)mkp*=bQE{qlqZ~9 z;U7aUV>>5H^r&)jCjfGV-wuEmpV1_rHV~oeI@Gp?w}Wj&l7df#+}c3HtpJ@oI+UKw zikph&7;08Qb(WUU-~CYJJU0!U-EMgI{R7j0b?*1GYNk6Ma-`dyj+};Sq^+;xABK=Q z&4jcKB;&T4-(w=&iVbEywyQ?SB+5H z?57+6!bD^apGpSj3@Ry~H63=+zaSmumy9j0Qrlp3=OyBJ%p^!8O-d zUOnbstK8;fv1tgjA^w@eiJsZ~0-$w+=8$`(ee74L-oE@NU0T#H2Df0g$2?B$$kb$C5JQ zU7-*RNQ4Nur=>Dc1}i`cjGbfai9=0L*sN%$ZGv5)(<&i&WffAAF3H*%noMSx3lrSf zaLMLJf=sI!9s{~@gW29xgQ8D|RKuYp+n=*a?en0{;OK3ttpBd85Y6#+B_NEhE=S>& zC#7oH9uh9$=;AH{`^Z=k3os(dT zT_{%oXvj^=n*{y77yMDTK-U!!{0JX5<)RXT3tMws`5qUs2CO;INuOl7P9vhSklT|) zjw7PdFbj`fMn4c{frdv73Z`sBNaj(S)KkgK9y$T8OS!b8fmv~i-z|dy=ESX_)?#Jg z%x8EQ7!Mg#xfri};>*&g9(nqR1uK-jWR^|z^Rv$m4H-EJTgQNj3VVmjB=Xv6FhHoh9#xB!niccvPUP-Z#UU-dRYJh? zPYQ00RJxf+-tyIFo`P;`SDC*TGO@9IU+pZ+pV7bJ?0_w@K%y;)@cu(*JQBp5NV7qP%b9>;y5A)tUlynu(A&YCv=wFj)KjDvwK zYRm1?=9c5-7VY;ip=v0p%WMzjX;;Jqz#P=qzz$h~+LKUkIv^Yg*C&Gnh@LJ25N2U< z*bN*5D7c*HhtDeFzNdTOH7Cz1Ax(xykYF-(p8OSJTXUId=#~S@BS?5P1 z#E~^FAuP$1lKtl;^?=gt(HgmHWV&3`l>-0$+qQT{*lwI)TwspDIpq+Ve~FFCF`~{% zJtW;6Y=|p!DdVi`Is=)vN0Fr=#~{%REe3_ti4M?4*0+ZuP0BPA6U)W2x#TDFj0q+J zl9waj@~TsUE|3~xXs~b^EDzzOlm`}I)~B(&R^>3&_bsbq?H-bqQ*M>_1DZ^3M8ELp zAUFY|@Jg|REH?VhZ}hA1RI7DWpOYIPnT=XL}H|y=jf7>R3XPd;3t56-^oXr5F2&9Zbcw`#IRJ&S1T3cT zQ{=@&nA{FrZVZv2=P8B5!c4~r_pSOk>4C^&DRs%d7Gda_uK^ct!xZ{86xIM>8E!KT z9$}VSYURNKxLardNNzIdL@szvv9V|&wkHsnS=PQZPH7jdGrtyxCqqulbS${_yAAeU z+yF{o;9ist+)TgN?*xt{xB3`G34p%5U7{Cmq9IEOBn3a!AQ&rSpeY)8svUOymszi1 zs%?K4_4bK@%uyx+*&WjDg@p@x#SLA2tP(^5B)b958Y)ZSY7*aav)0Uh*iji z=GoLcjg|VM3UFr@7y*!(>I}am3$vj6oguRIeKnikw&O!znco=fpeMV?;-%$By+N8PB0{31B z%EYH(Cxg*9jmru(NpR&U0P}#6ueZ)@DHk?5>HRA(ornws^hq0W-)q#g_&UXZkZ0@< z(yf%SHRatCgexjS?eL&K*mU_dSl^Rr`z%j+n=z?BTCHA&r|M?*{^a;bMs)YcX;H;_ z?|4z{_!BAMVP&DT?mJ$^7FJzV{y$5yC&L`jXfEQMi||#F^x)vSQe1>#A(rhCP~h6Q z!A1`&7-oI56#~E{y>5uU^3*ZNxumncyP)G91UY}LtUvqLy%wTSvVOK(_{p$v%A)nr zu*|ri1mUzh;qiyoTE!1)*&}u^@1@`QW;%>wEo{CM#!DSLQuLkkkO-DTpJnkS$OHMV zq{8GDmrZS<7w~;kX*WGNc*EYhtMA7Af0Vw)8`AXjya?DE4|FAQ8&3vpq}iSJ4rY)r zlgB&)WgwgRoG{N->xpO`B0>~^%Z~5rv+HnSe|Y$(={u_GXXC?P6A$xaEQ54K?Y~(@ zRSLdyp-tgHqZ;#FILwS5XAw!ZgBE_m?|N|1RrEAIQ)P8&Y3+H-dG4~7`{yTKFVkLKfc>cV^r1nIx>s~|0ZeG?J6Ev&*6XJ~^CSe} z%wt^j3?B8e2d7s|6Mw)sDUg(FGP*Gob*)um(@bP4q*eh3O>Ek}v*98ME_uLmIqczf zwJtHPs_N|Xyco+b2^0T%pFey2JaH28%@X)L93Lr#nKT8Tu3}C9)0F`SgpSFIysXR$ z>drl%z{#2!(>G2 zlA0ni4r(!Ne@QZg+n|3UjnI4Qe%--cZ4Rw$_pleXBgVBkd*XByJ4}N*Jb*hzTKXRL zJ1=CPZ@nq3R?YbDiGEZ9xG(l%MVO!k!K%i9ZIEK+Ul$Ix%zBx+X7(bb-;RIBt2?0v zTtWwi;Kl4-Elkqx-TnK*)cVcsl*Nt8qTrvvD`*abAT@&~UYeKy&}@nP<ByqyPW@`Y``qvtg?G=tzI|RO{iQH*x;e1JGLCVg6C&G%RnaViBF&I!ax7i*?RJn5DOA3=G`qWQ5Cb8<>wu|!PCzpnLwZfaCfx& z_YbW{`Noi{2dc!$JAGaaB0hgs^8Hp#i$%0mLdfM{CKup_!|-^%dh1*X$}r`RwG35I z6cZAm*JW-a0#>moR|-^W?h zmg#C12NMQP@6D9}@#7kbxV8le2n;EM#b@n_L&TbC)_Br%voXe9#5%n7bLCx3GmbW+ z=+{{&&h(}83&JwBtg4cdA}lj94P~i3N7FKK%@1^+t57u7Z6CAa>>3g?42E61+AicD zQ3ISZEK9#^mD`8T*1q&N3OT;{29bku{BmySsNBukP-p4UCzsJ zSCyAxIi1RK&0%Rywy^>}C;7g)BIB7tpc1i|8M%;cZCilcQZ~v8xPi`q=zpH!#a-sJ zV7{)t>~w({eHv{I?YVg_-_3H5>?VF8gF91N`V*R!J-#iFDjs^n1kB->CMkG9wXN-$ zk0Z4VD`2V+lPy2%RO@H8ToQo2m`bB<_+OQr%#?vyBqydkWo><=fbNQw;Pbocy)`8CQi6n0e{r~l5g_eWDArleZU+QZqHk+ z7OX{?(=~y_z&Lko;+iz}lbt@MutR)Jb&Vm*;lc;&?<@v=wt}yw|321?9R4>pZ6WxC z{o6|Bk!nAV!vJ*x*p}zrROjvb(6=1rEA^&&&ITP6W3F(iAjQvqk=tpK({L0Ibv_Mr z^Pe=|&Np>2`hj?IH5U@fU#`37WHoz*LV|)WMidKH=}%Yyq2$CeGtPvU)q)^I5{nt9 zD59UmoP?|TaxYvimpUI4lxZ1|uzJpdAA-bXH`nK^bs$vfLjY37t0aXm)d>MutLK9s z`O=m3PKqM6Q@s$LI_vUG7QIh&m_*tQ?hkgMJ|P>{s%PXcfL&E4Ex^$$$ZT+YfaU{H zC-zb>Kd1Y%k1TTWKovdMU0ko`g3qP7fmI)$>C49`+Qs4Df8Uj=zmVFu;4(=niWK#k zAzs4JZdx@zvEv=K{+lP1uA{fs{#vbT8&=+h4sWC^r`2 z%yYg(r|$@tUI^QK%L0cPT;I{PqFP~jK;t4}Vq%fN(^5zFO~eR3;`HYE^*ERvhAj(ZWLO@Vx09RL8}4NW_kKc@_u91(~x z<=etSPk-9J^y?8#+3z45i*2c)&g9@i)`Ia>6D^o%#caRAuS|su8_pudRD{R<5DAm}gXM@*C$byJ z6%J7rPbJ#`IOHk>W;>am_lRx9`%?RcuYz2jugk?Rf-Uy$Ex{FQnN38wAu@j?5y*#D z%Y&_W+hRi86@YAV+6DIbuq;#T6zoH%4o3);LmELA=)~oI>}7H>!(SBW3^l%;A>^)w znhCzzW|mnCfzKob1mgjjm}@5IjrW0R?UJQ>>-Yjvv54KI>^5h&DulaA zk~+@GIrl^wvrs^)I-K$YKScHPs_Q^#Y6EUDH2 z=uSYv%Ye*qRy;6}f}K18#`T(i4CG!g(7NgUfZKDF)OM=PBq-NaFKjmpwoZbvRAsOS z5V8bx-sCDwOmf8oGFUk<_l@Tsx<*#`vZ`RO$DNvlP!X`cRRYWa70wa9;fq|tgLr#0 zjH2;KL8{)EE}h8M!5_jW$oe9KdJX-w!1NR+iS5ZOIe`UPY!TkRMrR%2zg=ko(jjG+ zt$k!kT9YQ64+UQlR#Vgg1@MwAt#2&Ew-=<0SCwaG7}OML5@<(zl(QT4pMsU(C?(s# zGC+z?<2~UaYU{jKUYEq#sLn^RjUpEpIAPX`4g)Won`ee_Y`cBD?I86YQ~`^u-W2cK zk$$HL6^4~cj(xUb1(5r(~_6p=709|yYd--OCjB)@VR1!V#p*&F5gsb3j-Ai zS&2Ngr%-xlD<>uf2p`FG)N0Sj(%aAEq#+yo5E`CmAV3snK6v+(RbJA3!_v9jW znW#H=*f_}{xcdcfiPxVeCNG-g>)@?eCu(w3Asy`b=O+YNddF?m*As(TjpY#_F4R2u zM_D`UG!?p5;1kcugKdNS`Q}>jRL17fJK37hO#2{%nmU`dplfB4TkV#a0-x%06^nJJ zL)^djsZVO^%WgdBOYiv?e>WWbRqYbZyWvFZ;Dg#d0mIq5nbkWg=p5z7NwN!x%Gz~z ziE!H@_Z!ZdJ)Xgd)FPf=JDS_+jw#V(FBQ6QB#NnZa*Vsy*PQ)d#>AToZ&EbB31?~o zw}v;MagdIY|IBJSpryw;0waO)EW$hk*esUFl|zn8dNcn`OsxCYC>CUkmx%}Q8)cKj zB=8j+NWzc*N=~mQgf3^VONEveINo!;{9G{*_GI(!M>ZT{gzxEOp8O{)$C-UsR%ZaJ zMey>ot^e-*fs&MTfta?7F|hkX*n0$DFapV90?L)qxq*`_6+-`6`!qF2}@4rv*q zubsfvvU=$*j*YV(A7GyUt;1S#IPT$2^om`QaxNu()xi~>2iFIRjrwuw&v_n`piP({ zolD7eR+*mDbgX5=4f!jZE$BtO4oUX2s)_mCq`r>Mxq8DMV0vq zW_!JxTJ%GfQ7sVF&%>lnx|^o`FuPa>bN4s&=|94 zd6%gf-cnU(EP~@-TH)((7nxEM$*sSEke>oj{&Godhavik%xnZg z6{*HYa9!OWa*=sly>48tI1eYfuEUQ=W&yv^AD9;hsvU+Uw))reXE2=)1;K%yiDHFc zlfI+5?9k9gyj;NBeA)byq9v;{>1)X>G$DOlteS$MB=-gFq~Pa)F^dZ+H{Ye0KH_gs zw+X-jQ_Qn1Mg_%aPCw>TTYf@iGpts~f-RPAOzZX!x14~)IK7%2AhW%X2kv8_0aRcL z4#tV}WbTEJ^`M&Z(B_@1fp95wEDzYG>>*#7)H&INYS<%Jzc=#0)Xszt@A6Wp4xi!q zOC$$QsHrQ#ps*H{#&8)y@NBQkrBdNmWfo=HTsLE3BT@l0B1b%qQyl<`ClD`ZNf=NZ zJM=R8h6{fTv2SNcd@1w)frcgwg=)G4VQP!cdPIJ6v3+#s3F>+JkwG}U3};yDo87q{4-hp`uTWK#joZ-qinu9ZH~Va1Z* zJ~S?CDjY|zk!L28iM2uR>it9kMuB7-oH%K<54hk;6?rp z`j!t?Lt8RCL$WgFY?&T`X!pC$u=6A+8ts1jd%5ITjcAN!xE0V7Tcsp?DSci!ngY{y zB{ph{>rwP$@P!@Lfe%1l5BwZ4Ht;`|RUR|?&VWqML&LH6Rj=!=NJ|RxG3-O}1W}?@ zK~S~5q7gq0_|MtM?lGwIz^HFTny7Ovfgl6_2ILC0F-I7M>8Ff53z7PI?caBog1L)@ zCMRi$9;KfvYu?3H-x!eMr`K>IYs08O6qP+c^lEYF|6AA6A7H8)Ep-JgiuEmaIe;lx zx#v4ru?Gx=g}D;J#C#88K3LTcq`3s-!GpRA>PKRgGg~8E%Fc?jRA|jL3-&j-T7a)4 zSdgW;UXm_VRTjK@3(uIhcu8wqeP8J#(=^Y+5lja>zh)7-DN!$w$qsLhHYk>Is@O}0 zxWw|j9#wzUbxKkaOj3+so3S?aLu3(T27|GG$G~Ekl2DJ56>eA2$3P6at6U^4P~A05 z_~K42crWDQn^-xig1Fl*%F_y^~a|FuVQ~{zDCMSXUS#>Kfl@4x5je8SIqZq zD?Do?HS(G_Zw{Ij>(FcTXk4}wFcu&lPbUwEc#0R+-yBPL{}U8Is!mfF^32nbR_d2E zs868+AK2zH-C>$&;8($$ZNfL@h^Cw*I2H}$L_!_Cu7+bzZan=3-tdIo1%S@vHSl&f zK%U9{90Y=$`zY>h7XSf9=K8J_N7yLr%ce?Kl0Fn6;Y0&)VkC|Vn?O_TAKvh!h)_y; z8g6QJOsUK6>BpLnQhxFCaQvq5(@-$<(53#dg5l;|U#Sw$5*ZhbW-NCHF z;ydsoE7e6$PAN4<<&M;~8DKC4qD+EnE(5=Rfa(^Z#XsnFc?9&mALLo9P*ica{{u-diUJcLc551fzZcf_v(Dz*z=M%0joSCkmjJ{NQyhcv{0{kR z=g^bzVPwJi0PLt5rTf9NR{>F zWD`gM86bfgY>=}NgZVbOKCszHI@23;=}`3c?09zy5gbLkd+|@}#*4Y0@$SoowH_~e zT>zkC1?Kuck0vSk2YY!VZDk|&Mo57 zT(p1(;>zd6`rRkbYf*p2JW{+lS@dG#)XmKq=$ItCR5SfzzyVbI!K3-c$NG048@+rS zz343yF5t+>e&upzs6lhjdOd-xbY?E_G+Td>VDPTMZ4&E_j*I3HQHC{?a7I|6Ey4OYa5hetIvvTp1`rmD8#~ z;AHcD;T9?~BNaGt0`vnXe4t9WgpD>EJ!&!Dym3~p3BQ?;vDtNZQ?!|O^RFCQ0~M#P zsR1CF8_`FMm&e3N#us884wvFBgDQXApHc1OvQ>MhH-q>)8Y&46q^@vN;i4kYjpBL~ z7NTYMYCm#y=g;gjvDeZftLg7yXyTl0^Q*`e;DYH^ZTfFV>Xr4V z9wDdoIF25g;4T}|x4hBN>j5kDz54|wZmzKq7S4o;N%|X+ZQj$H&2eF_KLyI$AH9>J zqgMA(afvU^OK8Jr->H zkuBW}-j;l_$N&BnabeGHb?>Zr{nN-*HRMJ>;QPl%__7{C?bh?6I zsB+eJYlnMD>3?csVP&VMcq%9@J=@ZCQZ>yxLlZARVPN@Z?@`LlgLed-r@ADcu!L{l z`WclObE7i_4+14Zvi0{23|k425w>h|V^N24YQTukPY+{Y=e`_b(Y=vdy}?w#N2}Hi zQTC5{wP!>Q-G-inwMc8*`||66Xjb<?`R~+u^Pfr;FClZ*|^GmYn3d`}@u+3bIy=mZN^W>-SM!Vs+%p(*&bI<@9VD&I^#<}uQSww{D6Keuw;O>v`o`ndF zFF$rKy2iStHuHEsJQLCRN6I|U|7zJ={r{eA@We$|M@0WEbs$u+%9o$w4*8EqR-6I4 z@)U4Js3^)@NjaAcgigp@l z(L)DEn*!nf#yQ5UemXCc3+vl1p=9gUL6=S zr0eL2NKMt(XF1m5`}6l7pH|48UD;b7V+f*|x{s$4OVko?*L}3?Ynd$)(hS>L=x?3B zy1n{56b?2KNw-qi!%}E~nS9Kc6GT6%Unb}LZ2>AFF>lb)BiNqrkXk-;Rd4^ z>Cf^@S0xh9c48~$+Qi~KRh!KO%P-uybg(DcYc(-?kcHr#3VF|vG>_+vv%Btacl`TR z^G6Av83B%&(u%yFlBXEH4CNl9jzTSUKjo)$NH z;b)0{qTbA;2)vg7;ln~=1U%Je`oY{-I?s8&z{VI$;gW4SIX}?+0K`{%MBVh*1rh`W;n z{`jO1q0{G|6wl^+^cm1#6_M}DRr!pf-wr;!d@Q@9Za6wRU62vVX6rxS;>QXv*l;d@ z1nPmH!Wm=SvyyrFQYLCcbHgxBIU>!DFSwDB%MwFV&u59+=e9s8MNr_i9xsz0ry3`J zy5tCXSjV7e3$B)1fBJSzuytkmfFu*WdY$HqqIw@EU$!c2uU~vV?JD5$P2SCf<%u2s zm0#&ErXqL-nIX^&S;Iciokvf~q)PHU2=5=2l*tb)lT4GEX+_ksO!2&(Q|9>un8jC? z`7O!JH>wK>a|W0e4xqHgT3G7DTH>FNu*Vj8#A}gG(!p}$+W@i1AxV2=puOc1k2S5V z#5`v(_}Jm2dLsaCO}$C-7vp#_ZSzmdpobkAr#@Drr%-c?THa-h+Im!@8?1a5KX24w$e#m3&jG{L= zghYXGgTEH~04+s|Y14&iYsRCYY?!FpIY}Sn%uOddFML7PW^4?iVa@kcoJ}@MJTs3>2tt!6kTd{~9JrwuUsJhR;bhQvfk2+N| zX{>F2_K0j{EHEMgK$x)b?Yp|U!n%u23X}jBI|1-j3ItwYniyY;`!i0=YCN#uy5&@V zQHeU}<8wACU?T%_iDuL$mdhSSpXO`FOY0`(vId7ZYpn!<@J>KTLOJ&N4)K97U=E~6 z^BX77iFztPNO;mTyY(7Ojp}qcp&%2iLdp{PMsFq+Os(k=!2*8MK3Di|VBxm3)7J_d z4;ZW5^#h94dQpDBuRHL9s606%X?kH1_ z)E&}W)TXj~KG!DxCMJNmch+y_u^{sCCDRHjn^4TKCdAF!BW;@P2LJlXdM2wJ!;fzv z@qwPTf77PXu6Min890%6!p0;T|9VQgXX2`g=rc3rjNm0^j(@*Nu&A{bYS*jCa8Szd zTrfn7P%O`_7z?)Du#_DhvrmkwWFcV}0rbU+7JKZ~Y1=8w@73v+c-Bo&u6^J}?kBgM zq5wN_M=QHcM??vaX_1u7xjUYHp>KoVE?XcSBr|@Jxl7~;SoTrcoIB6-<=9>}#Xof= zYSx&(g|mIJp&HL#uS^>jLN5r|DmCkT9=^2^xz~!3&-xNIbP*j_NjPnQN|m8I7xBNm z(pfRE;2b}oVBW)e1E&RRBmo<=P5!jkwD?;CQrb8uL>D{!eachrK2_&0-ggQ;=_KHY z@uaZdd#Kue4QKEPV@hNdIga^-}EJC@m zHaZuaVrBJssQobP(L{~2X*)@399L1A9l_t|?G&2jcFF`=TY~h^{n%X(lC)3`D<_UL z&VW*nsd!65rmmSPoXcO!fBiq>XDFz|6DnI|Cs1rJNy>O8T;;dnsluNt@AfJdE4Ij1 zBAF@|%>M;vFRvXGM>hJ4{#QGHH1;s=znH5gCpIi(|A;HLB1-_p4#|%g$!%OGoEL>< z9ofb5tqU&KC*S5SLD)kvGl8d4kDrzxzGlqZ2f;oe;IYM1m>(La;JwGqwrwE6aoXy) zI%{sPl$R&@;LUeoUZQ1Jg640mh`ywK4|c)y6)tR5$yqdrRvLey%c*jR+neR|H%BNG z8>^~+wSG#dDnY(~ zoHQx=HZ&q~@+0m|I3Jzc&>e$Glne6}jYe?l#OR6G5*0hjKG--^e<&J;v-4 zRa_Td<>~^yu$E=6PsjW?r+CjwgAr!E4KH?2U=M#=;OzzC9XhS&$m>JTi7OfAxHJl0 zMbCayDPk^!lO=i2_;@M{ViQ$gnG&WlZ@ac6(LLCQ!uaQu&U_4K^~ z)v8hlgMKzK#R>443zG7&-~x!_oi@9Fmt5{07EJsxDHFf`)6WpV54bF>LIR!6pL(tF z;EHz5FhU~q_`5n!>X=TdPY0fzm@4J0oQq@Q1o(0g9XW8m3|{aZesJ{M=`Xy{hyKAT z=3qw#GDYsPlwPK%lm6WUQAsnd{JhKM?;=eJ=`RG6FbeT|)-}$ymRN-I z2~YzU){$!-jR`ys);xDj$`Gjnu=WI56QK**FCPm9l89;QZd^KoT%#~5GS~+P#v@|% z@Q$dbu&}R2!PqOFm`It8+^7ZbJ29EtvZxdCRW!S03G0gU}Ri^0cOp^Da*Tox8#WsSkBNp&zI6bYEaH7j(Lb<#ngmc zz^C~ofGT{MG}=P%BO@my*clBC#m7e17LC_(AID~j@}cVExxoEg3X%b(UpAQ5A9;=bpo)5{)ZLBNjOd*Hw6&=nJ)(&}T!61)O50s&$@8hDoVdUK#&OL2;9U8(&ZJ$<=ZY zV7Z|{0o>Iue2`@xH6<)C(W!WGa86lT0w07-%dRA9W2I{97Yh2G2$uLZG#nJ@;bq6L?5QR?UxtGE*TE7&Aa!DE zOs+sY9rjX#t;ZBPYz+hpXIgA_q#I<~{sMi2CsdQ*w*r|NFOS??KhdF>nD@PFk%g-BSesoYodT8%75&@84 zLfD9Z^Q|X>34ApjZs8>&T3Roc3^cp1GBvq99P~}YU9~fTEH=k zb{_&L(znO)8py7T!w(IjW7p3wj)qXt!WJ=qY5@8Gc1oYhT(6d0OND<*g*o&kG{ z&W5AQT*8M-e~)HWo`{*6K-5TJC8m%N-<(cnDKdec!NOWF+7%)a=_Tc`=1^ADt~_>NWCi;2}D zHECb4ITHF!UZ`ERWePkTmGVXOA#zY2dlE!;pkgEaE zF#t;+l)VpaRKjh3#!e)fHum600|x_^!wuK9otW`r)usWCMe7yOP#4<$9TBQd+O+6) z|8UAlk0(B`h&8oJ-80b~svjH9%Wgb}zEjBXOm#Z5%zI~=F0^b8jmJw_eY8BjWO=VW zLU+?+{0XdP6B|P~;3YH3Rkt!_*2{0(f z%qx`*q|hi3Nd!N}6n*>F&i#?Y@%N(Oi_sg64<0Iyc@!-v;>UZot{G{AJ2OteJ;+HJ z+hy8ggc^>04Aw^I_YELvvg#o?0i~a}l->pa(X{I#3Zu~mb{FUXug3s&3d9bd!GZ1< zBEd^S`;~SZH;vXFEI$z9Q9F-TVL`3BEdjsE2wjBbNPR%)x>|`!#Uy*QPtyQ63s??@ zJsu04(XWa~NvvV-m}xK$K!ODb0K2k6HYOg9*r8YkOEu`@Yg)Gy0aO+(xd2vCk)=#u zBwFmzxaH)Y-J{{(lA?!fGw9}@{N`>+*FWq6)FXhcA7J0uIu3RLy8{qr_hvfWk)6(g z#WRzF!&W!f(;oC!q%Ixs1Xd%T0Ox>F6o}j3X8i53TLqJ1pc5&%L$>&Ggggx#0DroO zwmR%A2~veB(%XR?9ol%!3skRPwS~t23;Y`c{*eE?G+0~mtU zQC(n_U;>D(*eU6*re&zOfGgpH3&E*z=%ahFC1LA38tbz@^P~bl&DQM{1rks$6qwx* ztJ*-YsztrmupQoiD%%`jYJyGJ*ISMby#)FC+gIJ81~%LxLI|}&Gv|Y08!{TPG$Lhy zKIyYQD-;3KjiV0mVKNO?6sW>-hPW8Q+D7f#;vM198NIR+*lCO2;`|A3K+NHoTJMe3 zjNoq`Vj^*27O4P=Od z?(VsMVC$^2^NgYSo#kcVZ#>&7>Jy5)sTq~dzH^Zbv4pf&AO$qO<6Te&Kkw#o=HuqT z03dJxS77w1p7elkVpuzHovZ~&WS*=%8JQ^MhK>IPBJbWLyX%cG3`LUia6yWG`8^m` zBF;TqGT-uhn+$D-B$|EzTyXjiyPj;b1pDYldSDJOa0Ptt_ud}(wtuy#M8JA~00*qS zu0Zwa-JxV~^_mO$kv|xaFbMv>doaHlJ86cRQOHz)se`c6#qjyMiMzfFyvx7^5g_2j z9MCpmPRrZ?WDLW!ode)~`|L0H1N^aIaR8*5;fEnD7d~L81r`?YUxjX$$nOY%5cQ&` z_ZAd&k{HGC5*6h@6~z%`Vse%kbm+LY#_)!in8?{c+Cb;f6=Q-Eqq3r65fjtJ1>(kK zp%YVc0z?E6VlP422o6kLb=A&DIFeZ}UyRH@>fQ=3^fJ70t@1g%cfIB4YCR^5_yd7FnNMhU1?b~}V%0S`Zi6UY; zbjn1rZYWcbG7fNv{C?)liy$WvD{cc~6^=GKBCI&TCB9{0vD(mK;1dc6&@@KdG5T77 z0uD%Efd-;RgdMY00K^+N?O+c?zu_Z+SisrC77$<+R|Y@G(W6{f_>j?%Cx@Ic3U!h| z#DI1uoZ)~2e0}Fg0}ez%UMS`@;6)p8xN(L?4#eRKEc6KzUl%nrz=2OMq`)5n9gqg# zfmU9LWtLhJc+M9cbf6&>Qn-QPAY_rT!wVDsgOEHgm|#H)Wqin1i2iW!f5jzhVRK)29uf!(DkXe5cLYE;Ykn-HKnP3t{cxQNb zqK+TMh>^&NH5vm560AXo7d1%w(h9FEfvyfp(!m)Ko`IG^8uJ#VZ_!2{jdW7z7y!d_ zZ*U<+hZsgt;hGF@^}_!TT4*r>i49HM)>{ricTgePMZw7%dT63Cis7AL!i}0FMjah% z;9!Dv8#jQWw~~4kvlm{-0-4P!1eJ>paVW`Tem7ZgMKSbNnRMlrUyk`QQ+43A2~wC) zPdvH05!S6Jo#x?EXRqlon7h)a03uPk#BVo-^CO9GoHQ8~mj1#KqRnvCzZlSfC1}AyOVWv}6SV1XB0`C42QvklKR`OGFMMlw;CC6!301kU$iqSO)K8j67we z8y!R@vP~S%I=%w|2q%A0W-jXth6$*Z_Z%EGYGM5z)Rw< z#FHd+5fK@1Ko|Peg;_6X5h83O)B;YffMfqo zgqlL1xkC$FIBfWqdf_Z=u))==MDaezB# zP}?T!V#P&(f>{i-i+QLMJugrPf^@KvcVI?}hh@f=APnIWT=5FfZ0ZD_dP5APAPg-O z(}n+0?3Oefit0BSHn5E$UODKMa;2qCdnJKL=Anl2wWIDvW9)>#=XVj*;qAPzXP zXSJS4zKW?^-5NzLN!n;;m*H(K|CtKhsvyBn&faD^bA}~IAr4DO>JvJE z6%bqnrMM8(Ue=(uAPfo;oNNITt^o)b074KhodU!5hbR;#x5-bw6zOOFPH=SCps zGk-`!BeNAbV zfSPg5^enjt&;kgSuz>_1fYUxfx!KQ74yYnv3OJYqyWJg5*^$`QnXGxe>p_N9>|8=X zctMOvQj&~8BxI{qgeOiQfg0y%M@#P$9cCtrO2{G(i}R)6ZYc~tXu(oJ*~P{?UIrbw zE)Ivy!Gt}H_SCDs8iV`-3^dU4h003K@UA4^eeT5oijF(E=Q*C{8F>G}L!>#E5Xl1%PUGfCw`!ab-mxfe9$mECnZlJK|3obOMnQ2aYju z52gh%cmQJ%X-mLcbyQSTB?Sf+cK)G$Er^CLXa`;be+~dzRDk~kBXAHnsDp7whb4w{ zf3bJoG+wplZ*$0d^d)!*Q+)+^1{H)h7@>rwKz(KKgw6M3b<-nN*aMVd0zA?MhLr-9 z5E&qt8D0AOSiEZxVtWbmnjL00kpM zZvvGa(kc=FVJDG!+*9oVzyIb^gw5O*K-*0i@K)=5?~3z zM;8YH1@S`%(Lx@TfFp;J9&}|1Fyf4b)&SC|7}3)*>+%014v=}IBSHw)g}>DR_<;eQ zp#n&d0v2$BrU!1#)s8QDa$N$0SKtPOASORBhxS*8P_P4JFk*?!JJ(>}U z9hYqppanN^1PNe?hfD&Lq|8@|47b6B(ka(h$aF!h{ zrUy|_353xXr&e2B@J^YKR!-+Kd*c958G$H49XAy{z$FZkdqH2vK&4o1rF?UzP$_FoSL&1z6ydb%_5bgHT(MP>1+NjEY%+#28+AcZoc9 zlrxZ&l#&8_5iL?leU*?wdE;X@;*NwNiatP?Kac1LGBd8PgE?-~fzyl-)FEktv-e zaZS}HIB}41Z>EH>L^@7Kl~h2Y?POOcN_k%SNEP&WZIGG=Fm2T4eQnSKB)L!)V2)(i zAE&3EJ$je?;$?d<1v=mcEz&waaF4MQkZ~|j?2;=a5(GL|UnK^iYv2cdKo=OAE0utZ z+MzaYl06Hjk`}O(qyRx11S1(#q9Bl>UP=Fzl|Tho@B>jm2LOdz2lhth@?>3*LZGJu zDu8JRu#(JmhCXVjj5TVlm;zPE0A(%!E3o()&KL!cvF)f{GMi>zzjPV1^6CV(Vr!pFXYZ;rZpaLmb zpJ{Mqg?gyT%2Y4d0ePu7uvi9LGbjDfBA_*5W&#C^i3HRKR~YAg$N>X18_%gFycY2pW9jIw>dM2Tj>c!MKz~N2 zDdeXG@~KPxdMV*ZRLI3p5n%tg^?9%=h_sB0yfU<#d%y>wLIrf8H7PKh0d#mGvqV4W z5%UGQez0l>X&)7_w&S%e6)9h=3j#Vbnj!>g5x~Ce3#fW^8G;JCHWL$o8@Ow5T!^vl96T)%P)zp+q&P2w|W@TVp?sOpHU1I)wbCysvBk0X)m+Og=tgLokp7 z6rhq)00NRw2JH3&HI^~!q_#@PE7~$HCqZuq8CZ0Xa208D5-4==nT@dJZkJr0l8a#>_P@ppaoM<1`rVhL-_{b zx?^iV1zz~MpTIY8vkMBBa3nDU0IehmO|vhnx3*guI1|xHeJPl7$?HPHhMCbmC8%*} zv{SN|Kp@Ftb_Y|*^X zvS8Fl?a&d8Gkq;bjI$P32)#A>^1_w=z#v{v1h$w zs*Dq^S-Pjj0S!b25*N)wZ4(@NB%Q3(upMZ~A4vj-HQ1iA~)76L430hJkZ)>NcG zUtIraJs@Z>@}~!&8D6Z=dW*O6LF9;Y$@?c3sN0v2P&c7lkRj^V*5;kj#I$OO9tmPd8aywLHX*Rfq0^g((4 zBjy#59$U+B&X$-#7bNd+aYL@Sn%|k+NnT!be^Jm>*}TJ2=s$7L300K zfiA{KAmvnU42jk2^X~Bi(t0Nj=}OSP?2D4Hh%gcmr&lnR`4;egASfN|c*X{3K)%U0 zzsbGjOEfMBd9q0_{V?<`1xPKoyKU%1;n5xc@k{R-CGO}5kOufpzi)&DSMXUQMh0r& z@7?I^ED|zGXg~^QY}h_=*_>>cm~ zkiG$EF!f`Al8;h0iv$8J{{t1oO>3120$)Xq$J0IS$bqp<$?^t=g5xkOZS1QAxL)@g zUmA&?_oLtRv0>u&-p)z@_$thW+g4}($F__VL~gJH{M3}UkNamM653SxvabI?VhpH3 zfx;2c`81FQMr-%Up!B5A{HdYk{lfPMkov2yORYap-oYX-a6dydMCd7)`&0(n1pfQ9 z1Lbf2Jt^^PBPbBJ;!~ZjX?WZW5FdJC{3TWG_&9dT&7|I3{sRQYtD^2df7v5fMm76bU(d2rwNsUv>dR zL>R!q!o$SH#>dFX%FE2n&d<=%($mz{*4NnC+S}a2L;(SIUp5^uPkRYRN@!#4?qe$v zS}7ofCs9Ff4Es<}i~j&QdE&rf27@;z9Ds;p;m#>kst%lbg+z%gTDJe5bTDAU4liHb zLW&$ovZTqAC{wCjInq}+apcVHNkd^nmUr$}#ET$BiUoQmaIC?X?~T!;L86>kD#`?i z6c$>cO4YNcD~cPA(7=d5Bgb96ez6=&wyfE+Xw#})>oUMN1Le-;prMXkPMtX8_0(eF zXNnYY0{?}&WQjyn5mc~Zbv0f^Sv1nry0uXkudr(~Yu?Pcv**twU3&atz<@afGwH4q zg0uCzov&WOj-8n5!w5QIS){PF)}AN0zJ3G=y14P<$dfBqDHEL1Xu>&fK(V zPn|0JI@XJ{YCQp7`U_ZJVwbC5&%V9;<>Zz#in5Uld zG3x58u!=e=sj1d#>#cXL%A=*c@~W$&xCSfiuy+2sDzPBQCadhS%r@)nv(QE>?X=WZ UYwfkzW~=SC+;;2joq+%VJHCEf)Bpeg literal 0 HcmV?d00001 From 3f7aaa2799db7c94076bb3155a83811a7c596708 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 4 Apr 2017 09:19:14 +0800 Subject: [PATCH 0247/1039] fix: broken links --- AVL Tree/README.markdown | 4 +- Bounded Priority Queue/README.markdown | 2 +- Count Occurrences/README.markdown | 6 +-- Depth-First Search/README.markdown | 6 +-- Deque/README.markdown | 42 +++++++++---------- Heap Sort/README.markdown | 2 +- Huffman Coding/README.markdown | 28 ++++++------- Knuth-Morris-Pratt/README.markdown | 32 +++++++------- Kth Largest Element/README.markdown | 6 +-- .../README.markdown | 4 +- Priority Queue/README.markdown | 6 +-- Quicksort/README.markdown | 24 +++++------ Segment Tree/README.markdown | 12 +++--- Selection Sort/README.markdown | 10 ++--- 14 files changed, 92 insertions(+), 92 deletions(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index a9218203a..c8d8d4628 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -53,7 +53,7 @@ For the rotation we're using the terminology: * *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: +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) @@ -76,7 +76,7 @@ Insertion never needs more than 2 rotations. Removal might require up to __log(n ## The code -Most of the code in [AVLTree.swift](AVLTree.swift) is just regular [binary search tree](../Binary Search Tree/) 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. +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. diff --git a/Bounded Priority Queue/README.markdown b/Bounded Priority Queue/README.markdown index 4e4c89272..8cbaa85b2 100644 --- a/Bounded Priority Queue/README.markdown +++ b/Bounded Priority Queue/README.markdown @@ -26,7 +26,7 @@ Suppose that we wish to insert the element `G` with priority 0.1 into this BPQ. ## Implementation -While a [heap](../Heap/) may be a really simple implementation for a priority queue, a sorted [linked list](../Linked List/) allows for **O(k)** insertion and **O(1)** deletion, where **k** is the bounding number of elements. +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: diff --git a/Count Occurrences/README.markdown b/Count Occurrences/README.markdown index 4c65c4219..85b77d2d0 100644 --- a/Count Occurrences/README.markdown +++ b/Count Occurrences/README.markdown @@ -36,7 +36,7 @@ func countOccurrencesOfKey(_ key: Int, inArray a: [Int]) -> Int { } return low } - + func rightBoundary() -> Int { var low = 0 var high = a.count @@ -50,12 +50,12 @@ func countOccurrencesOfKey(_ key: Int, inArray a: [Int]) -> Int { } return low } - + return rightBoundary() - leftBoundary() } ``` -Notice that the helper functions `leftBoundary()` and `rightBoundary()` are very similar to the [binary search](../Binary Search/) algorithm. The big difference is that they don't stop when they find the search key, but keep going. +Notice that the helper functions `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. To test this algorithm, copy the code to a playground and then do: diff --git a/Depth-First Search/README.markdown b/Depth-First Search/README.markdown index 9e1a5112d..98a19e0cb 100644 --- a/Depth-First Search/README.markdown +++ b/Depth-First Search/README.markdown @@ -40,7 +40,7 @@ func depthFirstSearch(_ graph: Graph, source: Node) -> [String] { } ``` -Where a [breadth-first search](../Breadth-First Search/) visits all immediate neighbors first, a depth-first search tries to go as deep down the tree or graph as it can. +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: @@ -71,13 +71,13 @@ 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 Sort/) of nodes in a 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! diff --git a/Deque/README.markdown b/Deque/README.markdown index 67a734576..fda1de5f8 100644 --- a/Deque/README.markdown +++ b/Deque/README.markdown @@ -9,23 +9,23 @@ 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, atIndex: 0) } - + public mutating func dequeue() -> T? { if isEmpty { return nil @@ -33,7 +33,7 @@ public struct Deque { return array.removeFirst() } } - + public mutating func dequeueBack() -> T? { if isEmpty { return nil @@ -41,11 +41,11 @@ public struct Deque { return array.removeLast() } } - + public func peekFront() -> T? { return array.first } - + public func peekBack() -> T? { return array.last } @@ -73,7 +73,7 @@ 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: @@ -92,7 +92,7 @@ Likewise, inserting an element at the front of the array is expensive because it 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. +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: @@ -120,26 +120,26 @@ public struct Deque { 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 } @@ -155,7 +155,7 @@ public struct Deque { return array.removeLast() } } - + public func peekFront() -> T? { if isEmpty { return nil @@ -163,7 +163,7 @@ public struct Deque { return array[head] } } - + public func peekBack() -> T? { if isEmpty { return nil @@ -176,7 +176,7 @@ public struct Deque { 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 `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. @@ -219,7 +219,7 @@ Notice how the array has resized itself. There was no room to add the `1`, so Sw | 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. +> **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: @@ -250,7 +250,7 @@ There is one tiny problem... If you enqueue a lot of objects at the front, you'r } ``` -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. +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. @@ -302,7 +302,7 @@ This way we can strike a balance between fast enqueuing and dequeuing at the fro ## See also -Other ways to implement deque are by using a [doubly linked list](../Linked List/), a [circular buffer](../Ring Buffer/), or two [stacks](../Stack/) facing opposite directions. +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) diff --git a/Heap Sort/README.markdown b/Heap Sort/README.markdown index 5f047f82b..7fdd8d2ca 100644 --- a/Heap Sort/README.markdown +++ b/Heap Sort/README.markdown @@ -40,7 +40,7 @@ And fix up the heap to make it valid max-heap again: 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 Sort/), 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. +> **Note:** This process is very similar to [selection sort](../Selection%20Sort/), which repeatedly looks for the minimum item in the remainder of the array. Extracting the minimum or maximum value is what heaps are good at. Performance of heap sort is **O(n lg n)** in best, worst, and average case. Because we modify the array directly, heap sort can be performed in-place. But it is not a stable sort: the relative order of identical elements is not preserved. diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 6b2c0d245..4e6f75514 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -16,7 +16,7 @@ If you count how often each byte appears, you can clearly see that some bytes oc 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 @@ -30,12 +30,12 @@ We can assign bit strings to each of these bytes. The more common a byte is, the 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 + 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 @@ -57,7 +57,7 @@ The edges between the nodes either say "1" or "0". These correspond to the bit-e Compression is then a matter of looping through the input bytes, and for each byte traverse 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`). So the Huffman code for `c` is `0011`. +For example, to go from the root node to `c`, we go right (`0`), right again (`0`), left (`1`), and left again (`1`). So the Huffman code for `c` is `0011`. Decompression works in exactly the opposite way. It reads the compressed bits one-by-one and traverses the tree until we get 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`. @@ -137,7 +137,7 @@ Here are the definitions we need: ```swift class Huffman { typealias NodeIndex = Int - + struct Node { var count = 0 var index: NodeIndex = -1 @@ -152,7 +152,7 @@ class Huffman { } ``` -The tree structure is stored in the `tree` array and will be made up of `Node` objects. Since this is a [binary tree](../Binary Tree/), each node needs two children, `left` and `right`, and a reference back to its `parent` node. Unlike a typical binary tree, however, these nodes don't to use pointers to refer to each other but 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.) +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, however, these nodes don't to use pointers to refer to each other but 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 `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'll add more nodes as we build up the actual tree. For the moment there isn't a tree yet, just 256 separate leaf nodes with no connections between them. All the node counts are 0. @@ -183,7 +183,7 @@ Instead, we'll add a method to export the frequency table without all the pieces var byte: UInt8 = 0 var count = 0 } - + func frequencyTable() -> [Freq] { var a = [Freq]() for i in 0..<256 where tree[i].count > 0 { @@ -209,7 +209,7 @@ To build the tree, we do the following: 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 Queue/). A priority queue is a data structure that is optimized so that finding the minimum value is always very fast. Here, we repeatedly need to find the node with the smallest count. +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 very fast. Here, we repeatedly need to find the node with the smallest count. The function `buildTree()` then becomes: @@ -233,7 +233,7 @@ The function `buildTree()` then becomes: tree[node1.index].parent = parentNode.index // 4 tree[node2.index].parent = parentNode.index - + queue.enqueue(parentNode) // 5 } @@ -286,7 +286,7 @@ Now that we know how to build the compression tree from the frequency table, we } ``` -This first calls `countByteFrequency()` to build the frequency table, then `buildTree()` to put together the compression tree. It also creates a `BitWriter` object for writing individual bits. +This first calls `countByteFrequency()` to build the frequency table, then `buildTree()` to put together the compression tree. It also creates a `BitWriter` object for writing individual bits. Then it loops through the entire input and for each byte calls `traverseTree()`. That method will step through the tree nodes and for each node write a 1 or 0 bit. Finally, we return the `BitWriter`'s data object. @@ -309,7 +309,7 @@ The interesting stuff happens in `traverseTree()`. This is a recursive method: } ``` -When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we're about to encode. This method recursively walks the tree from a leaf node up to the root, and then back again. +When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we're about to encode. This method recursively walks the tree from a leaf node up to the root, and then back again. As we're 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's the right node, we emit a 0. @@ -395,10 +395,10 @@ Here's how you would 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)! ``` diff --git a/Knuth-Morris-Pratt/README.markdown b/Knuth-Morris-Pratt/README.markdown index f01b87b3d..95fdea9e9 100644 --- a/Knuth-Morris-Pratt/README.markdown +++ b/Knuth-Morris-Pratt/README.markdown @@ -1,9 +1,9 @@ # 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. - +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 @@ -16,7 +16,7 @@ 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/) 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 String Search/) 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 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: @@ -93,10 +93,10 @@ extension String { ``` 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 + text: GCACTGACTGACTGACTAG textIndex: ^ pattern: ACTGACTA patternIndex: ^ @@ -104,54 +104,54 @@ Let's make an example reasoning with the code above. Let's consider the string ` 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: ^ + 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 + 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 + 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 + 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. +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* diff --git a/Kth Largest Element/README.markdown b/Kth Largest Element/README.markdown index d50d691a1..53bec1c1c 100644 --- a/Kth Largest Element/README.markdown +++ b/Kth Largest Element/README.markdown @@ -44,7 +44,7 @@ Of course, if you were looking for the k-th *smallest* element, you'd use `a[k]` ## A faster solution -There is a clever algorithm that combines the ideas of [binary search](../Binary Search/) and [quicksort](../Quicksort/) to arrive at an **O(n)** 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. @@ -86,7 +86,7 @@ The following function implements these ideas: ```swift public func randomizedSelect(array: [T], order k: Int) -> T { var a = array - + func randomPivot(inout a: [T], _ low: Int, _ high: Int) -> T { let pivotIndex = random(min: low, max: high) swap(&a, pivotIndex, high) @@ -120,7 +120,7 @@ public func randomizedSelect(array: [T], order k: Int) -> T { return a[low] } } - + precondition(a.count > 0) return randomizedSelect(&a, 0, a.count - 1, k) } diff --git a/Minimum Spanning Tree (Unweighted)/README.markdown b/Minimum Spanning Tree (Unweighted)/README.markdown index cfd29c987..23f18c335 100644 --- a/Minimum Spanning Tree (Unweighted)/README.markdown +++ b/Minimum Spanning Tree (Unweighted)/README.markdown @@ -16,7 +16,7 @@ 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 Search/) 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. +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. @@ -185,6 +185,6 @@ print(minimumSpanningTree) // [node: a edges: ["b", "h"]] // [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 Search) to find the minimum spanning tree. +> **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* diff --git a/Priority Queue/README.markdown b/Priority Queue/README.markdown index 8308ec16f..fbbcaa0f3 100644 --- a/Priority Queue/README.markdown +++ b/Priority Queue/README.markdown @@ -12,7 +12,7 @@ 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 Coding/) 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. +- [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! @@ -31,8 +31,8 @@ Common operations on a priority queue: There are different ways to implement priority queues: -- As a [sorted array](../Ordered Array/). 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 Search Tree/). This is great for making a double-ended priority queue because it implements both "find minimum" and "find maximum" efficiently. +- 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: diff --git a/Quicksort/README.markdown b/Quicksort/README.markdown index d359ecb5c..e0bd8e604 100644 --- a/Quicksort/README.markdown +++ b/Quicksort/README.markdown @@ -14,7 +14,7 @@ func quicksort(_ a: [T]) -> [T] { let less = a.filter { $0 < pivot } let equal = a.filter { $0 == pivot } let greater = a.filter { $0 > pivot } - + return quicksort(less) + equal + quicksort(greater) } ``` @@ -30,7 +30,7 @@ Here's how it works. When given an array, `quicksort()` splits it up into three 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. +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 @@ -73,7 +73,7 @@ The `less` array is empty because there was no value smaller than `-1`; the othe 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: [ ] @@ -122,7 +122,7 @@ There is no guarantee that partitioning keeps the elements in the same relative [ 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 Sort/), for example). Most of the time that's not a big deal. +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 @@ -133,7 +133,7 @@ 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..(_ a: inout [T], low: Int, high: Int) -> Int i += 1 } } - + (a[i], a[high]) = (a[high], a[i]) return i } @@ -168,7 +168,7 @@ After partitioning, the array looks like this: The variable `p` contains the return value of the call to `partitionLomuto()` and is 7. This is the index of the pivot element in the new array (marked with a star). -The left partition goes from 0 to `p-1` and is `[ 0, 3, 2, 1, 5, 8, -1 ]`. The right partition goes from `p+1` to the end, and is `[ 9, 10, 14, 26, 27 ]` (the fact that the right partition is already sorted is a coincidence). +The left partition goes from 0 to `p-1` and is `[ 0, 3, 2, 1, 5, 8, -1 ]`. The right partition goes from `p+1` to the end, and is `[ 9, 10, 14, 26, 27 ]` (the fact that the right partition is already sorted is a coincidence). You may notice something interesting... The value `8` occurs more than once in the array. One of those `8`s did not end up neatly in the middle but somewhere in the left partition. That's a small downside of the Lomuto algorithm as it makes quicksort slower if there are a lot of duplicate elements. @@ -281,11 +281,11 @@ 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 { swap(&a[i], &a[j]) } else { @@ -309,9 +309,9 @@ 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. +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 ]`. +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. @@ -357,7 +357,7 @@ And again: 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. +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: diff --git a/Segment Tree/README.markdown b/Segment Tree/README.markdown index 15b1a3227..9897c9c3b 100644 --- a/Segment Tree/README.markdown +++ b/Segment Tree/README.markdown @@ -18,7 +18,7 @@ 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: @@ -43,7 +43,7 @@ The main idea of segment trees is simple: we precalculate some segments in our a ## Structure of segment tree -A segment tree is just a [binary tree](../Binary Tree/) where each node is an instance of the `SegmentTree` class: +A segment tree is just a [binary tree](../Binary%20Tree/) where each node is an instance of the `SegmentTree` class: ```swift public class SegmentTree { @@ -116,18 +116,18 @@ Here's the code: 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) diff --git a/Selection Sort/README.markdown b/Selection Sort/README.markdown index e95749d14..cb8ed59c2 100644 --- a/Selection Sort/README.markdown +++ b/Selection Sort/README.markdown @@ -2,7 +2,7 @@ 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 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. +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... ] @@ -23,7 +23,7 @@ It's called a "selection" sort, because at every step you search through the res ## An example -Let's say 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. +Let's say 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: @@ -65,14 +65,14 @@ func selectionSort(_ array: [Int]) -> [Int] { 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 swap(&a[x], &a[lowest]) } @@ -108,7 +108,7 @@ The source file [SelectionSort.swift](SelectionSort.swift) has a version of this ## Performance -Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. +Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble%20Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. [Heap sort](../Heap%20Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. From 93cbde7ae9f22d800bb30050b504e13a652ce5a2 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Tue, 4 Apr 2017 02:46:04 -0400 Subject: [PATCH 0248/1039] Fixed a bug when appending or inserting a node --- .../LinkedList.playground/Contents.swift | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index ed46331d8..6e743ba89 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -73,7 +73,8 @@ public final class LinkedList { self.append(newNode) } - public func append(_ newNode: Node) { + public func append(_ node: Node) { + let newNode = LinkedListNode(value: node.value) if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode @@ -104,9 +105,9 @@ public final class LinkedList { self.insert(newNode, atIndex: index) } - public func insert(_ newNode: Node, atIndex index: Int) { + 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 @@ -264,16 +265,16 @@ f // [Universe, Swifty] //list.removeAll() //list.isEmpty -list.remove(node: list.first!) // "Hello" +list.remove(node: list.first!) // "Universe" list.count // 2 -list[0] // "Swift" -list[1] // "World" +list[0] // "Swifty" +list[1] // "Hello" -list.removeLast() // "World" +list.removeLast() // "Hello" list.count // 1 -list[0] // "Swift" +list[0] // "Swifty" -list.remove(atIndex: 0) // "Swift" +list.remove(atIndex: 0) // "Swifty" list.count // 0 let linkedList: LinkedList = [1, 2, 3, 4] // [1, 2, 3, 4] @@ -281,7 +282,7 @@ 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" +let listArrayLiteral2: LinkedList? = ["Swift", "Algorithm", "Club"] +listArrayLiteral2?.count // 3 +listArrayLiteral2?[0] // "Swift" +listArrayLiteral2?.removeLast() // "Club" From 3028c6500f4b2bf8ac4fe899f238b32f946fa879 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Tue, 4 Apr 2017 03:07:05 -0400 Subject: [PATCH 0249/1039] Corrected comments in playground. Fixed a logic bug when inserting/appending a node --- Linked List/LinkedList.playground/Contents.swift | 8 ++++---- Linked List/LinkedList.swift | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 6e743ba89..abbb90467 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -282,7 +282,7 @@ 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" +let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] +listArrayLiteral2.count // 3 +listArrayLiteral2[0] // "Swift" +listArrayLiteral2.removeLast() // "Club" diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 53dc77a06..55593cdc9 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -71,7 +71,8 @@ public final class LinkedList { self.append(newNode) } - public func append(_ newNode: Node) { + public func append(_ node: Node) { + let newNode = Node(value: node.value) if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode @@ -102,9 +103,9 @@ public final class LinkedList { self.insert(newNode, atIndex: index) } - public func insert(_ newNode: Node, atIndex index: Int) { + public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) - + let newNode = Node(value: node.value) newNode.previous = prev newNode.next = next prev?.next = newNode From b0204d3e0a9a84c8ddb4fdce3fa9dc8276e755ed Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 4 Apr 2017 10:08:48 +0300 Subject: [PATCH 0250/1039] Dijkstra's algorithm --- .../Dijkstra.playground/Contents.swift | 122 +++++++ .../Dijkstra.playground/contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + Dijkstra Algorithm/README.md | 23 ++ .../Screenshots/screenshot1.jpg | Bin 0 -> 214771 bytes .../Screenshots/screenshot2.jpg | Bin 0 -> 225916 bytes .../Screenshots/screenshot3.jpg | Bin 0 -> 224243 bytes .../Contents.swift | 57 ++++ .../Resources/Pause.png | Bin 0 -> 712 bytes .../Resources/Start.png | Bin 0 -> 1044 bytes .../Resources/Stop.png | Bin 0 -> 498 bytes .../Sources/CustomUI/EdgeRepresentation.swift | 109 ++++++ .../Sources/CustomUI/ErrorView.swift | 30 ++ .../Sources/CustomUI/MyShapeLayer.swift | 7 + .../Sources/CustomUI/RoundedButton.swift | 20 ++ .../Sources/CustomUI/VertexView.swift | 63 ++++ .../Sources/Graph.swift | 308 +++++++++++++++++ .../Sources/GraphColors.swift | 15 + .../Sources/GraphView.swift | 246 ++++++++++++++ .../Sources/SimpleObjects/Edge.swift | 12 + .../Sources/SimpleObjects/Vertex.swift | 62 ++++ .../Sources/Window.swift | 319 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + .../timeline.xctimeline | 6 + README.markdown | 1 + 26 files changed, 1422 insertions(+) create mode 100644 Dijkstra Algorithm/Dijkstra.playground/Contents.swift create mode 100644 Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground create mode 100644 Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Dijkstra Algorithm/README.md create mode 100644 Dijkstra Algorithm/Screenshots/screenshot1.jpg create mode 100644 Dijkstra Algorithm/Screenshots/screenshot2.jpg create mode 100644 Dijkstra Algorithm/Screenshots/screenshot3.jpg create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Pause.png create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Start.png create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Stop.png create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata create mode 100644 Dijkstra Algorithm/VisualizedDijkstra.playground/timeline.xctimeline diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift new file mode 100644 index 000000000..8d600d577 --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -0,0 +1,122 @@ +//: Playground - noun: a place where people can play + +import Foundation +import UIKit + +open class ProductVertex: Vertex {} + +open class Vertex: Hashable, Equatable { + + open var identifier: String! + open var neighbors: [(Vertex, Double)] = [] + open var pathLengthFromStart: Double = Double.infinity + open var pathVerticesFromStart: [Vertex] = [] +// open var point: CGPoint! + + public init(identifier: String/*, point: CGPoint*/) { + self.identifier = identifier +// self.point = point + } + + open var hashValue: Int { + return self.identifier.hashValue + } + + public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { + if lhs.hashValue == rhs.hashValue { + return true + } + return false + } + + open func clearCache() { + self.pathLengthFromStart = Double.infinity + self.pathVerticesFromStart = [] + } +} + +public class Dijkstra { + private var totalVertices: Set + + public init(vertices: Set) { + self.totalVertices = vertices + } + + private func clearCache() { + self.totalVertices.forEach { $0.clearCache() } + } + + public func findShortestPaths(from startVertex: Vertex) { + self.clearCache() + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(startVertex) + var currentVertex: Vertex! = startVertex + while currentVertex != nil { + totalVertices.remove(currentVertex) + let filteredNeighbors = currentVertex.neighbors.filter { totalVertices.contains($0.0) } + for neighbor in filteredNeighbors { + let neighborVertex = neighbor.0 + let weight = neighbor.1 + + let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + if theoreticNewWeight < neighborVertex.pathLengthFromStart { + neighborVertex.pathLengthFromStart = theoreticNewWeight + neighborVertex.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighborVertex.pathVerticesFromStart.append(neighborVertex) + } + } + if totalVertices.isEmpty { + currentVertex = nil + break + } + currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } + } + } +} + +var _vertices: Set = Set() + +func createNotConnectedVertices() { + for i in 0..<15 { + let vertex = Vertex(identifier: "\(i)") + _vertices.insert(vertex) + } +} + +func setupConnections() { + for vertex in _vertices { + let randomEdgesCount = arc4random_uniform(4) + 1 + for _ 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] +} + +createNotConnectedVertices() +setupConnections() +let dijkstra = Dijkstra(vertices: _vertices) +let offset = Int(arc4random_uniform(UInt32(_vertices.count))) +let index = _vertices.index(_vertices.startIndex, offsetBy: offset) +let startVertex = _vertices[index] +dijkstra.findShortestPaths(from: startVertex) +let destinationVertex = randomVertex(except: startVertex) +destinationVertex.pathLengthFromStart +destinationVertex.pathVerticesFromStart + + diff --git a/Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground b/Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground new file mode 100644 index 000000000..5da2641c9 --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata b/Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md new file mode 100644 index 000000000..872e9f851 --- /dev/null +++ b/Dijkstra Algorithm/README.md @@ -0,0 +1,23 @@ +# Dijkstra-algorithm +WWDC 2017 Scholarship Project +Created by [Taras Nikulin](https://github.com/crabman448) + +## About +Dijkstra's algorithm is used for finding shortest paths from start vertex in graph(with weighted vertices) to all other vertices. +More algorithm's description can be found in playground or on wikipedia: +[Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) + +To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. + +If you need only realization of the algorithm without visualization 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) + +## Screenshots + + + + + + diff --git a/Dijkstra Algorithm/Screenshots/screenshot1.jpg b/Dijkstra Algorithm/Screenshots/screenshot1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..390bc658224310c7720678cffd68bf1654b5c045 GIT binary patch literal 214771 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

@lrF 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 Ag8%>k literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Screenshots/screenshot2.jpg b/Dijkstra Algorithm/Screenshots/screenshot2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bc51046fb36bd2c77b11cf8f6bc28afd0a2faff8 GIT binary patch literal 225916 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Screenshots/screenshot3.jpg b/Dijkstra Algorithm/Screenshots/screenshot3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e9f7a1207f315e8f5aa20c72f3264c65edafd3a8 GIT binary patch literal 224243 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift new file mode 100644 index 000000000..e4b3e6732 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Contents.swift @@ -0,0 +1,57 @@ +/*: + ## 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! ;) + */ diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Pause.png b/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Pause.png new file mode 100644 index 0000000000000000000000000000000000000000..12a5d49228a5ed6708e3478435ea0c60885c958f GIT binary patch literal 712 zcmeAS@N?(olHy`uVBq!ia0vp^6(G#P1|%(0%q{^b#^NA%Cx&(BWL`2bFg1C)IEGX( zzP)&mmqCH&utUQCxs8f{HfWVMXq*p literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Start.png b/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Start.png new file mode 100644 index 0000000000000000000000000000000000000000..3ab9556297d800bdd36cdbc8f1a256467230cab9 GIT binary patch literal 1044 zcmeAS@N?(olHy`uVBq!ia0vp^6(G#P1|%(0%q{^b#^NA%Cx&(BWL`2bFrV{uaSW+o ze0w)L@3sR^YvAq|hc<1|I~zH3wb+gh-PeZvlV%-HS6HBXw%|~;(9`t1^UptTtf{?Q z(L3`%(`xYx%0k}XmonK3ec^udOZS4Z!}?HjJLbE_U)WyUQ(aKqa__Ru4!#oq3+xlp zw>P|F{N-c#(C&h+vpT~vJ;q(GFGBYAlsar@naenRx5x{z1;tmnt})lDmM})V6kD*q zLGS9S8|)=2C9END!xktn$ezmcjrlD{?SJ+sH|&>x{l4kP`M-7bPjZsp7BcBFzP4tK z@|3tD)@Ukr!E4c?Z9Ho>HiQYWZe>sCW!*CA#0p!+Y@G#DU7X$uMkF(?RpHAze?W>m zLv>@IJHxdI2kp-3Rze$&F-3Xml)5DJvVVDSz`>u%#`MdH{)~g`UWfF*lWb(QWBqdG zK(GU|&a>OOC+=r7)Hi(1)5vHz`YW=%f$fKIS?$v7jE3uTe$U_C!d4+)^4>4}0>gX5 zdGYU=q#hKX*evSn%v^J9dfk4{jE2jM!Qp1Cyaig(|8}V@U_94;`fj17$$_0QPhaad zvh9#rQa$u>?*WXSH7}vG0di#Kjw?Mc5Zk>2W!`p^6Rx_QLbB-q6Kh7eRP%ZJg zFZ2RKbn%a`+D&XX_>ZhE7Be{z$Mdgt@&d+h?H}wO3P>fq|MB=&z7w+yyFlqBX_Eti z8;{TbEdML~&(1j#GY`B!ao9pzrE$Bv$pOWg?J}R(RtqzR3H`n18_~}+gYklMfDfR@_i+Q?DS1lN{JHKU#t~tgS;khN)H^G$efY+m6SzN0N z8N!6Fhl+!Z=vcoFtV1x|8LZ&Y{x-0YE%AF|ub!8sJynnC^dFi9Xc+d^gn1J4@gcZs_E z4UN3P1vVMX5)sGu9FE@4z$`tl?m#2A!3IXl_|hZsa-!ywxqaHDf!UnF)78&qol`;+ E0JOlxT>t<8 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Stop.png b/Dijkstra Algorithm/VisualizedDijkstra.playground/Resources/Stop.png new file mode 100644 index 0000000000000000000000000000000000000000..b74585cbe2b300ac7126e7bc63c0968843432f8b GIT binary patch literal 498 zcmeAS@N?(olHy`uVBq!ia0vp^6(G#P1|%(0%q{^b#^NA%Cx&(BWL^TXLn;{G zUS{NFP~bV@aA5y)#|anj$ZWa$zH)oawF4(7G5%&_>9cP-z;vAV$VZ)s2Rj-q=CN|i zm ULH=xDyfH9%y85}Sb4q9e0I4;^asU7T literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift new file mode 100644 index 000000000..5ff656dab --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift @@ -0,0 +1,109 @@ +import UIKit + +public class EdgeRepresentation: Equatable { + 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 = self.graphColors.defaultEdgeColor + label.clipsToBounds = true + label.adjustsFontSizeToFitWidth = true + label.layer.cornerRadius = arcDiameter / 2 + label.text = "" + + let shapeLayer = MyShapeLayer() + shapeLayer.path = path.cgPath + shapeLayer.strokeColor = self.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() { + self.layer.strokeColor = self.graphColors.checkingColor.cgColor + self.label.backgroundColor = self.graphColors.checkingColor + } + + public func setDefaultColor() { + self.layer.strokeColor = self.graphColors.defaultEdgeColor.cgColor + self.label.backgroundColor = self.graphColors.defaultEdgeColor + } + + public func setText(text: String) { + self.label.text = text + } + + public static func ==(lhs: EdgeRepresentation, rhs: EdgeRepresentation) -> Bool { + if lhs.label.hashValue == rhs.label.hashValue && lhs.layer.hashValue == rhs.layer.hashValue { + return true + } + return false + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift new file mode 100644 index 000000000..69874e5d7 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift @@ -0,0 +1,30 @@ +import UIKit + +public class ErrorView: UIView { + private var label: UILabel! + public override init(frame: CGRect) { + super.init(frame: frame) + self.commonInit() + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func commonInit() { + self.backgroundColor = UIColor(red: 242/255, green: 156/255, blue: 84/255, alpha: 1) + self.layer.cornerRadius = 10 + + let labelFrame = CGRect(x: 10, y: 10, width: self.frame.width - 20, height: self.frame.height - 20) + self.label = UILabel(frame: labelFrame) + self.label.numberOfLines = 0 + self.label.adjustsFontSizeToFitWidth = true + self.label.textAlignment = .center + self.label.textColor = UIColor.white + self.addSubview(self.label) + } + + public func setText(text: String) { + self.label.text = text + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift new file mode 100644 index 000000000..54147f5e1 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift @@ -0,0 +1,7 @@ +import Foundation +import UIKit + +public class MyShapeLayer: CAShapeLayer { + public var startPoint: CGPoint? + public var endPoint: CGPoint? +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift new file mode 100644 index 000000000..2647c4525 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift @@ -0,0 +1,20 @@ +import UIKit + +public class RoundedButton: UIButton { + private var graphColors: GraphColors = GraphColors.sharedInstance + + public override init(frame: CGRect) { + super.init(frame: frame) + self.commonInit() + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func commonInit() { + self.backgroundColor = self.graphColors.buttonsBackgroundColor + self.titleLabel?.adjustsFontSizeToFitWidth = true + self.layer.cornerRadius = 7 + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift new file mode 100644 index 000000000..29c971411 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift @@ -0,0 +1,63 @@ +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) + self.backgroundColor = self.graphColors.defaultVertexColor + self.layer.cornerRadius = frame.width / 2 + self.clipsToBounds = true + self.setupIdLabel() + self.setupPathLengthFromStartLabel() + } + + private func setupIdLabel() { + let x: CGFloat = self.frame.width * 0.2 + let y: CGFloat = 0 + let width: CGFloat = self.frame.width * 0.6 + let height: CGFloat = self.frame.height / 2 + let idLabelFrame = CGRect(x: x, y: y, width: width, height: height) + + self.idLabel = UILabel(frame: idLabelFrame) + self.idLabel.textAlignment = .center + self.idLabel.adjustsFontSizeToFitWidth = true + self.addSubview(self.idLabel) + } + + private func setupPathLengthFromStartLabel() { + let x: CGFloat = self.frame.width * 0.2 + let y: CGFloat = self.frame.height / 2 + let width: CGFloat = self.frame.width * 0.6 + let height: CGFloat = self.frame.height / 2 + let pathLengthLabelFrame = CGRect(x: x, y: y, width: width, height: height) + + self.pathLengthLabel = UILabel(frame: pathLengthLabelFrame) + self.pathLengthLabel.textAlignment = .center + self.pathLengthLabel.adjustsFontSizeToFitWidth = true + self.addSubview(self.pathLengthLabel) + } + + public func setIdLabel(text: String) { + self.idLabel.text = text + } + + public func setPathLengthLabel(text: String) { + self.pathLengthLabel.text = text + } + + public func setLabelsTextColor(color: UIColor) { + self.idLabel.textColor = color + self.pathLengthLabel.textColor = color + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift new file mode 100644 index 000000000..0b0b97b92 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift @@ -0,0 +1,308 @@ +import Foundation +import UIKit + +public enum GraphState { + case initial + case autoVisualization + case interactiveVisualization + case parsing + case completed +} + +public class Graph { + private init() { } + + 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: Bool = false + public var stopVisualization: Bool = false + public var startVertex: Vertex! + public var interactiveNeighborCheckAnimationDuration: Double = 1.8 { + didSet { + self._interactiveOneSleepDuration = UInt32(self.interactiveNeighborCheckAnimationDuration * 1000000.0 / 3.0) + } + } + private var _interactiveOneSleepDuration: UInt32 = 600000 + + public var visualizationNeighborCheckAnimationDuration: Double = 2.25 { + didSet { + self._visualizationOneSleepDuration = UInt32(self.visualizationNeighborCheckAnimationDuration * 1000000.0 / 3.0) + } + } + private var _visualizationOneSleepDuration: UInt32 = 750000 + + public var vertices: Set { + return self._vertices + } + + public init(verticesCount: UInt) { + self.verticesCount = verticesCount + } + + public func removeGraph() { + self._vertices.removeAll() + self.startVertex = nil + } + + public func createNewGraph() { + guard self._vertices.isEmpty, self.startVertex == nil else { + assertionFailure("Clear graph before creating new one") + return + } + self.createNotConnectedVertices() + self.setupConnections() + let offset = Int(arc4random_uniform(UInt32(self._vertices.count))) + let index = self._vertices.index(self._vertices.startIndex, offsetBy: offset) + self.startVertex = self._vertices[index] + self.setVertexLevels() + } + + private func clearCache() { + self._vertices.forEach { $0.clearCache() } + } + + public func reset() { + for vertex in self._vertices { + vertex.clearCache() + } + } + + private func createNotConnectedVertices() { + for i in 0.. Vertex { + var newSet = self._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() { + self._vertices.forEach { $0.clearLevelInfo() } + guard let startVertex = self.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) { + self.clearCache() + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(self.startVertex) + var currentVertex: Vertex! = self.startVertex + + var totalVertices = self._vertices + + breakableLoop: while currentVertex != nil { + totalVertices.remove(currentVertex) + while self.pauseVisualization == true { + if self.stopVisualization == true { + break breakableLoop + } + } + if self.stopVisualization == true { + break breakableLoop + } + DispatchQueue.main.async { + currentVertex.setVisitedColor() + } + usleep(750000) + currentVertex.visited = true + let filteredEdges = currentVertex.edges.filter { !$0.neighbor.visited } + for edge in filteredEdges { + let neighbor = edge.neighbor + let weight = edge.weight + let edgeRepresentation = edge.edgeRepresentation + + while self.pauseVisualization == true { + if self.stopVisualization == true { + break breakableLoop + } + } + if self.stopVisualization == true { + break breakableLoop + } + DispatchQueue.main.async { + edgeRepresentation?.setCheckingColor() + neighbor.setCheckingPathColor() + self.delegate?.willCompareVertices(startVertexPathLength: currentVertex.pathLengthFromStart, + edgePathLength: weight, + endVertexPathLength: neighbor.pathLengthFromStart) + } + usleep(self._visualizationOneSleepDuration) + + + let theoreticNewWeight = currentVertex.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 = currentVertex.pathVerticesFromStart + neighbor.pathVerticesFromStart.append(neighbor) + } + usleep(self._visualizationOneSleepDuration) + + DispatchQueue.main.async { + self.delegate?.didFinishCompare() + edge.edgeRepresentation?.setDefaultColor() + edge.neighbor.setDefaultColor() + } + usleep(self._visualizationOneSleepDuration) + } + if totalVertices.isEmpty { + currentVertex = nil + break + } + currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } + } + if self.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 self.nextVertices.contains(vertex) { + self.delegate?.willStartVertexNeighborsChecking() + self.state = .parsing + self.parseNeighborsFor(vertex: vertex) { + self.state = .interactiveVisualization + self.delegate?.didFinishVertexNeighborsChecking() + } + } else { + self.delegate?.didTapWrongVertex() + } + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift new file mode 100644 index 000000000..95e9b8d74 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphColors.swift @@ -0,0 +1,15 @@ +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) +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift new file mode 100644 index 000000000..49bc6853f --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift @@ -0,0 +1,246 @@ +import UIKit + +public class GraphView: UIView { + private var graph: Graph! + private var panningView: VertexView? = nil + private var graphColors: GraphColors = GraphColors.sharedInstance + + public override init(frame: CGRect) { + super.init(frame: frame) + self.backgroundColor = self.graphColors.graphBackgroundColor + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + + } + + public func configure(graph: Graph) { + self.graph = graph + } + + public func removeGraph() { + for vertex in self.graph.vertices { + if let view = vertex.view { + view.removeFromSuperview() + vertex.view = nil + } + } + for vertex in self.graph.vertices { + for edge in vertex.edges { + if let edgeRepresentation = edge.edgeRepresentation { + edgeRepresentation.layer.removeFromSuperlayer() + edgeRepresentation.label.removeFromSuperview() + edge.edgeRepresentation = nil + } + } + } + } + + public func createNewGraph() { + self.setupVertexViews() + self.setupEdgeRepresentations() + self.addGraph() + } + + public func reset() { + for vertex in self.graph.vertices { + vertex.edges.forEach { $0.edgeRepresentation?.setDefaultColor() } + vertex.setDefaultColor() + } + } + + private func addGraph() { + for vertex in self.graph.vertices { + for edge in vertex.edges { + if let edgeRepresentation = edge.edgeRepresentation { + self.layer.addSublayer(edgeRepresentation.layer) + self.addSubview(edgeRepresentation.label) + } + } + } + for vertex in self.graph.vertices { + if let view = vertex.view { + self.addSubview(view) + } + } + } + + private func setupVertexViews() { + var level = 0 + var buildViewQueue = [self.graph.startVertex!] + let itemWidth: CGFloat = 40 + while !buildViewQueue.isEmpty { + let levelItemsCount = CGFloat(buildViewQueue.count) + let xStep = (self.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(self.didTapVertex(sender:)), for: .touchUpInside) + let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:))) + vertex.view?.addGestureRecognizer(panGesture) + } + level += 1 + buildViewQueue = self.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 self.panningView != nil { + if self.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) + } + } + } + self.panningView = vertexView + case .changed: + if self.movingVertexOutputEdges.isEmpty && self.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) >= self.frame.width + || (vertexView.frame.origin.y + vertexView.frame.height + translation.y) >= self.frame.height { + break + } + self.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 = self.path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: false) + edgeRepresentation.layer.path = newPath + CATransaction.commit() + + } + + self.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 = self.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: + self.movingVertexInputEdges = [] + self.movingVertexOutputEdges = [] + self.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] = [self.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() + } + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift new file mode 100644 index 000000000..6f4493bbe --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Edge.swift @@ -0,0 +1,12 @@ +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 + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift new file mode 100644 index 000000000..c9270b0df --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift @@ -0,0 +1,62 @@ +import UIKit + +public class Vertex: Hashable, Equatable { + private var graphColors: GraphColors = GraphColors.sharedInstance + + public var identifier: String + public var edges: [Edge] = [] + public var pathLengthFromStart: Double = Double.infinity { + didSet { + DispatchQueue.main.async { + self.view?.setPathLengthLabel(text: "\(self.pathLengthFromStart)") + } + } + } + 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 view: VertexView? + + public init(identifier: String) { + self.identifier = identifier + } + + public var hashValue: Int { + return self.identifier.hashValue + } + + public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { + if lhs.hashValue == rhs.hashValue { + return true + } + return false + } + + public func clearCache() { + self.pathLengthFromStart = Double.infinity + self.pathVerticesFromStart = [] + self.visited = false + } + + public func clearLevelInfo() { + self.level = 0 + self.levelChecked = false + } + + public func setVisitedColor() { + self.view?.backgroundColor = self.graphColors.visitedColor + self.view?.setLabelsTextColor(color: UIColor.white) + } + + public func setCheckingPathColor() { + self.view?.backgroundColor = self.graphColors.checkingColor + } + + public func setDefaultColor() { + self.view?.backgroundColor = self.graphColors.defaultVertexColor + self.view?.setLabelsTextColor(color: UIColor.black) + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift new file mode 100644 index 000000000..e8aabad27 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift @@ -0,0 +1,319 @@ +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 = GraphColors.sharedInstance + + public override init(frame: CGRect) { + super.init(frame: frame) + self.frame = frame + self.backgroundColor = self.graphColors.mainWindowBackgroundColor + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func configure(graph: Graph) { + self.graph = graph + self.graph.createNewGraph() + self.graph.delegate = self + let frame = CGRect(x: 10, y: 170, width: self.frame.width - 20, height: self.frame.height - 180) + self.graphView = GraphView(frame: frame) + self.graphView.layer.cornerRadius = 15 + + self.graphView.configure(graph: self.graph) + self.graphView.createNewGraph() + self.addSubview(self.graphView) + + self.configureCreateGraphButton() + self.configureStartVisualizationButton() + self.configureStartInteractiveVisualizationButton() + self.configureStartButton() + self.configurePauseButton() + self.configureStopButton() + self.configureComparisonLabel() + self.configureActivityIndicator() + + self.topView = UIView(frame: CGRect(x: 10, y: 10, width: self.frame.width - 20, height: 150)) + self.topView.backgroundColor = self.graphColors.topViewBackgroundColor + self.topView.layer.cornerRadius = 15 + self.addSubview(self.topView) + + self.topView.addSubview(self.createGraphButton) + self.topView.addSubview(self.startVisualizationButton) + self.topView.addSubview(self.startInteractiveVisualizationButton) + self.topView.addSubview(self.startButton) + self.topView.addSubview(self.pauseButton) + self.topView.addSubview(self.stopButton) + self.topView.addSubview(self.comparisonLabel) + self.topView.addSubview(self.activityIndicator) + } + + private func configureCreateGraphButton() { + let frame = CGRect(x: self.center.x - 200, y: 12, width: 100, height: 34) + self.createGraphButton = RoundedButton(frame: frame) + self.createGraphButton.setTitle("New graph", for: .normal) + self.createGraphButton.addTarget(self, action: #selector(self.createGraphButtonTap), for: .touchUpInside) + } + + private func configureStartVisualizationButton() { + let frame = CGRect(x: self.center.x - 50, y: 12, width: 100, height: 34) + self.startVisualizationButton = RoundedButton(frame: frame) + self.startVisualizationButton.setTitle("Auto", for: .normal) + self.startVisualizationButton.addTarget(self, action: #selector(self.startVisualizationButtonDidTap), for: .touchUpInside) + } + + private func configureStartInteractiveVisualizationButton() { + let frame = CGRect(x: self.center.x + 100, y: 12, width: 100, height: 34) + self.startInteractiveVisualizationButton = RoundedButton(frame: frame) + self.startInteractiveVisualizationButton.setTitle("Interactive", for: .normal) + self.startInteractiveVisualizationButton.addTarget(self, action: #selector(self.startInteractiveVisualizationButtonDidTap), for: .touchUpInside) + } + + private func configureStartButton() { + let frame = CGRect(x: self.center.x - 65, y: 56, width: 30, height: 30) + self.startButton = UIButton(frame: frame) + let playImage = UIImage(named: "Start.png") + self.startButton.setImage(playImage, for: .normal) + self.startButton.isEnabled = false + self.startButton.addTarget(self, action: #selector(self.didTapStartButton), for: .touchUpInside) + } + + private func configurePauseButton() { + let frame = CGRect(x: self.center.x - 15, y: 56, width: 30, height: 30) + self.pauseButton = UIButton(frame: frame) + let pauseImage = UIImage(named: "Pause.png") + self.pauseButton.setImage(pauseImage, for: .normal) + self.pauseButton.isEnabled = false + self.pauseButton.addTarget(self, action: #selector(self.didTapPauseButton), for: .touchUpInside) + } + + private func configureStopButton() { + let frame = CGRect(x: self.center.x + 35, y: 56, width: 30, height: 30) + self.stopButton = UIButton(frame: frame) + let stopImage = UIImage(named: "Stop.png") + self.stopButton.setImage(stopImage, for: .normal) + self.stopButton.isEnabled = false + self.stopButton.addTarget(self, action: #selector(self.didTapStopButton), for: .touchUpInside) + } + + private func configureComparisonLabel() { + let size = CGSize(width: 250, height: 42) + let origin = CGPoint(x: self.center.x - 125, y: 96) + let frame = CGRect(origin: origin, size: size) + self.comparisonLabel = UILabel(frame: frame) + self.comparisonLabel.textAlignment = .center + self.comparisonLabel.text = "Have fun!" + } + + private func configureActivityIndicator() { + let size = CGSize(width: 50, height: 42) + let origin = CGPoint(x: self.center.x - 25, y: 100) + let activityIndicatorFrame = CGRect(origin: origin, size: size) + self.activityIndicator = UIActivityIndicatorView(frame: activityIndicatorFrame) + self.activityIndicator.activityIndicatorViewStyle = .whiteLarge + } + + @objc private func createGraphButtonTap() { + self.comparisonLabel.text = "" + self.graphView.removeGraph() + self.graph.removeGraph() + self.graph.createNewGraph() + self.graphView.createNewGraph() + self.graph.state = .initial + } + + @objc private func startVisualizationButtonDidTap() { + self.comparisonLabel.text = "" + self.pauseButton.isEnabled = true + self.stopButton.isEnabled = true + self.createGraphButton.isEnabled = false + self.startVisualizationButton.isEnabled = false + self.startInteractiveVisualizationButton.isEnabled = false + self.createGraphButton.alpha = 0.5 + self.startVisualizationButton.alpha = 0.5 + self.startInteractiveVisualizationButton.alpha = 0.5 + + if self.graph.state == .completed { + self.graphView.reset() + self.graph.reset() + } + self.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() { + self.comparisonLabel.text = "" + self.pauseButton.isEnabled = true + self.stopButton.isEnabled = true + self.createGraphButton.isEnabled = false + self.startVisualizationButton.isEnabled = false + self.startInteractiveVisualizationButton.isEnabled = false + self.createGraphButton.alpha = 0.5 + self.startVisualizationButton.alpha = 0.5 + self.startInteractiveVisualizationButton.alpha = 0.5 + + if self.graph.state == .completed { + self.graphView.reset() + self.graph.reset() + } + + self.graph.startVertex.pathLengthFromStart = 0 + self.graph.startVertex.pathVerticesFromStart.append(self.graph.startVertex) + self.graph.state = .parsing + self.graph.parseNeighborsFor(vertex: self.graph.startVertex) { + self.graph.state = .interactiveVisualization + DispatchQueue.main.async { + self.comparisonLabel.text = "Pick next vertex" + } + } + } + + @objc private func didTapStartButton() { + self.startButton.isEnabled = false + self.pauseButton.isEnabled = true + DispatchQueue.global(qos: .utility).async { + self.graph.pauseVisualization = false + } + } + + @objc private func didTapPauseButton() { + self.startButton.isEnabled = true + self.pauseButton.isEnabled = false + DispatchQueue.global(qos: .utility).async { + self.graph.pauseVisualization = true + } + } + + @objc private func didTapStopButton() { + self.startButton.isEnabled = false + self.pauseButton.isEnabled = false + self.comparisonLabel.text = "" + self.activityIndicator.startAnimating() + if self.graph.state == .parsing || self.graph.state == .autoVisualization { + self.graph.stopVisualization = true + } else if self.graph.state == .interactiveVisualization { + self.didStop() + } + } + + private func setButtonsToInitialState() { + self.createGraphButton.isEnabled = true + self.startVisualizationButton.isEnabled = true + self.startInteractiveVisualizationButton.isEnabled = true + self.startButton.isEnabled = false + self.pauseButton.isEnabled = false + self.stopButton.isEnabled = false + self.createGraphButton.alpha = 1 + self.startVisualizationButton.alpha = 1 + self.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() { + self.graph.state = .completed + self.setButtonsToInitialState() + self.comparisonLabel.text = "Completed!" + } + + public func didTapWrongVertex() { + if !self.subviews.contains { $0 is ErrorView } { + self.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() { + self.graph.state = .initial + self.graph.stopVisualization = false + self.graph.pauseVisualization = false + self.graphView.reset() + self.graph.reset() + self.setButtonsToInitialState() + self.activityIndicator.stopAnimating() + } + + public func willStartVertexNeighborsChecking() { + DispatchQueue.main.async { + self.comparisonLabel.text = "" + } + } + + public func didFinishVertexNeighborsChecking() { + DispatchQueue.main.async { + self.comparisonLabel.text = "Pick next vertex" + } + } +} diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground b/Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground new file mode 100644 index 000000000..35968656f --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata b/Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/timeline.xctimeline b/Dijkstra Algorithm/VisualizedDijkstra.playground/timeline.xctimeline new file mode 100644 index 000000000..bf468afec --- /dev/null +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + diff --git a/README.markdown b/README.markdown index 5e6cfbfe4..eee5cbb46 100644 --- a/README.markdown +++ b/README.markdown @@ -183,6 +183,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [Single-Source Shortest Paths](Single-Source%20Shortest%20Paths%20(Weighted)/) - [Minimum Spanning Tree](Minimum%20Spanning%20Tree%20%28Unweighted%29/) on an unweighted tree - [All-Pairs Shortest Paths](All-Pairs%20Shortest%20Paths/) +- [Dijkstra's shortest path algorithm](Dijkstra%20Algorithm/) ## Puzzles From 8efb7354645763fce0823ec74c2fe3ffb904f4df Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Tue, 4 Apr 2017 10:25:36 +0100 Subject: [PATCH 0251/1039] MIT License --- MinimumCoinChange/LICENSE | 222 ++++---------------------------------- 1 file changed, 21 insertions(+), 201 deletions(-) diff --git a/MinimumCoinChange/LICENSE b/MinimumCoinChange/LICENSE index 8dada3eda..fda6e6146 100755 --- a/MinimumCoinChange/LICENSE +++ b/MinimumCoinChange/LICENSE @@ -1,201 +1,21 @@ - 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. +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. From 63257f629f99ba76a7997a1e0b18b8236cefa57b Mon Sep 17 00:00:00 2001 From: Richard Date: Tue, 4 Apr 2017 13:37:53 -0700 Subject: [PATCH 0252/1039] fixed typos in readme --- Strassen Matrix Multiplication/README.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Strassen Matrix Multiplication/README.markdown b/Strassen Matrix Multiplication/README.markdown index fa822d310..07ce534b2 100644 --- a/Strassen Matrix Multiplication/README.markdown +++ b/Strassen Matrix Multiplication/README.markdown @@ -18,7 +18,7 @@ matrix A = |1 2|, matrix B = |5 6| 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 48| +|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. @@ -72,7 +72,7 @@ Then, for each row in A and column in B, we take the dot product of the ith row ```swift for k in 0..) -> Matrix { for i in 0.. Date: Tue, 4 Apr 2017 14:07:19 -0700 Subject: [PATCH 0253/1039] Update README.markdown --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 5e6cfbfe4..067de2418 100644 --- a/README.markdown +++ b/README.markdown @@ -106,6 +106,7 @@ Bad sorting algorithms (don't use these!): - Statistics - [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%20Multiplication%20Matrix). Efficient way to handle matrix multiplication. ### Machine learning From bbba068205500a62943a601540d4dfba205586f2 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 4 Apr 2017 14:09:02 -0700 Subject: [PATCH 0254/1039] Updated a link to Strassen Multiplication Matrix. --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 067de2418..29fc9d748 100644 --- a/README.markdown +++ b/README.markdown @@ -106,7 +106,7 @@ Bad sorting algorithms (don't use these!): - Statistics - [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%20Multiplication%20Matrix). Efficient way to handle matrix multiplication. +- [Strassen's Multiplication Matrix](Strassen%20Matrix%20Multiplication/). Efficient way to handle matrix multiplication. ### Machine learning From 20d7c1fd66b93c2a3933abe5d048169cea888ced Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Tue, 4 Apr 2017 17:46:46 -0700 Subject: [PATCH 0255/1039] Revisions in README.md # Coherence & Sentence structures # Grammar and spelling --- DiningPhilosophers/README.md | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index ec1611c65..0bf4f28ce 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -1,22 +1,22 @@ # Dining Philosophers -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) +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 an example problem often used in concurrent algorithm design to illustrate synchronization issues and techniques for resolving them. +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 use GCD Dispatch and Semaphone on Swift cross platform +This Swift implementation is based on the Chandy/Misra solution, and it uses the GCD Dispatch and Semaphone 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. However, a philosopher can only eat spaghetti when they have both left and right forks. Each fork can be held by only one philosopher and so a philosopher can use the fork only if it is not being used by another philosopher. After an individual 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 cannot start eating before getting both forks. +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. @@ -26,35 +26,32 @@ This is an illustration of an dinining 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 on the Chandy/Misra solution that more generally allows for arbitrary agents to contend for an arbitrary number of resources in a completely distributed scenario with no needs for a central authority to control the locking and serialization of resources. - -However, it is very important to note here that this solution violates the requirement that "the philosophers do not speak to each other" (due to the request messages). +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 needs 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. For all such forks the philosopher does not have, they send a request message. -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. +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 will solve an arbitrarily large problem. +This solution also allows for a large degree of concurrency, and it will solve an arbitrarily large problem. -It also solves the starvation problem. The clean / dirty labels act as a way of giving 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. Chandy and Misra's solution is more flexible than that, but has an element tending in that direction. +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. -In their analysis they derive a system of preference levels from the distribution of the forks and their clean/dirty states. They show that this system may describe an acyclic graph, and if so, the operations in their 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, like all philosophers holding their left side forks, then the graph is cyclic at the outset, and their solution cannot prevent a deadlock. Initializing the system so that philosophers with lower IDs have dirty forks ensures the graph is initially acyclic. +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 GCD and Semaphore tecnique and it could be built on both macOS and Linux. +This Swift 3.0 implementation of the Chandy/Misra solution is based on the GCD and Semaphore tecnique 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 simply used in order to keep the main thread on wait forever and let the Philosophers contienue forever in their alternate think and eat cycle. - +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 From 56c5ecf2c5c6baf4b7442dbf46db5c9d13fda523 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Tue, 4 Apr 2017 19:31:26 -0700 Subject: [PATCH 0256/1039] Revisions in README.markdown 1- Coherence, Sentence structure, & Consistency 2- Grammar, Word choice, & Spelling --- Huffman Coding/README.markdown | 82 +++++++++++++++++----------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 4e6f75514..69e105c87 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -1,12 +1,12 @@ # Huffman Coding -The idea: Encode objects that occur often with a smaller number of bits than objects that occur less frequently. +The idea: To encode objects that occur with a smaller number of bits than objects that occur less frequently. -Although you can encode any type of objects with this scheme, it's most common to compress a stream of bytes. Let's say you have the following text, where each character is one byte: +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 clearly see that some bytes occur more than others: +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 @@ -41,11 +41,11 @@ Now if we replace the original bytes with these bit strings, the compressed outp 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%! -But hold on... 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 doesn't know how to interpret the bits. Because of the overhead of this frequency table (about 1 kilobyte), it doesn't really pay to use Huffman encoding on very small inputs. +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 it creates a binary tree that describes the bit strings for each of the input bytes. +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: @@ -53,17 +53,17 @@ For our example, the tree looks like this: 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 either say "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. +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 traverse 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. +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`). So the Huffman code for `c` is `0011`. +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 we get 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`. +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's 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're dealing in bits, so we need to translate between the two. +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 { @@ -92,11 +92,11 @@ public class BitWriter { } ``` -To add a bit to the `NSData` you call `writeBit()`. This stuffs each new bit into the `outByte` variable. Once you've written 8 bits, `outByte` gets added to the `NSData` object for real. +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. -We'll use a similar helper object for reading individual bits from `NSData`: +Here is a similar helper object for reading individual bits from `NSData`: ```swift public class BitReader { @@ -122,15 +122,15 @@ public class BitReader { } ``` -This works in a similar fashion. We 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`. +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:** It's no big deal if you're unfamiliar with this sort of bit manipulation. Just know that these two helper objects make it simple for us to write and read bits and not worry about all the messy stuff of making sure they end up in the right place. +> **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 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 how often each of these bytes occurs in the input data. +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're going to need to build a tree anyway, we might as well store the frequency table as the leaves of the tree. +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: @@ -152,9 +152,9 @@ class Huffman { } ``` -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, however, these nodes don't to use pointers to refer to each other but 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.) +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 `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'll add more nodes as we build up the actual tree. For the moment there isn't a tree yet, just 256 separate leaf nodes with no connections between them. All the node counts are 0. +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: @@ -170,13 +170,13 @@ We use the following method to count how often each byte occurs in the input dat } ``` -This steps through the `NSData` object from beginning to end and for each byte increments the `count` of the corresponding leaf node. That's all there is to it. After `countByteFrequency()` completes, the first 256 `Node` objects in the `tree` array represent the frequency table. +This steps through the `NSData` object from beginning to end and for each byte increments the `count` of the corresponding leaf node. After `countByteFrequency()` completes, the first 256 `Node` objects in the `tree` array represent the frequency table. -Now, I mentioned that in order to decompress a Huffman-encoded block of data, you also need to have the original frequency table. If you were writing the compressed data to a file, then somewhere in the file you'd include the frequency table. +To decompress a Huffman-encoded block of data, we need to have the original frequency table. If we were writing the compressed data to a file, then somewhere in the file we should include the frequency table. -You could simply dump the first 256 elements from the `tree` array but that's not very efficient. It's likely that not all of these 256 elements will be used, plus you don't need to serialize the `parent`, `right`, and `left` pointers. All we need is the frequency information, not the entire tree. +We could dump the first 256 elements from the `tree` array, but that is not efficient. Not all of these 256 elements will be used, and we do not need to serialize the `parent`, `right`, and `left` pointers. All we need is the frequency information and not the entire tree. -Instead, we'll add a method to export the frequency table without all the pieces we don't need: +Instead, we will add a method to export the frequency table without all the pieces we do not need: ```swift struct Freq { @@ -193,7 +193,7 @@ Instead, we'll add a method to export the frequency table without all the pieces } ``` -The `frequencyTable()` method looks at those first 256 nodes from the tree but keeps only those that are actually 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 `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 @@ -201,7 +201,7 @@ 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 therefore they are highest up in the tree. +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: @@ -209,7 +209,7 @@ To build the tree, we do the following: 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 very fast. Here, we repeatedly need to find the node with the smallest count. +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: @@ -252,15 +252,15 @@ Here is how it works step-by-step: 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're done with `node1` and `node2`, but the `parentNode` still need to be connected to other nodes in 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're done. +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 quite slow, **O(n^2)**. Using the priority queue, the running time is only **O(n log n)** where **n** is the number of nodes. +> **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. @@ -286,11 +286,11 @@ Now that we know how to build the compression tree from the frequency table, we } ``` -This first calls `countByteFrequency()` to build the frequency table, then `buildTree()` to put together the compression tree. It also creates a `BitWriter` object for writing individual bits. +This first calls `countByteFrequency()` to build the frequency table and then calls `buildTree()` to put together the compression tree. It also creates a `BitWriter` object for writing individual bits. -Then it loops through the entire input and for each byte calls `traverseTree()`. That method will step through the tree nodes and for each node write a 1 or 0 bit. Finally, we return the `BitWriter`'s data object. +Then, it loops through the entire input and calls `traverseTree()`for each byte. This method will step through the tree nodes and for each node write a 1 or 0 bit. Finally, we return the `BitWriter`'s data object. -> **Note:** Compression always requires two passes through the entire input data: first to build the frequency table, second to convert the bytes to their compressed bit sequences. +> **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: @@ -309,15 +309,15 @@ The interesting stuff happens in `traverseTree()`. This is a recursive method: } ``` -When we call this method from `compressData()`, the `nodeIndex` parameter is the array index of the leaf node for the byte that we're about to encode. This method recursively walks the tree from a leaf node up to the root, and then back again. +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're 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's the right node, we emit a 0. +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 aren't 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're going in is enough to determine what bit value to write. +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: @@ -332,9 +332,9 @@ if let originalData = s1.dataUsingEncoding(NSUTF8StringEncoding) { ## Decompression -Decompression is pretty much compression in reverse. However, the compressed bits are useless to us without the frequency table. Earlier you saw the `frequencyTable()` method that returns an array of `Freq` objects. The idea is that if you were saving the compressed data into a file or sending it across the network, you'd also save that `[Freq]` array along with it. +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. Fortunately, this is pretty easy: +We first need some way to turn the `[Freq]` array back into a compression tree: ```swift fileprivate func restoreTree(fromTable frequencyTable: [Freq]) { @@ -349,7 +349,7 @@ We first need some way to turn the `[Freq]` array back into a compression tree. 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 returns the original data: +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 { @@ -385,13 +385,13 @@ This also uses a helper method to traverse the tree: } ``` -`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. +`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's how you would use the decompression method: +Here is how we use the decompression method: ```swift let frequencyTable = huffman1.frequencyTable() @@ -402,9 +402,9 @@ Here's how you would use the decompression method: let s2 = String(data: decompressedData, encoding: NSUTF8StringEncoding)! ``` -First you 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 you compressed in the first place. +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. -You can see how this works in more detail in the Playground. +we can see how this works in more detail in the Playground. ## See also From d70f40ed8668e60584dc1bd9d5b859b7ad2e91de Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Wed, 5 Apr 2017 10:34:21 -0700 Subject: [PATCH 0257/1039] Revisions in README.markdown I have revised your document to be simplified and concise. --- Array2D/README.markdown | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/Array2D/README.markdown b/Array2D/README.markdown index d67079691..88f25c99a 100644 --- a/Array2D/README.markdown +++ b/Array2D/README.markdown @@ -1,14 +1,14 @@ # Array2D -In C and Objective-C you can write the following line, +In C and Objective-C, you can write the following line, int cookies[9][7]; -to make a 9x7 grid of cookies. This would create a two-dimensional array of 63 elements. To find the cookie at column 3, row 6, you'd write: +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]; -Unfortunately, you can't write the above in Swift. To create a multi-dimensional array in Swift you'd have to do something like this: +This statement is not acceptable in Swift. To create a multi-dimensional array in Swift, you can write: ```swift var cookies = [[Int]]() @@ -21,19 +21,19 @@ for _ in 1...9 { } ``` -And then to find a cookie: +Then, to find a cookie, you can write: ```swift let myCookie = cookies[3][6] ``` -Actually, you could create the array in a single line of code, like so: +You can also create the array in a single line of code: ```swift var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9) ``` -but that's just ugly. To be fair, you can hide the ugliness in a helper function: +This looks complicated, but can simplfy it in a helper function: ```swift func dim(_ count: Int, _ value: T) -> [T] { @@ -41,13 +41,13 @@ func dim(_ count: Int, _ value: T) -> [T] { } ``` -And then creating the array looks like this: +Then, you can create the array: ```swift var cookies = dim(9, dim(7, 0)) ``` -Swift infers that the datatype of the array should be `Int` because you specified `0` as the default value of the array elements. To use a string instead, you'd write: +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")) @@ -59,9 +59,9 @@ The `dim()` function makes it easy to go into even more dimensions: var threeDimensions = dim(2, dim(3, dim(4, 0))) ``` -The downside of using multi-dimensional arrays in this fashion -- actually, multiple nested arrays -- is that it's easy to lose track of what dimension represents what. +The downside of using multi-dimensional arrays or multiple nested arrays in this way is to lose track of what dimension represents what. -So instead let's create our own type that acts like a 2-D array and that is more convenient to use. Here it is, short and sweet: +Instead, you can create your own type that acts like a 2-D array which is more convenient to use: ```swift public struct Array2D { @@ -92,26 +92,24 @@ public struct Array2D { `Array2D` is a generic type, so it can hold any kind of object, not just numbers. -To create an instance of `Array2D` you'd write: +To create an instance of `Array2D`, you can write: ```swift var cookies = Array2D(columns: 9, rows: 7, initialValue: 0) ``` -Thanks to the `subscript` function, you can do the following to retrieve an object from the array: +By using the `subscript` function, you can retrieve an object from the array: ```swift let myCookie = cookies[column, row] ``` -Or change it: +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 don't have to worry about that; you only have to think in terms of "column" and "row", and let `Array2D` figure out the details for you. That's the advantage of wrapping primitive types into a wrapper class or struct. - -And that's all there is to it. +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* From 777bf7b948e75d77bbac8cbba5dc40716c6b5d61 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 6 Apr 2017 16:34:58 +0300 Subject: [PATCH 0258/1039] Deleted unnecessary code and added comments --- .../Dijkstra.playground/Contents.swift | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift index 8d600d577..13087a8f9 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -3,19 +3,15 @@ import Foundation import UIKit -open class ProductVertex: Vertex {} - open class Vertex: Hashable, Equatable { open var identifier: String! open var neighbors: [(Vertex, Double)] = [] open var pathLengthFromStart: Double = Double.infinity open var pathVerticesFromStart: [Vertex] = [] -// open var point: CGPoint! - public init(identifier: String/*, point: CGPoint*/) { + public init(identifier: String) { self.identifier = identifier -// self.point = point } open var hashValue: Int { @@ -77,7 +73,9 @@ public class Dijkstra { var _vertices: Set = Set() func createNotConnectedVertices() { - for i in 0..<15 { + //change this value to increase or decrease amount of vertices in the graph + let numberOfVerticesInGraph = 15 + for i in 0.. Vertex { 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) -let offset = Int(arc4random_uniform(UInt32(_vertices.count))) -let index = _vertices.index(_vertices.startIndex, offsetBy: offset) -let startVertex = _vertices[index] + +//decide which vertex will be the starting one +let startVertex = randomVertex() + +//ask algorithm to find shortest paths from start vertex to all others dijkstra.findShortestPaths(from: startVertex) + +//printing results let destinationVertex = randomVertex(except: startVertex) -destinationVertex.pathLengthFromStart -destinationVertex.pathVerticesFromStart +print(destinationVertex.pathLengthFromStart) +var pathVerticesFromStartString: [String] = [] +for vertex in destinationVertex.pathVerticesFromStart { + pathVerticesFromStartString.append(vertex.identifier) +} +print(pathVerticesFromStartString.joined(separator: "->")) From 11fdc6ca756b4d402e807a0f9b6063fd6f38dab1 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Thu, 6 Apr 2017 11:57:03 -0700 Subject: [PATCH 0259/1039] Revisions in README.markdown I have revised your document to be more concise. --- Graph/README.markdown | 62 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index a2531e808..bc33b044a 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -1,26 +1,26 @@ # Graph -A graph is something that looks like this: +A graph looks like the following picture: ![A graph](Images/Graph.png) -In computer-science lingo, a graph is a set of *vertices* paired with a set of *edges*. The vertices are the round things and the edges are the lines between them. Edges connect a vertex to other vertices. +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 also called "nodes" and edges are also called "links". +> **Note:** Vertices are sometimes called "nodes", and edges are called "links". -For example, a graph can represent a social network. Each person is a vertex, and people who know each other are connected by edges. A somewhat historically inaccurate example: +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 come in all kinds of 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. +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*. So far the edges you've seen have been undirected, so 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. +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 would indicate 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). +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) @@ -28,51 +28,51 @@ 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/). Both can be considered graphs, but in a simpler form. After all, they have vertices (nodes) and edges (links). +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 very first graph I showed you contained *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. +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 very common type of graph is the *directed acyclic graph* or DAG: +Another common type of graph is the *directed acyclic graph* or DAG: ![DAG](Images/DAG.png) -Like a tree this does not have any cycles in it (no matter where you start, there is no path back to the starting vertex), but unlike a tree the edges are directional and the shape doesn't necessarily form a hierarchy. +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 graphs are an extremely useful data structure. +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 some programming problem where you can represent some of your data as vertices and some of it as edges between those vertices, 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. +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, let's say 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: +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. Here, an edge between two vertices means that the source task must be completed before the destination task can start. So task C cannot start before B and D are finished, and B nor D can start before A is finished. +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're 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 "relationship". +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're a musician you might appreciate this graph: +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's 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. +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're probably already using graphs without even knowing it. Your data model is also a graph (from Apple's Core Data documentation): +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 that's 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: +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're going to learn any data structure, it should be the graph and the vast collection of standard graph algorithms. +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 objects and a bunch of edge objects. But how do you describe these in code? +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. @@ -80,9 +80,9 @@ There are two main strategies: adjacency list and adjacency matrix. ![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. +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, column for vertex B would have value 5.6: +**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) @@ -103,7 +103,7 @@ Let *V* be the number of vertices in the graph, and *E* the number of edges. Th 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. -We'll show you sample implementations of both adjacency list and adjacency matrix. +Here are sample implementations of both adjacency list and adjacency matrix: ## The code: edges and vertices @@ -137,9 +137,9 @@ It stores arbitrary data with a generic type `T`, which is `Hashable` to enforce ## The code: graphs -> **Note:** There are many, 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're 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. +> **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's an example of a very simple graph: +Here is an example of a simple graph: ![Demo](Images/Demo1.png) @@ -165,7 +165,7 @@ for graph in [AdjacencyMatrixGraph(), AdjacencyListGraph()] { } ``` -As mentioned earlier, to create an undirected edge you need to make two directed edges. If we wanted undirected graphs, we'd call this method instead, which takes care of that work for us: +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) @@ -198,7 +198,7 @@ private class EdgeList where T: Equatable, T: Hashable { } ``` -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: +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 { @@ -231,7 +231,7 @@ where the general form `a -> [(b: w), ...]` means an edge exists from `a` to `b` ## The code: adjacency matrix -We'll 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`. +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: @@ -277,6 +277,6 @@ Then the adjacency matrix looks like this: ## See also -This article described what a graph is and how you can implement the basic data structure. But we have many more articles on practical uses for graphs, so check those out too! +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* From 0a77b0685a7c26512377ba57ed02d2ee4644a880 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Thu, 6 Apr 2017 13:57:39 -0700 Subject: [PATCH 0260/1039] Revisions in README.markdown I have revised your document to be more concise. --- Binary Search Tree/README.markdown | 138 ++++++++++++++--------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index b3b955c61..14ef931b9 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -2,7 +2,7 @@ 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. -If you don't know what a tree is or what it is for, then [read this first](../Tree/). +For more iformation about a tree, [read this first](../Tree/). ## "Always sorted" property @@ -12,56 +12,56 @@ Here is an example of a valid binary search tree: 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. +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. -Say we want to insert the new value `9`: +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've now arrived at a point where there are no more values to compare with. A new node for `9` is inserted at that location. +- 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. -The tree now looks like this: +Here is the tree after inserting the new value `9`: ![After adding 9](Images/Tree2.png) -There is always only one possible place where the new element can be inserted in the tree. Finding this place is usually pretty quick. It takes **O(h)** time, where **h** is the height of the tree. +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 in a way such that whenever we query it, we can quickly check if a value is in the tree. +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 essentially perform the same steps as with insertion: +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. -- And if the value is equal to the current node, we've found it! +- 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're looking for, or run out of nodes to look at. +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. -If we were looking for the value `5` in the example, it would go as follows: +Here is an example for searching the value `5`: ![Searching the tree](Images/Searching.png) -Thanks to the structure of the tree, searching is really fast. 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.) +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 don't want to look at just a single node, but at all of them. +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. +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. -Once again, this happens recursively. +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`: @@ -69,7 +69,7 @@ If you traverse a binary search tree in-order, it looks at all the nodes as if t ## Deleting nodes -Removing nodes is also 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 following example, 10 is removed and replaced with either 9 (Figure 2), or 11 (Figure 3). +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) @@ -80,9 +80,9 @@ Note the replacement needs to happen when the node has at least one child. If it ## 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'll show you how to make a class-based version but we'll also look at how to make one using enums. +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's a first stab at a `BinarySearchTree` class: +Here is an example for a `BinarySearchTree` class: ```swift public class BinarySearchTree { @@ -133,21 +133,21 @@ public class BinarySearchTree { } ``` -This class describes just a single node, not the entire tree. It's 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. +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's how you'd use it: +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 doesn't 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`. +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 optionals, 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. +> **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 pretty useless, so here is how you would add new nodes to the tree: +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) { @@ -173,9 +173,9 @@ Like so many other tree operations, insertion is easiest to implement with recur 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 to sure this remains a valid binary tree! +> **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'd do: +To build the complete tree from the example you can do: ```swift let tree = BinarySearchTree(value: 7) @@ -186,7 +186,7 @@ tree.insert(9) tree.insert(1) ``` -> **Note:** For reasons that will become clear later, you should insert the numbers in a somewhat random order. If you insert them in sorted order, the tree won't have the right shape. +> **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: @@ -210,7 +210,7 @@ The first value in the array becomes the root of the tree. ### Debug output -When working with somewhat complicated data structures such as this, it's useful to have human-readable debug output. +When working with complicated data structures, it is useful to have human-readable debug output. ```swift extension BinarySearchTree: CustomStringConvertible { @@ -236,11 +236,11 @@ The root node is in the middle. With some imagination, you should see that this ![The tree](Images/Tree2.png) -By the way, you may be wondering what happens when you insert duplicate items? We always insert those in the right branch. Try it out! +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! Being able to find items quickly is the entire purpose of a binary search tree. :-) +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()`: @@ -258,11 +258,11 @@ Here is the implementation of `search()`: 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. -Of course, 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. +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's very conveniently done with optional chaining; when you write `left?.search(value)` it automatically returns nil if `left` is nil. There's no need to explicitly check for this with an `if` statement. +> **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: +Searching is a recursive process, but you can also implement it with a simple loop instead: ```swift public func search(value: T) -> BinarySearchTree? { @@ -280,9 +280,9 @@ Searching is a recursive process but you can also implement it with a simple loo } ``` -Verify for yourself that you understand that these two implementations are equivalent. Personally, I prefer to use iterative code over recursive code but your opinion may differ. ;-) +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's how to test searching: +Here is how to test searching: ```swift tree.search(5) @@ -291,9 +291,9 @@ tree.search(7) tree.search(6) // nil ``` -The first three lines all return the corresponding `BinaryTreeNode` object. The last line returns `nil` because there is no node with value `6`. +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()` always returns the "highest" node. That makes sense, because we start searching from the root downwards. +> **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 @@ -319,9 +319,9 @@ Remember there are 3 different ways to look at all nodes in the tree? Here they } ``` -They all do pretty much the same thing but in different orders. Notice once again that all the work is done recursively. Thanks to Swift's optional chaining, the calls to `traverseInOrder()` etc are ignored when there is no left or right child. +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 from the tree sorted from low to high you can write: +To print out all the values of the tree sorted from low to high you can write: ```swift tree.traverseInOrder { value in print(value) } @@ -336,7 +336,7 @@ This prints the following: 9 10 -You can also add things like `map()` and `filter()` to the tree. For example, here's an implementation of map: +You can also add things like `map()` and `filter()` to the tree. For example, here is an implementation of map: ```swift @@ -365,11 +365,11 @@ This turns the contents of the tree back into a sorted array. Try it out in the tree.toArray() // [1, 2, 5, 7, 9, 10] ``` -As an exercise for yourself, see if you can implement filter and reduce. +As an exercise, see if you can implement filter and reduce. ### Deleting nodes -We can make the code much more readable by defining some helper functions. +We can make the code more readable by defining some helper functions. ```swift private func reconnectParentToNode(node: BinarySearchTree?) { @@ -384,7 +384,7 @@ We can make the code much more readable by defining some helper functions. } ``` -Making changes to the tree involves changing a bunch of `parent` and `left` and `right` pointers. This function helps with that. It takes the parent of the current node -- that is `self` -- and connects it to another node. Usually that other node will be one of the children of `self`. +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: @@ -407,7 +407,7 @@ We also need a function that returns the minimum and maximum of a node: ``` -The rest of the code is pretty self-explanatory: +The rest of the code is self-explanatory: ```swift @discardableResult public func remove() -> BinarySearchTree? { @@ -457,7 +457,7 @@ Recall that the height of a node is the distance to its lowest leaf. We can calc 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 a lot more concise. +> **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: @@ -479,7 +479,7 @@ You can also calculate the *depth* of a node, which is the distance to the root. } ``` -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. Example: +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) { @@ -489,11 +489,11 @@ if let node9 = tree.search(9) { ### Predecessor and successor -The binary search tree is always "sorted" but that doesn't mean that consecutive numbers are actually next to each other in the tree. +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 can't 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`. +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: @@ -512,11 +512,11 @@ The `predecessor()` function returns the node whose value precedes the current v } ``` -It's 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. +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. -However, if there is no left subtree then we have to look at our parent nodes until we find a smaller value. So 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`. +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 exact same way but mirrored: +The code for `successor()` works the same way but mirrored: ```swift public func successor() -> BinarySearchTree? { @@ -535,11 +535,11 @@ The code for `successor()` works the exact same way but mirrored: Both these methods run in **O(h)** time. -> **Note:** There is a cool 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! +> **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, like so: +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) { @@ -547,7 +547,7 @@ if let node1 = tree.search(1) { } ``` -The value of the root node is `7`, so a node with value `100` is supposed to be in the tree's right branch. However, you're 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! +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. @@ -562,7 +562,7 @@ You can check whether a tree is a valid binary search tree with the following me } ``` -This verifies that the left branch does indeed contain values that are less than the current node's value, and that the right branch only contains values that are larger. +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: @@ -577,11 +577,11 @@ if let node1 = tree.search(1) { ## The code (solution 2) -We've implemented the binary tree node as a class but you can also use an enum. +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. +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's how you'd make a binary search tree using an enum: +Here is how you can make a binary search tree using an enum: ```swift public enum BinarySearchTree { @@ -597,9 +597,9 @@ The enum has three cases: - `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 don't have a reference to their parent node. It's not a major impediment but it will make certain operations slightly more cumbersome to implement. +> **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. -As usual, we'll implement most functionality recursively. We'll treat each case of the enum slightly differently. For example, this is how you could calculate the number of nodes in the tree and the height of the tree: +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 { @@ -655,7 +655,7 @@ tree = tree.insert(9) tree = tree.insert(1) ``` -Notice that each time you insert something, you get back a completely new tree object. That's why you need to assign the result back to the `tree` variable. +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: @@ -678,7 +678,7 @@ Here is the all-important search function: } ``` -As you can see, most of these functions have the same structure. +Most of these functions have the same structure. Try it out in a playground: @@ -688,7 +688,7 @@ tree.search(1) tree.search(11) // nil ``` -To print the tree for debug purposes you can use this method: +To print the tree for debug purposes, you can use this method: ```swift extension BinarySearchTree: CustomDebugStringConvertible { @@ -703,21 +703,21 @@ extension BinarySearchTree: CustomDebugStringConvertible { } ``` -When you do `print(tree)` it will look something like this: +When you do `print(tree)`, it will look like this: ((1 <- 2 -> 5) <- 7 -> (9 <- 10 -> .)) -The root node is in the middle; a dot means there is no child at that position. +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 roughly the same number of nodes. In that case, the height of the tree is *log(n)*, where *n* is the number of nodes. That's the ideal situation. +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. -However, if one branch is significantly longer than the other, searching becomes very slow. We end up checking way more values than we'd ideally have to. In the worst case, the height of the tree can become *n*. Such a tree acts more like a [linked list](../Linked%20List/) than a binary search tree, with performance degrading to **O(n)**. Not good! +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 quite nicely. But it doesn't guarantee success, nor is it always practical. +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. See [AVL tree](../AVL%20Tree) and [red-black tree](../Red-Black%20Tree) for examples. +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 From 499bd86cd7ffab858dac481735b532f1789c0ab9 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Thu, 6 Apr 2017 17:07:38 -0700 Subject: [PATCH 0261/1039] Revisions in README.markdown I have revised your document to be more concise. Some words and phrases are removed or replaced due to redundancy. --- Queue/README.markdown | 52 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Queue/README.markdown b/Queue/README.markdown index 9efce66b9..8938e0cf1 100644 --- a/Queue/README.markdown +++ b/Queue/README.markdown @@ -2,11 +2,11 @@ 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 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. +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 also the first one to come out again. It's only fair! (A very similar data structure, the [stack](../Stack/), is LIFO or last-in first-out.) +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.) -For example, let's enqueue a number: +Here is an example to enqueue a number: ```swift queue.enqueue(10) @@ -38,11 +38,11 @@ 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 isn't important, you might as well use a [stack](../Stack/) instead of a queue. Stacks are simpler and faster. +> **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 very simplistic implementation of a queue in Swift. It's just a wrapper around an array that lets you enqueue, dequeue, and peek at the front-most item: +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 { @@ -74,11 +74,11 @@ public struct Queue { } ``` -This queue works just fine but it is not optimal. +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. So that's great. +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 so because an array in Swift always has some empty space at the end. If we do the following: +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() @@ -95,13 +95,13 @@ where `xxx` is memory that is reserved but not filled in yet. Adding a new eleme [ "Ada", "Steve", "Tim", "Grace", xxx, xxx ] -This is simply matter of copying memory from one place to another, a constant-time operation. +This results by copying memory from one place to another which is a constant-time operation. -Of course, there are only a limited number of such 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. +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, so it's relatively slow. But since it happens only every so often, the time for appending a new element to the end of the array is still **O(1)** on average, or **O(1)** "amortized". +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 slightly different. To dequeue we remove the element from the *beginning* of the array, not the end. This is always an **O(n)** operation because it requires all remaining array elements to be shifted in memory. +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"`: @@ -112,13 +112,13 @@ In our example, dequeuing the first element `"Ada"` copies `"Steve"` in the plac / / / 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... +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 more efficient, we can use the same trick of reserving some extra free space, but this time do it at the front of the array. We're going to have to write this code ourselves as the built-in Swift array doesn't support this out of the box. +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 idea is as follows: whenever we dequeue an item, we don't 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: +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 ] @@ -126,13 +126,13 @@ After dequeuing `"Steve"`, the array is: [ xxx, xxx, "Tim", "Grace", xxx, xxx ] -These empty spots at the front never get reused for anything, so they're wasting space. Every so often you can trim the array by moving the remaining elements to the front again: +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 so it's an **O(n)** operation. But because it only happens once in a while, dequeuing is now **O(1)** on average. +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 could implement this version of `Queue`: +Here is how you can implement this version of `Queue`: ```swift public struct Queue { @@ -176,9 +176,9 @@ public struct Queue { } ``` -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 `head` variable is the index in the array of the front-most object. +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 now the next item has become the front one. +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: @@ -190,9 +190,9 @@ to this: [ xxx, "Steve", "Tim", "Grace", xxx, xxx ] head -It's like some weird supermarket where the people in the checkout lane don't shuffle forward towards the cash register, but the cash register moves up the queue. +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. -Of course, 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: +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) @@ -202,11 +202,11 @@ Of course, if we never remove those empty spots at the front then the array will } ``` -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 don't want to resize it all the time, so there must be at least 50 elements in the array before we try to trim it. +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: +To test this in a playground, do the following: ```swift var q = Queue() @@ -251,11 +251,11 @@ 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` isn't much more complicated than the first one but dequeuing is now also an **O(1)** operation, just because we were a bit smarter about how we used the array. +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 other ways to create a queue. Alternative implementations use a [linked list](../Linked%20List/), a [circular buffer](../Ring%20Buffer/), or a [heap](../Heap/). +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. From 0f4baf57b3485af6391de0bc06f626e8efc88c82 Mon Sep 17 00:00:00 2001 From: Parva9eh Date: Thu, 6 Apr 2017 17:38:53 -0700 Subject: [PATCH 0262/1039] Revisions in README.markdown I have revised your document to be more concise. --- Selection Sort/README.markdown | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Selection Sort/README.markdown b/Selection Sort/README.markdown index cb8ed59c2..daebc64f4 100644 --- a/Selection Sort/README.markdown +++ b/Selection Sort/README.markdown @@ -1,6 +1,6 @@ # Selection Sort -Goal: Sort an array from low to high (or high to low). +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. @@ -10,20 +10,20 @@ This is similar to [insertion sort](../Insertion%20Sort/), but the difference is It works as follows: -- Find the lowest number in the array. You 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 you've found with the number at index 0. Now the sorted portion consists of just the number at index 0. +- 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 it with the number at index 1. Now the sorted portion contains two numbers and extends from index 0 to index 1. +- 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 so on... until no numbers remain to be sorted. +- 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's called a "selection" sort, because at every step you search through the rest of the array to select the next lowest number. +It nis called a "selection" sort because at every step you search through the rest of the array to select the next lowest number. ## An example -Let's say 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. +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: @@ -43,7 +43,7 @@ Again, we look for the lowest number, starting from the `|` bar. We find `4` and [ 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's no need to swap `5` with itself and we simply move forward: +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 ] * @@ -52,7 +52,7 @@ This process repeats until the array is sorted. Note that everything to the left [ 3, 4, 5, 6, 8 |] -As you can see, selection sort is an *in-place* sort because everything happens in the same array; no additional memory is necessary. 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 isn't stable). +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 @@ -90,9 +90,9 @@ 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's not much point to sorting it. +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 Swift's own `sort()`, the `selectionSort()` function will return a sorted *copy* of the original array. +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. @@ -100,17 +100,17 @@ A step-by-step explanation of how the code works: 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, 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!) +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 always be in the correct position because at that point there are no other smaller elements left. +> **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 types. +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 -Selection sort is easy to understand but it performs quite badly, **O(n^2)**. It's worse than [insertion sort](../Insertion%20Sort/) but better than [bubble sort](../Bubble%20Sort/). The killer is finding the lowest element in the rest of the array. This takes up a lot of time, especially since the inner loop will be performed over and over. +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 . -[Heap sort](../Heap%20Sort/) uses the same principle as selection sort but has a really fast method for finding the minimum value in the rest of the array. Its performance is **O(n log n)**. +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 From 8d84f6fdb9996e0a8b84360fd54eeb9892965e04 Mon Sep 17 00:00:00 2001 From: vincentngo Date: Thu, 6 Apr 2017 22:25:17 -0400 Subject: [PATCH 0263/1039] Spelling error --- Binary Search Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Binary Search Tree/README.markdown b/Binary Search Tree/README.markdown index 14ef931b9..80c2df7df 100644 --- a/Binary Search Tree/README.markdown +++ b/Binary Search Tree/README.markdown @@ -2,7 +2,7 @@ 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 iformation about a tree, [read this first](../Tree/). +For more information about a tree, [read this first](../Tree/). ## "Always sorted" property From 8080f271109d494eed485137392363bed2d462f4 Mon Sep 17 00:00:00 2001 From: Jacopo Mangiavacchi Date: Fri, 7 Apr 2017 19:18:26 +0200 Subject: [PATCH 0264/1039] Fix and optimizations --- .../Sources/MinimumCoinChange.swift | 89 +++++++++++-------- .../MinimumCoinChangeTests.swift | 20 +++-- 2 files changed, 66 insertions(+), 43 deletions(-) diff --git a/MinimumCoinChange/Sources/MinimumCoinChange.swift b/MinimumCoinChange/Sources/MinimumCoinChange.swift index db7edecbe..c995063ab 100644 --- a/MinimumCoinChange/Sources/MinimumCoinChange.swift +++ b/MinimumCoinChange/Sources/MinimumCoinChange.swift @@ -1,5 +1,5 @@ // -// Minimum Coin Change Problem +// Minimum Coin Change Problem Playground // Compare Greedy Algorithm and Dynamic Programming Algorithm in Swift // // Created by Jacopo Mangiavacchi on 04/03/17. @@ -7,70 +7,85 @@ import Foundation +public enum MinimumCoinChangeError: Error { + case noRestPossibleForTheGivenValue +} + public struct MinimumCoinChange { - private let sortedCoinSet: [Int] - private var cache: [Int : [Int]] + internal let sortedCoinSet: [Int] public init(coinSet: [Int]) { self.sortedCoinSet = coinSet.sorted(by: { $0 > $1} ) - self.cache = [:] } //Greedy Algorithm - public func changeGreedy(_ value: Int) -> [Int] { + 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 { + if newValue == 0 { break } } + if newValue > 0 { + throw MinimumCoinChangeError.noRestPossibleForTheGivenValue + } + return change } //Dynamic Programming Algorithm - public mutating func changeDynamic(_ value: Int) -> [Int] { - if value <= 0 { - return [] - } + public func changeDynamic(_ value: Int) throws -> [Int] { + guard value > 0 else { return [] } - if let cached = cache[value] { - return cached - } - - var change: [Int] = [] - - var potentialChangeArray: [[Int]] = [] - - for coin in sortedCoinSet { - if value - coin >= 0 { - var potentialChange: [Int] = [] - potentialChange.append(coin) - let newPotentialValue = value - coin + var cache: [Int : [Int]] = [:] - if value > 0 { - potentialChange.append(contentsOf: changeDynamic(newPotentialValue)) - } + func _changeDynamic(_ value: Int) -> [Int] { + guard value > 0 else { return [] } - //print("value: \(value) coin: \(coin) potentialChange: \(potentialChange)") - potentialChangeArray.append(potentialChange) + if let cached = cache[value] { + return cached } + + var change: [Int] = [] + + var potentialChangeArray: [[Int]] = [] + + for coin in sortedCoinSet { + if value - coin >= 0 { + var potentialChange: [Int] = [coin] + potentialChange.append(contentsOf: _changeDynamic(value - coin)) + potentialChangeArray.append(potentialChange) + } + } + + if potentialChangeArray.count > 0 { + let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) + change = sortedPotentialChangeArray[0] + } + + if change.reduce(0, +) == value { + cache[value] = change + } + + return change } - - if potentialChangeArray.count > 0 { - let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) - change = sortedPotentialChangeArray[0] - } - - cache[value] = change + + let change: [Int] = _changeDynamic(value) + + if change.reduce(0, +) != value { + throw MinimumCoinChangeError.noRestPossibleForTheGivenValue + } + return change } } - diff --git a/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift b/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift index 86c9007ba..705113e92 100644 --- a/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift +++ b/MinimumCoinChange/Tests/MinimumCoinChangeTests/MinimumCoinChangeTests.swift @@ -3,16 +3,24 @@ import XCTest class MinimumCoinChangeTests: XCTestCase { func testExample() { - var mcc = MinimumCoinChange(coinSet: [1, 2, 5, 10, 20, 25]) + let mcc = MinimumCoinChange(coinSet: [1, 2, 5, 10, 20, 25]) + print("Coin set: \(mcc.sortedCoinSet)") - for i in 0..<100 { - let greedy = mcc.changeGreedy(i) - let dynamic = mcc.changeDynamic(i) + do { + for i in 0..<100 { + let greedy = try mcc.changeGreedy(i) + let dynamic = try mcc.changeDynamic(i) - if greedy.count != dynamic.count { - print("\(i): greedy = \(greedy) dynamic = \(dynamic)") + 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 = [ From 7abd8765deff7437e591730ea5c4cbf263ec9fc6 Mon Sep 17 00:00:00 2001 From: Ievgen Pavliuk Date: Sat, 8 Apr 2017 14:30:42 +0200 Subject: [PATCH 0265/1039] Fixed typo in AVL --- AVL Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AVL Tree/README.markdown b/AVL Tree/README.markdown index c8d8d4628..e7515d99f 100644 --- a/AVL Tree/README.markdown +++ b/AVL Tree/README.markdown @@ -48,7 +48,7 @@ Each tree node keeps track of its current balance factor in a variable. After in ![Rotation0](Images/RotationStep0.jpg) For the rotation we're using the terminology: -* *Root* - the parent not of the subtrees that will be rotated; +* *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 From 3e62df6cff7e3408647b8da016ca4230fb2a191c Mon Sep 17 00:00:00 2001 From: Ute Schiehlen Date: Mon, 10 Apr 2017 11:18:34 +0200 Subject: [PATCH 0266/1039] Silenced warnings in print statements --- .../RedBlackTree.playground/Sources/RedBlackTree.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift index 6f3b16b86..351f89a9d 100644 --- a/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift +++ b/Red-Black Tree/RedBlackTree.playground/Sources/RedBlackTree.swift @@ -638,11 +638,11 @@ extension RedBlackTree { 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 \(node.key ?? nil) has red left child") + 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 \(node.key ?? nil) has red right child") + print("Property-Error: Red node with key \(String(describing: node.key)) has red right child") return false } } @@ -677,7 +677,7 @@ extension RedBlackTree { let addedHeight = node.color == .black ? 1 : 0 return left + addedHeight } else { - print("Property-Error: Black height violated at node with key \(node.key ?? nil)") + print("Property-Error: Black height violated at node with key \(String(describing: node.key))") return -1 } } @@ -697,7 +697,7 @@ extension RBTreeNode: CustomDebugStringConvertible { s = "key: nil" } if let parent = parent { - s += ", parent: \(parent.key)" + s += ", parent: \(String(describing: parent.key))" } if let left = leftChild { s += ", left = [" + left.debugDescription + "]" From 51d36815aaf49d23cc0630ed36459141acbdab9e Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Mon, 10 Apr 2017 15:38:52 -0400 Subject: [PATCH 0267/1039] Updated a comment about nested class declarations for Swift 3. Formatted the signature at the bottom --- Linked List/README.markdown | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index 1884aeb23..c5a752e13 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -79,18 +79,18 @@ 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, I'd like to put the `LinkedListNode` class inside `LinkedList` but Swift currently doesn't allow generic types to have nested types. Instead we're using a typealias so inside `LinkedList` we can write the shorter `Node` instead of `LinkedListNode`. +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.) @@ -267,7 +267,7 @@ Let's write a method that lets you insert a new node at any index in the list. F ```swift private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) - + var i = index var next = head var prev: Node? @@ -283,13 +283,13 @@ Let's write a method that lets you insert a new node at any index in the list. F } ``` -This returns a tuple containing the node currently at the specified index and the node that immediately precedes it, if any. The loop is very similar to `nodeAtIndex()`, except that here we also keep track of what the previous node is as we iterate through the list. +This returns a tuple containing the node currently at the specified index and the node that immediately precedes it, if any. The loop is very similar to `nodeAtIndex()`, except that here we also keep track of what the previous node is as we iterate through the list. Let's look at an example. Suppose we have the following list: head --> A --> B --> C --> D --> E --> nil -We want to find the nodes before and after index 3. As we start the loop, `i = 3`, `next` points at `"A"`, and `prev` is nil. +We want to find the nodes before and after index 3. As we start the loop, `i = 3`, `next` points at `"A"`, and `prev` is nil. head --> A --> B --> C --> D --> E --> nil next @@ -320,7 +320,7 @@ Now that we have this helper function, we can write the method for inserting nod ```swift public func insert(value: T, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index) // 1 - + let newNode = Node(value: value) // 2 newNode.previous = prev newNode.next = next @@ -364,20 +364,20 @@ What else do we need? Removing nodes, of course! First we'll do `removeAll()`, w 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 `removeNode()` is the most optimal because you don't need to iterate through the list to find the node first. +Next we'll add some functions that let you remove individual nodes. If you already have a reference to the node, then using `removeNode()` 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 @@ -412,7 +412,7 @@ If you don't have a reference to the node, you can use `removeLast()` or `remove } ``` -All these removal functions also return the value from the removed element. +All these removal functions also return the value from the removed element. ```swift list.removeLast() // "World" @@ -543,4 +543,4 @@ When performing operations on a linked list, you always need to be careful to up 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. -*Written for Swift Algorithm Club by Matthijs Hollemans* +*Originally written by Matthijs Hollemans for Ray Wenderlich's Swift Algorithm Club* From a613ca599c03a98e588e32982d57097d5b388909 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Mon, 10 Apr 2017 16:39:50 -0400 Subject: [PATCH 0268/1039] Updated the Playground file with more comments and added an overloadded implementations of 'insert' & 'append' to accept a whole list as an argument --- .../LinkedList.playground/Contents.swift | 96 +++++++++++++++---- .../contents.xcplayground | 2 +- 2 files changed, 81 insertions(+), 17 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index abbb90467..93ed4246d 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -1,30 +1,41 @@ -//: Playground - noun: a place where people can play +//: # Linked Lists -public class LinkedListNode { - var value: T - var next: LinkedListNode? - weak var previous: LinkedListNode? - - public init(value: T) { - self.value = value - } -} +// 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 fileprivate var head: Node? + // Default initializer public init() {} + // Computed property to check if the linked list is empty public var isEmpty: Bool { return head == nil } + // Computed property to get the first node in the linked list (if any) public var first: Node? { return head } + // Computed property to iterate through the linked list and return the last node in the list (if any) public var last: Node? { if var node = head { while case let next? = node.next { @@ -36,6 +47,7 @@ public final class LinkedList { } } + // Computed property to iterate through the linked list and return the total number of nodes public var count: Int { if var node = head { var c = 1 @@ -49,6 +61,7 @@ public final class LinkedList { } } + // Function to return the node at a specific index public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head @@ -62,17 +75,20 @@ public final class LinkedList { return nil } + // Subscript function to return the node at a specific index public subscript(index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) return node!.value } + // Append a value public func append(_ value: T) { let newNode = Node(value: value) self.append(newNode) } + // Append a node without taking ownership (appends a copy) public func append(_ node: Node) { let newNode = LinkedListNode(value: node.value) if let lastNode = last { @@ -83,6 +99,16 @@ public final class LinkedList { } } + // Append a whole linked list without taking ownership (appends a copy) + public func append(_ list: LinkedList) { + var nodeToCopy = list.head + while let node = nodeToCopy { + self.append(node.value) + nodeToCopy = node.next + } + } + + // Private helper function to return the nodes (in a tuple) before and after a specific index private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) @@ -100,11 +126,13 @@ public final class LinkedList { return (prev, next) } + // Insert a value at a specific index public func insert(_ value: T, atIndex index: Int) { let newNode = Node(value: value) self.insert(newNode, atIndex: index) } + // Insert a node at a specific index without taking ownership (inserts a copy) public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = LinkedListNode(value: node.value) @@ -118,10 +146,33 @@ public final class LinkedList { } } + // Insert a whole linked list at a specific index without taking ownership (inserts a copy) + 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 + } + + // Function to remove all nodes from the list public func removeAll() { head = nil } + // Function to remove a specific node from the list and return its value @discardableResult public func remove(node: Node) -> T { let prev = node.previous let next = node.next @@ -138,11 +189,13 @@ public final class LinkedList { return node.value } + // Function to remove the last node in the list @discardableResult public func removeLast() -> T { assert(!isEmpty) return remove(node: last!) } + // Function to remove the node at a specific index from the list @discardableResult public func remove(atIndex index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) @@ -150,6 +203,7 @@ public final class LinkedList { } } +//: End of the base class declarations & beginning of extensions' declarations: extension LinkedList: CustomStringConvertible { public var description: String { var s = "[" @@ -218,6 +272,8 @@ extension LinkedList: ExpressibleByArrayLiteral { } } + +//: Ok, now that the declarations are done, let's see our Linked List in action: let list = LinkedList() list.isEmpty // true list.first // nil @@ -247,10 +303,20 @@ 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(atIndex: 2) // "Goodbye" + + list.insert("Swift", atIndex: 1) -list[0] -list[1] -list[2] +list[0] // "Hello" +list[1] // "Swift" +list[2] // "World" print(list) list.reverse() // [World, Swift, Hello] @@ -262,9 +328,6 @@ m // [8, 6, 5] let f = list.filter { s in s.characters.count > 5 } f // [Universe, Swifty] -//list.removeAll() -//list.isEmpty - list.remove(node: list.first!) // "Universe" list.count // 2 list[0] // "Swifty" @@ -286,3 +349,4 @@ let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] listArrayLiteral2.count // 3 listArrayLiteral2[0] // "Swift" listArrayLiteral2.removeLast() // "Club" + diff --git a/Linked List/LinkedList.playground/contents.xcplayground b/Linked List/LinkedList.playground/contents.xcplayground index 06828af92..3de2b51ba 100644 --- a/Linked List/LinkedList.playground/contents.xcplayground +++ b/Linked List/LinkedList.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file From 45ef5cc2e0fb0f340744812a43b0fa329b20f867 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Mon, 10 Apr 2017 16:57:12 -0400 Subject: [PATCH 0269/1039] Added 2 overloaded 'insert' & 'append' funcs that take a List as an argument to LinkedList.swift. Added 5 tests to LinkedListTests.swift to check the added 2 functions --- Linked List/LinkedList.swift | 51 ++++++++++++++++----- Linked List/Tests/LinkedListTests.swift | 60 +++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 11 deletions(-) diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 55593cdc9..a7ef9bf5e 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -1,14 +1,15 @@ -public class LinkedListNode { - var value: T - var next: LinkedListNode? - weak var previous: LinkedListNode? +public final class LinkedList { - public init(value: T) { - self.value = value + public class LinkedListNode { + var value: T + var next: LinkedListNode? + weak var previous: LinkedListNode? + + public init(value: T) { + self.value = value + } } -} - -public final class LinkedList { + public typealias Node = LinkedListNode fileprivate var head: Node? @@ -72,7 +73,7 @@ public final class LinkedList { } public func append(_ node: Node) { - let newNode = Node(value: node.value) + let newNode = LinkedListNode(value: node.value) if let lastNode = last { newNode.previous = lastNode lastNode.next = newNode @@ -81,6 +82,14 @@ public final class LinkedList { } } + 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) @@ -105,7 +114,7 @@ public final class LinkedList { public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) - let newNode = Node(value: node.value) + let newNode = LinkedListNode(value: node.value) newNode.previous = prev newNode.next = next prev?.next = newNode @@ -116,6 +125,26 @@ public final class LinkedList { } } + 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 } diff --git a/Linked List/Tests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift index 6f58d9775..ea063cacb 100755 --- a/Linked List/Tests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -165,7 +165,67 @@ class LinkedListTest: XCTestCase { 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, atIndex: 2) + XCTAssertTrue(list.count == 8) + XCTAssertEqual(list.node(atIndex: 1)?.value, 2) + XCTAssertEqual(list.node(atIndex: 2)?.value, 99) + XCTAssertEqual(list.node(atIndex: 3)?.value, 102) + XCTAssertEqual(list.node(atIndex: 4)?.value, 10) + } + func testInsertListAtFirstIndex() { + let list = buildList() + let list2 = LinkedList() + list2.append(99) + list2.append(102) + list.insert(list2, atIndex: 0) + XCTAssertTrue(list.count == 8) + XCTAssertEqual(list.node(atIndex: 0)?.value, 99) + XCTAssertEqual(list.node(atIndex: 1)?.value, 102) + XCTAssertEqual(list.node(atIndex: 2)?.value, 8) + } + + func testInsertListAtLastIndex() { + let list = buildList() + let list2 = LinkedList() + list2.append(99) + list2.append(102) + list.insert(list2, atIndex: list.count) + XCTAssertTrue(list.count == 8) + XCTAssertEqual(list.node(atIndex: 5)?.value, 5) + XCTAssertEqual(list.node(atIndex: 6)?.value, 99) + XCTAssertEqual(list.node(atIndex: 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(atIndex: 5)?.value, 5) + XCTAssertEqual(list.node(atIndex: 6)?.value, 99) + XCTAssertEqual(list.node(atIndex: 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(atIndex: 0)?.value, 5) + XCTAssertEqual(list.node(atIndex: 1)?.value, 10) + } + func testRemoveAtIndexOnListWithOneElement() { let list = LinkedList() list.append(123) From c74bec1667b6be79b6a8dd56dd09b9c0076c1ef7 Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Mon, 10 Apr 2017 19:24:50 -0400 Subject: [PATCH 0270/1039] Updated the xcode version in .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b6ff6190c..d413140fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode8 +osx_image: xcode8.3 # sudo: false install: From 84009ae732937157fd3f071b78430895968d500b Mon Sep 17 00:00:00 2001 From: Marwan Alani Date: Tue, 11 Apr 2017 19:33:40 -0400 Subject: [PATCH 0271/1039] Added proper annotation to the Linked List playground files --- .../LinkedList.playground/Contents.swift | 82 ++++++++++++++----- 1 file changed, 61 insertions(+), 21 deletions(-) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 93ed4246d..b86fbf0b4 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -5,7 +5,7 @@ //: Linked List Class Declaration: public final class LinkedList { - // Linked List's Node Class Declaration + /// Linked List's Node Class Declaration public class LinkedListNode { var value: T var next: LinkedListNode? @@ -16,26 +16,26 @@ public final class LinkedList { } } - // Typealiasing the node class to increase readability of code + /// Typealiasing the node class to increase readability of code public typealias Node = LinkedListNode - // The head of the Linked List + /// The head of the Linked List fileprivate var head: Node? - // Default initializer + /// Default initializer public init() {} - // Computed property to check if the linked list is empty + /// Computed property to check if the linked list is empty public var isEmpty: Bool { return head == nil } - // Computed property to get the first node in the linked list (if any) + /// Computed property to get the first node in the linked list (if any) public var first: Node? { return head } - // Computed property to iterate through the linked list and return the last node in the list (if any) + /// Computed property to iterate through the linked list and return the last node in the list (if any) public var last: Node? { if var node = head { while case let next? = node.next { @@ -47,7 +47,7 @@ public final class LinkedList { } } - // Computed property to iterate through the linked list and return the total number of nodes + /// Computed property to iterate through the linked list and return the total number of nodes public var count: Int { if var node = head { var c = 1 @@ -61,7 +61,10 @@ public final class LinkedList { } } - // Function to return the node at a specific index + /// 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: Optional LinkedListNode public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head @@ -75,20 +78,26 @@ public final class LinkedList { return nil } - // Subscript function to return the node at a specific index + /// 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(atIndex: index) assert(node != nil) return node!.value } - // Append a value + /// Append a value to the end of the list + /// + /// - Parameter value: The data value to be appended public func append(_ value: T) { let newNode = Node(value: value) self.append(newNode) } - // Append a node without taking ownership (appends a copy) + /// Append a copy of a LinkedListNode to the end of the list. + /// + /// - Parameter node: The node containing the value to be appended public func append(_ node: Node) { let newNode = LinkedListNode(value: node.value) if let lastNode = last { @@ -99,7 +108,9 @@ public final class LinkedList { } } - // Append a whole linked list without taking ownership (appends a copy) + /// Append a copy of a LinkedList to the end of the list. + /// + /// - Parameter list: The list to be copied and appended. public func append(_ list: LinkedList) { var nodeToCopy = list.head while let node = nodeToCopy { @@ -108,7 +119,10 @@ public final class LinkedList { } } - // Private helper function to return the nodes (in a tuple) before and after a specific index + /// A private helper funciton to find the nodes before and after a specified index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameter index: Integer value of the index between the nodes. + /// - Returns: A tuple of 2 nodes before & after the specified index respectively. private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) { assert(index >= 0) @@ -126,13 +140,21 @@ public final class LinkedList { return (prev, next) } - // Insert a value at a specific index + /// Insert a value at a specific index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameters: + /// - value: The data value to be inserted + /// - index: Integer value of the index to be insterted at public func insert(_ value: T, atIndex index: Int) { let newNode = Node(value: value) self.insert(newNode, atIndex: index) } - // Insert a node at a specific index without taking ownership (inserts a copy) + /// Insert a copy of a node at a specific index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameters: + /// - node: The node containing the value to be inserted + /// - index: Integer value of the index to be inserted at public func insert(_ node: Node, atIndex index: Int) { let (prev, next) = nodesBeforeAndAfter(index: index) let newNode = LinkedListNode(value: node.value) @@ -146,7 +168,11 @@ public final class LinkedList { } } - // Insert a whole linked list at a specific index without taking ownership (inserts a copy) + /// Insert a copy of a LinkedList at a specific index. Crashes if index is out of bounds (0...self.count) + /// + /// - Parameters: + /// - list: The LinkedList to be copied and inserted + /// - index: Integer value of the index to be inserted at public func insert(_ list: LinkedList, atIndex index: Int) { if list.isEmpty { return } var (prev, next) = nodesBeforeAndAfter(index: index) @@ -167,12 +193,15 @@ public final class LinkedList { next?.previous = prev } - // Function to remove all nodes from the list + /// Function to remove all nodes/value from the list public func removeAll() { head = nil } - // Function to remove a specific node from the list and return its value + /// Function to remove a specific node. + /// + /// - Parameter node: The node to be deleted + /// - Returns: The data value contained in the deleted node. @discardableResult public func remove(node: Node) -> T { let prev = node.previous let next = node.next @@ -189,13 +218,18 @@ public final class LinkedList { return node.value } - // Function to remove the last node in the list + /// 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 the node at a specific index from the list + /// 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(atIndex index: Int) -> T { let node = self.node(atIndex: index) assert(node != nil) @@ -204,6 +238,8 @@ public final class LinkedList { } //: 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 = "[" @@ -217,6 +253,7 @@ extension LinkedList: CustomStringConvertible { } } +// MARK: - Extension to add a 'reverse' function to the list extension LinkedList { public func reverse() { var node = head @@ -228,6 +265,7 @@ extension LinkedList { } } +// MARK: - An extension with an implementation of 'map' & 'filter' functions extension LinkedList { public func map(transform: (T) -> U) -> LinkedList { let result = LinkedList() @@ -252,6 +290,7 @@ extension LinkedList { } } +// MARK: - Extension to enable initialization from an Array extension LinkedList { convenience init(array: Array) { self.init() @@ -262,6 +301,7 @@ extension LinkedList { } } +// MARK: - Extension to enable initialization from an Array Literal extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() From 621a28da46cebf8bcd003ef6e80afb7e63b01136 Mon Sep 17 00:00:00 2001 From: vincentngo Date: Thu, 13 Apr 2017 21:07:51 -0400 Subject: [PATCH 0272/1039] Update README.markdown --- Hash Table/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Hash Table/README.markdown b/Hash Table/README.markdown index 958c3595a..bc9636195 100644 --- a/Hash Table/README.markdown +++ b/Hash Table/README.markdown @@ -103,7 +103,7 @@ it first hashes the key `"lastName"` to calculate the array index, which is 3. S 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 becasuse the slow process of looking up items in the hash table. 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. +Chains should not become long because the slow process of looking up items in the hash table. 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. @@ -127,7 +127,7 @@ public struct HashTable { } ``` -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 useing in a chain, and `Bucket` is an array of such `Elements`. +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. From 55c11cadd38ee59e89a3128860b53f63e8b0457d Mon Sep 17 00:00:00 2001 From: ph1ps Date: Fri, 14 Apr 2017 21:37:24 +0200 Subject: [PATCH 0273/1039] Claim Naive Bayes Classifier --- Naive Bayes Classifier/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Naive Bayes Classifier/README.md diff --git a/Naive Bayes Classifier/README.md b/Naive Bayes Classifier/README.md new file mode 100644 index 000000000..e69de29bb From 85f8085de5131657a9f8f5e7ab8f8d3e42f39edf Mon Sep 17 00:00:00 2001 From: ph1ps Date: Fri, 14 Apr 2017 21:38:44 +0200 Subject: [PATCH 0274/1039] Add initial version of NB --- Naive Bayes Classifier/NaiveBayes.swift | 141 ++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 Naive Bayes Classifier/NaiveBayes.swift diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift new file mode 100644 index 000000000..c988cacbe --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -0,0 +1,141 @@ +// +// main.swift +// NaiveBayes +// +// Created by Philipp Gabriel on 14.04.17. +// Copyright © 2017 ph1ps. All rights reserved. +// + +//TODO naming +import Foundation + +extension Array where Element == Double { + + func mean() -> Double { + return self.reduce(0, +) / Double(count) + } + + func standardDeviation() -> Double { + let calculatedMean = mean() + + let sum = self.reduce(0.0) { (previous, next) in + return previous + pow(next - calculatedMean, 2) + } + + return sqrt(sum / Double(count - 1)) + } +} + +extension Array where Element == Int { + + //Is this the best way?! + func uniques() -> [Int] { + return Array(Set(self)) + } + +} + +class NaiveBayes { + + var data: [[Double]] + var classes: [Int] + var variables: [Int: [(feature: Int, mean: Double, stDev: Double)]] + + init(data: [[Double]], classes: [Int]) { + self.data = data + self.classes = classes + self.variables = [Int: [(feature: Int, mean: Double, stDev: Double)]]() + } + + //TODO + //init(dataAndClasses: [[Double]], index ofClassRow: Int) {} + + //TODO: Does it really need to be n^2 runtime? + func train() { + + for `class` in 0.. Int { + let likelihoods = predictLikelihood(input: input).max { (first, second) -> Bool in + return first.1 < second.1 + } + + guard let `class` = likelihoods?.0 else { + return -1 + } + + return `class` + } + + func predictLikelihood(input: [Double]) -> [(Int, Double)] { + + var probabilityOfClasses = [Int: Double]() + let amount = classes.uniques().count + + classes.forEach { `class` in + let individual = classes.filter { $0 == `class` }.count + probabilityOfClasses[`class`] = Double(amount) / Double(individual) + } + + let probaClass = variables.map { (key, value) -> (Int, [Double]) in + let probaFeature = value.map { (feature, mean, stDev) -> Double in + let featureValue = input[feature] + let eulerPart = pow(M_E, -1 * pow(featureValue - mean, 2) / (2 * pow(stDev, 2))) + let distribution = eulerPart / sqrt(2 * .pi) / stDev + return distribution + } + return (key, probaFeature) + } + + let likelihoods = probaClass.map { (key, probaFeature) in + return (key, probaFeature.reduce(1, *) * (probabilityOfClasses[key] ?? 1.0)) + } + + let sum = likelihoods.map { $0.1 }.reduce(0, +) + let normalized = likelihoods.map { (`class`, likelihood) in + return (`class`, likelihood / sum) + } + + return normalized + } +} + +let data: [[Double]] = [ + [6,180,12], + [5.92,190,11], + [5.58,170,12], + [5.92,165,10], + [5,100,6], + [5.5,150,8], + [5.42,130,7], + [5.75,150,9] +] + +let classes = [0,0,0,0,1,1,1,1] + +let naive = NaiveBayes(data: data, classes: classes) +naive.train() +let result = naive.predictLikelihood(input: [6,130,8]) +print(result) + + + + + + + + From be4ac46a126d4f1b744bb84216ab0ef68686e2e7 Mon Sep 17 00:00:00 2001 From: Philipp Gabriel Date: Fri, 14 Apr 2017 21:40:52 +0200 Subject: [PATCH 0275/1039] Add NB to README --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index 29fc9d748..7df847960 100644 --- a/README.markdown +++ b/README.markdown @@ -116,6 +116,7 @@ Bad sorting algorithms (don't use these!): - Logistic Regression - Neural Networks - PageRank +- [Naive Bayes Classifier](Naive%20Bayes%20Classifier/) ## Data structures From f536ff10804f32066a5fdea1becfc6b80ebbf25f Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 02:06:55 +0600 Subject: [PATCH 0276/1039] Bugs fied. Readme added. --- .../EggDrop.playground/Contents.swift | 5 +++ .../EggDrop.playground/Sources/EggDrop.swift | 41 +++++++++++++++++ .../EggDrop.playground/contents.xcplayground | 4 ++ Egg Drop Problem/EggDrop.swift | 36 +++++++++------ Egg Drop Problem/README.markdown | 44 +++++++++++++++++++ .../contents.xcworkspacedata | 6 +++ 6 files changed, 123 insertions(+), 13 deletions(-) create mode 100644 Egg Drop Problem/EggDrop.playground/Contents.swift create mode 100644 Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift create mode 100644 Egg Drop Problem/EggDrop.playground/contents.xcplayground create mode 100644 Egg Drop Problem/README.markdown diff --git a/Egg Drop Problem/EggDrop.playground/Contents.swift b/Egg Drop Problem/EggDrop.playground/Contents.swift new file mode 100644 index 000000000..4ddb936b3 --- /dev/null +++ b/Egg Drop Problem/EggDrop.playground/Contents.swift @@ -0,0 +1,5 @@ + //: Playground - noun: a place where people can play + +import Cocoa + +eggDrop(numberOfEggs: 2, numberOfFloors: 4) diff --git a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift new file mode 100644 index 000000000..f69284491 --- /dev/null +++ b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift @@ -0,0 +1,41 @@ +public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { + if numberOfEggs == 0 || numberOfFloors == 0{ + return 0 + } + if numberOfEggs == 1 || numberOfFloors == 1{ + return 1 + } + + var eggFloor = [[Int]](repeating: [Int](repeating: 0, count: numberOfFloors+1), count: numberOfEggs+1) //egg(rows) floor(cols) array to store the solutions + var attempts: Int = 0 + + for var floorNumber in (0..<(numberOfFloors+1)){ + eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts + for var eggNumber in (2..<(numberOfEggs+1)){ + eggFloor[eggNumber][floorNumber] = 0 + } + } + eggFloor[2][1] = 1 //base case: if there's are two eggs and one floor, it takes one attempt + + for var eggNumber in (2..<(numberOfEggs+1)){ + for var floorNumber in (2..<(numberOfFloors+1)){ + eggFloor[eggNumber][floorNumber] = 1000000 + for var visitingFloor in (1..<(floorNumber+1)){ + //there are two cases + //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> visitingFloor-1 + //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floorNumber-visitingFloor + attempts = 1 + max(eggFloor[eggNumber-1][visitingFloor-1], eggFloor[eggNumber][floorNumber-visitingFloor])//we add one taking into account the attempt we're taking at the moment + + if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min + eggFloor[eggNumber][floorNumber] = attempts; + } + } + } + } + + return eggFloor[numberOfEggs][numberOfFloors] +} + +public func max(_ x1: Int, _ x2: Int) -> Int{ + return x1 > x2 ? x1 : x2 +} diff --git a/Egg Drop Problem/EggDrop.playground/contents.xcplayground b/Egg Drop Problem/EggDrop.playground/contents.xcplayground new file mode 100644 index 000000000..63b6dd8df --- /dev/null +++ b/Egg Drop Problem/EggDrop.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift index 6d0aab2a1..a525793db 100644 --- a/Egg Drop Problem/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.swift @@ -1,23 +1,33 @@ -func eggDrop(_ numberOfEggs: Int, numberOfFloors: Int) -> Int { - var eggFloor: [[Int]] = [] //egg(rows) floor(cols) array to store the solutions +public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { + if numberOfEggs == 0 || numberOfFloors == 0{ + return 0 + } + if numberOfEggs == 1 || numberOfFloors == 1{ + return 1 + } + + var eggFloor = [[Int]](repeating: [Int](repeating: 0, count: numberOfFloors+1), count: numberOfEggs+1) //egg(rows) floor(cols) array to store the solutions var attempts: Int = 0 - for var i in (0.. k-1 - //case 2: egg doesn't break. meaning we'll still have 'i' number of eggs, and we'll go upstairs -> j-k - attempts = 1 + max(eggFloor[i-1][k-1], eggFloor[i][j-k])//we add one taking into account the attempt we're taking at the moment + //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floors-k + attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment - if attempts < eggFloor[i][j]{ //finding the min - eggFloor[i][j] = attempts; + if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min + eggFloor[eggNumber][floorNumber] = attempts; } } } @@ -26,6 +36,6 @@ func eggDrop(_ numberOfEggs: Int, numberOfFloors: Int) -> Int { return eggFloor[numberOfEggs][numberOfFloors] } -func max(_ x1: Int, _ x2: Int){ +public func max(_ x1: Int, _ x2: Int) -> Int{ return x1 > x2 ? x1 : x2 } diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown new file mode 100644 index 000000000..a58827ba3 --- /dev/null +++ b/Egg Drop Problem/README.markdown @@ -0,0 +1,44 @@ +#Egg Drop Dynamic Problem + +#Problem Description + +Given some number of floors and some number of eggs, what is the minimum number of attempts it will take to find out from which floor egg will break. + +Suppose that we wish to know which stories in a 36-story building are safe to drop eggs from, and which will cause the eggs to break on landing. We make a few assumptions: + +- An egg that survives a fall can be used again. +- A broken egg must be discarded. +- The effect of a fall is the same for all eggs. +- If an egg breaks when dropped, then it would break if dropped from a higher floor. +- If an egg survives a fall then it would survive a shorter fall. + +If only one egg is available and we wish to be sure of obtaining the right result, the experiment can be carried out in only one way. Drop the egg from the first-floor window; if it survives, drop it from the second floor window. Continue upward until it breaks. In the worst case, this method may require 36 droppings. Suppose 2 eggs are available. What is the least number of egg-droppings that is guaranteed to work in all cases? +The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized. + +#Solution +We store all the solutions in a 2D array. Where rows represents number of eggs and columns represent number of floors. + +First, we set base cases: +1) If there's only one egg, it takes as many attempts as number of floors +2) If there's are two eggs and one floor, it takes one attempt + +eggNumber ==> Number of eggs at the moment +floorNumber ==> Floor number at the moment +visitingFloor ==> Floor being visited at the moment +attempts ==> Minimum number of attempts it will take to find out from which floor egg will break + +When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. + +1) If the egg breaks after dropping from 'floorNumberth' floor, then we only need to check for floors lower than 'floorNumber' with remaining eggs; so the problem reduces to 'floorNumber'-1 floors and 'eggNumber'-1 eggs +2) If the egg doesn’t break after dropping from the xth floor, then we only need to check for floors higher than 'floorNumber'; so the problem reduces to floors-'floorNumber' floors and 'eggNumber' eggs. + +Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. + +```swift + +attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment + +if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min + eggFloor[eggNumber][floorNumber] = attempts; +} +``` diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index 5ac8577f5..1c6b407c3 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -7,6 +7,12 @@ + + + + From 75d3b5b59977a1cc54bcac2ce42e2c884eab5e69 Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 02:12:30 +0600 Subject: [PATCH 0277/1039] Bugs fixed --- Egg Drop Problem/README.markdown | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index a58827ba3..44af8174a 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -23,19 +23,21 @@ First, we set base cases: 2) If there's are two eggs and one floor, it takes one attempt eggNumber ==> Number of eggs at the moment + floorNumber ==> Floor number at the moment + visitingFloor ==> Floor being visited at the moment + attempts ==> Minimum number of attempts it will take to find out from which floor egg will break When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. -1) If the egg breaks after dropping from 'floorNumberth' floor, then we only need to check for floors lower than 'floorNumber' with remaining eggs; so the problem reduces to 'floorNumber'-1 floors and 'eggNumber'-1 eggs -2) If the egg doesn’t break after dropping from the xth floor, then we only need to check for floors higher than 'floorNumber'; so the problem reduces to floors-'floorNumber' floors and 'eggNumber' eggs. +1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. +2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. ```swift - attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min From 61949ab24314ee060f888642c59d6d20bcfa4841 Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 11:09:53 +0600 Subject: [PATCH 0278/1039] Minor changes in README --- .../EggDrop.playground/Sources/EggDrop.swift | 9 +++------ Egg Drop Problem/EggDrop.swift | 16 ++++++++-------- Egg Drop Problem/README.markdown | 19 ++++++++++++------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift index f69284491..897ba2dee 100644 --- a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift @@ -1,5 +1,5 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { - if numberOfEggs == 0 || numberOfFloors == 0{ + if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } if numberOfEggs == 1 || numberOfFloors == 1{ @@ -11,15 +11,12 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { for var floorNumber in (0..<(numberOfFloors+1)){ eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts - for var eggNumber in (2..<(numberOfEggs+1)){ - eggFloor[eggNumber][floorNumber] = 0 - } } - eggFloor[2][1] = 1 //base case: if there's are two eggs and one floor, it takes one attempt + eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt for var eggNumber in (2..<(numberOfEggs+1)){ for var floorNumber in (2..<(numberOfFloors+1)){ - eggFloor[eggNumber][floorNumber] = 1000000 + eggFloor[eggNumber][floorNumber] = Int.max //setting the final result a high number to find out minimum for var visitingFloor in (1..<(floorNumber+1)){ //there are two cases //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> visitingFloor-1 diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift index a525793db..7be691f57 100644 --- a/Egg Drop Problem/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.swift @@ -1,5 +1,5 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { - if numberOfEggs == 0 || numberOfFloors == 0{ + if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } if numberOfEggs == 1 || numberOfFloors == 1{ @@ -10,21 +10,21 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { var attempts: Int = 0 for var floorNumber in (0..<(numberOfFloors+1)){ - eggFloor[1][floorNumber] = floorNumber + eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts for var eggNumber in (2..<(numberOfEggs+1)){ eggFloor[eggNumber][floorNumber] = 0 } } - eggFloor[2][1] = 1 + eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt for var eggNumber in (2..<(numberOfEggs+1)){ for var floorNumber in (2..<(numberOfFloors+1)){ - eggFloor[eggNumber][floorNumber] = 1000000 - for var floors in (1..<(floorNumber+1)){ + eggFloor[eggNumber][floorNumber] = Int.max //setting the final result a high number to find out minimum + for var visitingFloor in (1..<(floorNumber+1)){ //there are two cases - //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> k-1 - //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floors-k - attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment + //case 1: egg breaks. meaning we'll have one less egg, and we'll have to go downstairs -> visitingFloor-1 + //case 2: egg doesn't break. meaning we'll still have 'eggs' number of eggs, and we'll go upstairs -> floorNumber-visitingFloor + attempts = 1 + max(eggFloor[eggNumber-1][visitingFloor-1], eggFloor[eggNumber][floorNumber-visitingFloor])//we add one taking into account the attempt we're taking at the moment if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min eggFloor[eggNumber][floorNumber] = attempts; diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index 44af8174a..2df3088b5 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -22,19 +22,24 @@ First, we set base cases: 1) If there's only one egg, it takes as many attempts as number of floors 2) If there's are two eggs and one floor, it takes one attempt -eggNumber ==> Number of eggs at the moment - -floorNumber ==> Floor number at the moment - -visitingFloor ==> Floor being visited at the moment - -attempts ==> Minimum number of attempts it will take to find out from which floor egg will break +- eggNumber ==> Number of eggs at the moment +- floorNumber ==> Floor number at the moment +- visitingFloor ==> Floor being visited at the moment +- attempts ==> Minimum number of attempts it will take to find out from which floor egg will break When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. 1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. 2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. +```swift +for var floorNumber in (0..<(numberOfFloors+1)){ + eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts +} + +eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt +``` + Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. ```swift From 4ab987c592763cd13719411b829d8d513a64707b Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 11:14:18 +0600 Subject: [PATCH 0279/1039] Minor changes in README --- Egg Drop Problem/README.markdown | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index 2df3088b5..eda28fa6f 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -16,32 +16,33 @@ If only one egg is available and we wish to be sure of obtaining the right resul The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized. #Solution +- eggNumber -> Number of eggs at the moment +- floorNumber -> Floor number at the moment +- visitingFloor -> Floor being visited at the moment +- attempts -> Minimum number of attempts it will take to find out from which floor egg will break + We store all the solutions in a 2D array. Where rows represents number of eggs and columns represent number of floors. First, we set base cases: 1) If there's only one egg, it takes as many attempts as number of floors 2) If there's are two eggs and one floor, it takes one attempt -- eggNumber ==> Number of eggs at the moment -- floorNumber ==> Floor number at the moment -- visitingFloor ==> Floor being visited at the moment -- attempts ==> Minimum number of attempts it will take to find out from which floor egg will break - -When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. - -1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. -2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. - ```swift for var floorNumber in (0..<(numberOfFloors+1)){ - eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts +eggFloor[1][floorNumber] = floorNumber //base case 1: if there's only one egg, it takes 'numberOfFloors' attempts } -eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt +eggFloor[2][1] = 1 //base case 2: if there are two eggs and one floor, it takes one attempt ``` +When we drop an egg from a floor 'floorNumber', there can be two cases (1) The egg breaks (2) The egg doesn’t break. + +1) If the egg breaks after dropping from 'visitingFloorth' floor, then we only need to check for floors lower than 'visitingFloor' with remaining eggs; so the problem reduces to 'visitingFloor'-1 floors and 'eggNumber'-1 eggs. +2) If the egg doesn’t break after dropping from the 'visitingFloorth' floor, then we only need to check for floors higher than 'visitingFloor'; so the problem reduces to floors-'visitingFloor' floors and 'eggNumber' eggs. + Since we need to minimize the number of trials in worst case, we take the maximum of two cases. We consider the max of above two cases for every floor and choose the floor which yields minimum number of trials. +We find the answer based on the base cases and previously found answers as follows. ```swift attempts = 1 + max(eggFloor[eggNumber-1][floors-1], eggFloor[eggNumber][floorNumber-floors])//we add one taking into account the attempt we're taking at the moment From 1fbb40efe14b80d6187a9ebd698960ba3520fe3b Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 11:35:40 +0600 Subject: [PATCH 0280/1039] Example added --- Egg Drop Problem/EggDrop.playground/Contents.swift | 6 +++++- Egg Drop Problem/EggDrop.swift | 3 --- Egg Drop Problem/README.markdown | 14 +++++++++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Egg Drop Problem/EggDrop.playground/Contents.swift b/Egg Drop Problem/EggDrop.playground/Contents.swift index 4ddb936b3..d452e7f9f 100644 --- a/Egg Drop Problem/EggDrop.playground/Contents.swift +++ b/Egg Drop Problem/EggDrop.playground/Contents.swift @@ -2,4 +2,8 @@ import Cocoa -eggDrop(numberOfEggs: 2, numberOfFloors: 4) +eggDrop(numberOfEggs: 2, numberOfFloors: 2) //expected answer: 2 +eggDrop(numberOfEggs: 2, numberOfFloors: 4) //expected answer: 3 +eggDrop(numberOfEggs: 2, numberOfFloors: 6) //expected answer: 3 +eggDrop(numberOfEggs: 5, numberOfFloors: 5) //expected answer: 2 +eggDrop(numberOfEggs: 5, numberOfFloors: 20) //expected answer: 4 \ No newline at end of file diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift index 7be691f57..897ba2dee 100644 --- a/Egg Drop Problem/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.swift @@ -11,9 +11,6 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { for var floorNumber in (0..<(numberOfFloors+1)){ eggFloor[1][floorNumber] = floorNumber //base case: if there's only one egg, it takes 'numberOfFloors' attempts - for var eggNumber in (2..<(numberOfEggs+1)){ - eggFloor[eggNumber][floorNumber] = 0 - } } eggFloor[2][1] = 1 //base case: if there are two eggs and one floor, it takes one attempt diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index eda28fa6f..1a436c374 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -25,7 +25,7 @@ We store all the solutions in a 2D array. Where rows represents number of eggs a First, we set base cases: 1) If there's only one egg, it takes as many attempts as number of floors -2) If there's are two eggs and one floor, it takes one attempt +2) If there are two eggs and one floor, it takes one attempt ```swift for var floorNumber in (0..<(numberOfFloors+1)){ @@ -50,3 +50,15 @@ if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min eggFloor[eggNumber][floorNumber] = attempts; } ``` +Example: +Let's assume we have 2 eggs and 2 floors. +1) We drop one egg from the first floor. If it breaks, then we get the answer. If it doesn't we'll have 2 eggs and 1 floors to work with. + attempts = 1 + maximum of 0(got the answer) and eggFloor[2][1] (base case 2 which gives us 1) + attempts = 1 + 1 = 2 +2) We drop one egg from the second floor. If it breaks, we'll have 1 egg and 1 floors to work with. If it doesn't, we'll get the answer. + attempts = 1 + maximum of eggFloor[1][1](base case 1 which gives us 1) and 0(got the answer) + attempts = 1 + 1 = 2 +3) Finding the minimum of 2 and 2 gives us 2, so the answer is 2. + 2 is the minimum number of attempts it will take to find out from which floor egg will break. + + From 082385a5ac58967b8eaf565654f1620444383ebf Mon Sep 17 00:00:00 2001 From: Arkalyk Akash Date: Sat, 15 Apr 2017 11:37:09 +0600 Subject: [PATCH 0281/1039] Update README.markdown --- Egg Drop Problem/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index 1a436c374..5ff6ebb1d 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -1,6 +1,6 @@ -#Egg Drop Dynamic Problem +# Egg Drop Dynamic Problem -#Problem Description +# Problem Description Given some number of floors and some number of eggs, what is the minimum number of attempts it will take to find out from which floor egg will break. @@ -15,7 +15,7 @@ Suppose that we wish to know which stories in a 36-story building are safe to dr If only one egg is available and we wish to be sure of obtaining the right result, the experiment can be carried out in only one way. Drop the egg from the first-floor window; if it survives, drop it from the second floor window. Continue upward until it breaks. In the worst case, this method may require 36 droppings. Suppose 2 eggs are available. What is the least number of egg-droppings that is guaranteed to work in all cases? The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized. -#Solution +# Solution - eggNumber -> Number of eggs at the moment - floorNumber -> Floor number at the moment - visitingFloor -> Floor being visited at the moment From ffea424eec7b80d010d731f6f1b44c442c26cab8 Mon Sep 17 00:00:00 2001 From: Arkalyk Akash Date: Sat, 15 Apr 2017 11:37:55 +0600 Subject: [PATCH 0282/1039] Update README.markdown --- Egg Drop Problem/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Egg Drop Problem/README.markdown b/Egg Drop Problem/README.markdown index 5ff6ebb1d..82543502d 100644 --- a/Egg Drop Problem/README.markdown +++ b/Egg Drop Problem/README.markdown @@ -1,6 +1,6 @@ # Egg Drop Dynamic Problem -# Problem Description +## Problem Description Given some number of floors and some number of eggs, what is the minimum number of attempts it will take to find out from which floor egg will break. @@ -15,7 +15,7 @@ Suppose that we wish to know which stories in a 36-story building are safe to dr If only one egg is available and we wish to be sure of obtaining the right result, the experiment can be carried out in only one way. Drop the egg from the first-floor window; if it survives, drop it from the second floor window. Continue upward until it breaks. In the worst case, this method may require 36 droppings. Suppose 2 eggs are available. What is the least number of egg-droppings that is guaranteed to work in all cases? The problem is not actually to find the critical floor, but merely to decide floors from which eggs should be dropped so that total number of trials are minimized. -# Solution +## Solution - eggNumber -> Number of eggs at the moment - floorNumber -> Floor number at the moment - visitingFloor -> Floor being visited at the moment @@ -50,7 +50,7 @@ if attempts < eggFloor[eggNumber][floorNumber]{ //finding the min eggFloor[eggNumber][floorNumber] = attempts; } ``` -Example: +## Example Let's assume we have 2 eggs and 2 floors. 1) We drop one egg from the first floor. If it breaks, then we get the answer. If it doesn't we'll have 2 eggs and 1 floors to work with. attempts = 1 + maximum of 0(got the answer) and eggFloor[2][1] (base case 2 which gives us 1) From 260948a2b7af625ea0fe6590e3cf966975c420dd Mon Sep 17 00:00:00 2001 From: ARKALYK AKASH Date: Sat, 15 Apr 2017 11:41:32 +0600 Subject: [PATCH 0283/1039] Comments added --- Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift | 3 ++- Egg Drop Problem/EggDrop.swift | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift index 897ba2dee..db1e48b95 100644 --- a/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.playground/Sources/EggDrop.swift @@ -2,7 +2,7 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } - if numberOfEggs == 1 || numberOfFloors == 1{ + if numberOfEggs == 1 || numberOfFloors == 1{ //edge case: When either number of eggs or number of floors is 1, answer is 1 return 1 } @@ -33,6 +33,7 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { return eggFloor[numberOfEggs][numberOfFloors] } +//Helper function to find max of two integers public func max(_ x1: Int, _ x2: Int) -> Int{ return x1 > x2 ? x1 : x2 } diff --git a/Egg Drop Problem/EggDrop.swift b/Egg Drop Problem/EggDrop.swift index 897ba2dee..db1e48b95 100644 --- a/Egg Drop Problem/EggDrop.swift +++ b/Egg Drop Problem/EggDrop.swift @@ -2,7 +2,7 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { if numberOfEggs == 0 || numberOfFloors == 0{ //edge case: When either number of eggs or number of floors is 0, answer is 0 return 0 } - if numberOfEggs == 1 || numberOfFloors == 1{ + if numberOfEggs == 1 || numberOfFloors == 1{ //edge case: When either number of eggs or number of floors is 1, answer is 1 return 1 } @@ -33,6 +33,7 @@ public func eggDrop(numberOfEggs: Int, numberOfFloors: Int) -> Int { return eggFloor[numberOfEggs][numberOfFloors] } +//Helper function to find max of two integers public func max(_ x1: Int, _ x2: Int) -> Int{ return x1 > x2 ? x1 : x2 } From 903ce26995d275e858dc535726df8a649260a4cd Mon Sep 17 00:00:00 2001 From: ph1ps Date: Sun, 16 Apr 2017 14:37:34 +0200 Subject: [PATCH 0284/1039] Add fully functional gaussian NB & examples --- Naive Bayes Classifier/NaiveBayes.swift | 122 ++++++++++++++---------- 1 file changed, 74 insertions(+), 48 deletions(-) diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift index c988cacbe..63edd9981 100644 --- a/Naive Bayes Classifier/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -1,16 +1,15 @@ // -// main.swift +// NaiveBayes.swift // NaiveBayes // // Created by Philipp Gabriel on 14.04.17. // Copyright © 2017 ph1ps. All rights reserved. // -//TODO naming import Foundation extension Array where Element == Double { - + func mean() -> Double { return self.reduce(0, +) / Double(count) } @@ -28,18 +27,17 @@ extension Array where Element == Double { extension Array where Element == Int { - //Is this the best way?! - func uniques() -> [Int] { - return Array(Set(self)) + func uniques() -> Set { + return Set(self) } } class NaiveBayes { - - var data: [[Double]] - var classes: [Int] - var variables: [Int: [(feature: Int, mean: Double, stDev: Double)]] + + private var data: [[Double]] + private var classes: [Int] + private var variables: [Int: [(feature: Int, mean: Double, stDev: Double)]] init(data: [[Double]], classes: [Int]) { self.data = data @@ -47,30 +45,37 @@ class NaiveBayes { self.variables = [Int: [(feature: Int, mean: Double, stDev: Double)]]() } - //TODO - //init(dataAndClasses: [[Double]], index ofClassRow: Int) {} - - //TODO: Does it really need to be n^2 runtime? + convenience init(dataAndClasses: [[Double]], rowOfClass: Int) { + let classes = dataAndClasses.map { Int($0[rowOfClass]) } + let data = dataAndClasses.map { row in + return row.enumerated().filter { $0.offset != rowOfClass }.map { $0.element } + } + + self.init(data: data, classes: classes) + } + func train() { - - for `class` in 0.. Int { - let likelihoods = predictLikelihood(input: input).max { (first, second) -> Bool in + func classify(with input: [Double]) -> Int { + let likelihoods = calcLikelihoods(with: input).max { (first, second) -> Bool in return first.1 < second.1 } @@ -81,30 +86,30 @@ class NaiveBayes { return `class` } - func predictLikelihood(input: [Double]) -> [(Int, Double)] { - - var probabilityOfClasses = [Int: Double]() - let amount = classes.uniques().count + func calcLikelihoods(with input: [Double]) -> [(Int, Double)] { + + var probaClass = [Int: Double]() + let amount = classes.count classes.forEach { `class` in let individual = classes.filter { $0 == `class` }.count - probabilityOfClasses[`class`] = Double(amount) / Double(individual) + probaClass[`class`] = Double(individual) / Double(amount) } - let probaClass = variables.map { (key, value) -> (Int, [Double]) in - let probaFeature = value.map { (feature, mean, stDev) -> Double in + let classesAndFeatures = variables.map { (key, value) -> (Int, [Double]) in + let distributions = value.map { (feature, mean, stDev) -> Double in let featureValue = input[feature] let eulerPart = pow(M_E, -1 * pow(featureValue - mean, 2) / (2 * pow(stDev, 2))) let distribution = eulerPart / sqrt(2 * .pi) / stDev return distribution } - return (key, probaFeature) + return (key, distributions) } - let likelihoods = probaClass.map { (key, probaFeature) in - return (key, probaFeature.reduce(1, *) * (probabilityOfClasses[key] ?? 1.0)) + let likelihoods = classesAndFeatures.map { (key, probaFeature) in + return (key, probaFeature.reduce(1, *) * (probaClass[key] ?? 1.0)) } - + let sum = likelihoods.map { $0.1 }.reduce(0, +) let normalized = likelihoods.map { (`class`, likelihood) in return (`class`, likelihood / sum) @@ -115,27 +120,48 @@ class NaiveBayes { } let data: [[Double]] = [ - [6,180,12], - [5.92,190,11], - [5.58,170,12], - [5.92,165,10], - [5,100,6], - [5.5,150,8], - [5.42,130,7], - [5.75,150,9] + [6, 180, 12], + [5.92, 190, 11], + [5.58, 170, 12], + [5.92, 165, 10], + [5, 100, 6], + [5.5, 150, 8], + [5.42, 130, 7], + [5.75, 150, 9] ] -let classes = [0,0,0,0,1,1,1,1] +let classes = [0, 0, 0, 0, 1, 1, 1, 1] let naive = NaiveBayes(data: data, classes: classes) naive.train() -let result = naive.predictLikelihood(input: [6,130,8]) -print(result) - - - - +print(naive.classify(with: [6, 130, 8])) + +let otherData: [[Double]] = [ + [6, 180, 12, 0], + [5.92, 190, 11, 0], + [5.58, 170, 12, 0], + [5.92, 165, 10, 0], + [5, 100, 6, 1], + [5.5, 150, 8, 1], + [5.42, 130, 7, 1], + [5.75, 150, 9, 1] +] +let otherNaive = NaiveBayes(dataAndClasses: otherData, rowOfClass: 3) +otherNaive.train() +print(otherNaive.calcLikelihoods(with: [6, 130, 8])) +guard let csv = try? String(contentsOfFile: "/Users/ph1ps/Desktop/wine.csv") else { + print("file not found") + exit(0) +} +let rows = csv.characters.split(separator: "\r\n").map { String($0) } +let wineData = rows.map { row -> [Double] in + let split = row.characters.split(separator: ";") + return split.map { Double(String($0))! } +} +let wineNaive = NaiveBayes(dataAndClasses: wineData, rowOfClass: 0) +wineNaive.train() +print(wineNaive.calcLikelihoods(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015])) From b6d40144c5ac91bd3155036fbcefca231a6dba0d Mon Sep 17 00:00:00 2001 From: ph1ps Date: Sun, 16 Apr 2017 23:52:57 +0200 Subject: [PATCH 0285/1039] Split into seperate types of NB classifier, implement strategy pattern --- Naive Bayes Classifier/NaiveBayes.swift | 209 +++++++++++++++++------- 1 file changed, 146 insertions(+), 63 deletions(-) diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift index 63edd9981..dbbf3cd9f 100644 --- a/Naive Bayes Classifier/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -33,49 +33,143 @@ extension Array where Element == Int { } +enum NBType { + + case gaussian(data: [[Double]], classes: [Int]) + case multinomial(data: [[Int]], classes: [Int]) + //case bernoulli(data: [[Bool]], classes: [Int]) --> TODO + + var classes: [Int] { + if case .gaussian(_, let classes) = self { + return classes + } else if case .multinomial(_, let classes) = self { + return classes + } + + return [] + } + + var data: [[Any]] { + if case .gaussian(let data, _) = self { + return data + } else if case .multinomial(let data, _) = self { + return data + } + + return [] + } + + func calcLikelihood(variables: [Any], input: Any) -> Double? { + + if case .gaussian = self { + + guard let input = input as? Double else { + return nil + } + + guard let mean = variables[0] as? Double else { + return nil + } + + guard let stDev = variables[1] as? Double else { + return nil + } + + let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) + let distribution = eulerPart / sqrt(2 * .pi) / stDev + + return distribution + + } else if case .multinomial = self { + + guard let variables = variables as? [(category: Int, probability: Double)] else { + return nil + } + + guard let input = input as? Double else { + return nil + } + + return variables.first { variable in + return variable.category == Int(input) + }?.probability + + } + + return nil + } + + func train(values: [Any]) -> [Any]? { + + if case .gaussian = self { + + guard let values = values as? [Double] else { + return nil + } + + return [values.mean(), values.standardDeviation()] + + } else if case .multinomial = self { + + guard let values = values as? [Int] else { + return nil + } + + let count = values.count + let categoryProba = values.uniques().map { value -> (Int, Double) in + return (value, Double(values.filter { $0 == value }.count) / Double(count)) + } + return categoryProba + } + + return nil + } +} + class NaiveBayes { - private var data: [[Double]] - private var classes: [Int] - private var variables: [Int: [(feature: Int, mean: Double, stDev: Double)]] + private var variables: [Int: [(feature: Int, variables: [Any])]] + private var type: NBType - init(data: [[Double]], classes: [Int]) { - self.data = data - self.classes = classes - self.variables = [Int: [(feature: Int, mean: Double, stDev: Double)]]() + init(type: NBType) { + self.type = type + self.variables = [Int: [(Int, [Any])]]() } - convenience init(dataAndClasses: [[Double]], rowOfClass: Int) { - let classes = dataAndClasses.map { Int($0[rowOfClass]) } + static func convert(dataAndClasses: [[T]], rowOfClasses: Int) -> (data: [[T]], classes: [Int]) { + let classes = dataAndClasses.map { Int($0[rowOfClasses] as! Double) } //TODO + let data = dataAndClasses.map { row in - return row.enumerated().filter { $0.offset != rowOfClass }.map { $0.element } + return row.enumerated().filter { $0.offset != rowOfClasses }.map { $0.element } } - self.init(data: data, classes: classes) + return (data, classes) } + //TODO remake pliss, i dont like this at all func train() { + var classes = type.classes + for `class` in classes.uniques() { - variables[`class`] = [(feature: Int, mean: Double, stDev: Double)]() + variables[`class`] = [(Int, [Any])]() - for feature in 0.. Int { - let likelihoods = calcLikelihoods(with: input).max { (first, second) -> Bool in + let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } @@ -86,8 +180,10 @@ class NaiveBayes { return `class` } - func calcLikelihoods(with input: [Double]) -> [(Int, Double)] { + //TODO fix this doesnt have to be a double + func classifyProba(with input: [Double]) -> [(Int, Double)] { + let classes = type.classes var probaClass = [Int: Double]() let amount = classes.count @@ -96,18 +192,15 @@ class NaiveBayes { probaClass[`class`] = Double(individual) / Double(amount) } - let classesAndFeatures = variables.map { (key, value) -> (Int, [Double]) in - let distributions = value.map { (feature, mean, stDev) -> Double in - let featureValue = input[feature] - let eulerPart = pow(M_E, -1 * pow(featureValue - mean, 2) / (2 * pow(stDev, 2))) - let distribution = eulerPart / sqrt(2 * .pi) / stDev - return distribution + let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in + let distribution = value.map { (feature, variables) -> Double in + return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 } - return (key, distributions) + return (`class`, distribution) } - let likelihoods = classesAndFeatures.map { (key, probaFeature) in - return (key, probaFeature.reduce(1, *) * (probaClass[key] ?? 1.0)) + let likelihoods = classesAndFeatures.map { (`class`, distribution) in + return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 1.0)) } let sum = likelihoods.map { $0.1 }.reduce(0, +) @@ -119,38 +212,6 @@ class NaiveBayes { } } -let data: [[Double]] = [ - [6, 180, 12], - [5.92, 190, 11], - [5.58, 170, 12], - [5.92, 165, 10], - [5, 100, 6], - [5.5, 150, 8], - [5.42, 130, 7], - [5.75, 150, 9] -] - -let classes = [0, 0, 0, 0, 1, 1, 1, 1] - -let naive = NaiveBayes(data: data, classes: classes) -naive.train() -print(naive.classify(with: [6, 130, 8])) - -let otherData: [[Double]] = [ - [6, 180, 12, 0], - [5.92, 190, 11, 0], - [5.58, 170, 12, 0], - [5.92, 165, 10, 0], - [5, 100, 6, 1], - [5.5, 150, 8, 1], - [5.42, 130, 7, 1], - [5.75, 150, 9, 1] -] - -let otherNaive = NaiveBayes(dataAndClasses: otherData, rowOfClass: 3) -otherNaive.train() -print(otherNaive.calcLikelihoods(with: [6, 130, 8])) - guard let csv = try? String(contentsOfFile: "/Users/ph1ps/Desktop/wine.csv") else { print("file not found") exit(0) @@ -162,6 +223,28 @@ let wineData = rows.map { row -> [Double] in return split.map { Double(String($0))! } } -let wineNaive = NaiveBayes(dataAndClasses: wineData, rowOfClass: 0) +let convertedWine = NaiveBayes.convert(dataAndClasses: wineData, rowOfClasses: 0) +let wineNaive = NaiveBayes(type: .gaussian(data: convertedWine.data, classes: convertedWine.classes)) wineNaive.train() -print(wineNaive.calcLikelihoods(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015])) +print(wineNaive.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015])) + +let golfData = [ + [0, 0, 0, 0], + [0, 0, 0, 1], + [1, 0, 0, 0], + [2, 1, 0, 0], + [2, 2, 1, 0], + [2, 2, 1, 1], + [1, 2, 1, 1], + [0, 1, 0, 0], + [0, 2, 1, 0], + [2, 1, 1, 0], + [0, 1, 1, 1], + [1, 1, 0, 1], + [1, 0, 1, 0], + [2, 1, 0, 1] +] +let golfClasses = [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0] +let golfNaive = NaiveBayes(type: .multinomial(data: golfData, classes: golfClasses)) +golfNaive.train() +print(golfNaive.classifyProba(with: [0, 2, 0, 1])) From 42db9a9d9a823a5bd0f2acf5f629881265ba7a83 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:12:10 +0300 Subject: [PATCH 0286/1039] Removed extra screenshots --- Dijkstra Algorithm/README.md | 4 ---- .../Screenshots/screenshot1.jpg | Bin 214771 -> 224243 bytes .../Screenshots/screenshot2.jpg | Bin 225916 -> 0 bytes .../Screenshots/screenshot3.jpg | Bin 224243 -> 0 bytes 4 files changed, 4 deletions(-) delete mode 100644 Dijkstra Algorithm/Screenshots/screenshot2.jpg delete mode 100644 Dijkstra Algorithm/Screenshots/screenshot3.jpg diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 872e9f851..10166a63f 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -17,7 +17,3 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Screenshots - - - - diff --git a/Dijkstra Algorithm/Screenshots/screenshot1.jpg b/Dijkstra Algorithm/Screenshots/screenshot1.jpg index 390bc658224310c7720678cffd68bf1654b5c045..e9f7a1207f315e8f5aa20c72f3264c65edafd3a8 100644 GIT binary patch literal 224243 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 literal 214771 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

@lrF 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 Ag8%>k diff --git a/Dijkstra Algorithm/Screenshots/screenshot2.jpg b/Dijkstra Algorithm/Screenshots/screenshot2.jpg deleted file mode 100644 index bc51046fb36bd2c77b11cf8f6bc28afd0a2faff8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 225916 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 diff --git a/Dijkstra Algorithm/Screenshots/screenshot3.jpg b/Dijkstra Algorithm/Screenshots/screenshot3.jpg deleted file mode 100644 index e9f7a1207f315e8f5aa20c72f3264c65edafd3a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224243 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 From a6020a54187ff8f473b1bccae3229846b7716258 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:13:19 +0300 Subject: [PATCH 0287/1039] Credits to the bottom --- Dijkstra Algorithm/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 10166a63f..bf158def9 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,6 +1,4 @@ # Dijkstra-algorithm -WWDC 2017 Scholarship Project -Created by [Taras Nikulin](https://github.com/crabman448) ## About Dijkstra's algorithm is used for finding shortest paths from start vertex in graph(with weighted vertices) to all other vertices. @@ -17,3 +15,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Screenshots + +## Credits +WWDC 2017 Scholarship Project +Created by [Taras Nikulin](https://github.com/crabman448) From a76764eaa0907a8ec455f911af14a0ad27087a95 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:16:05 +0300 Subject: [PATCH 0288/1039] Moved Vertex and Dijkstra classes to sources --- .../Dijkstra.playground/Contents.swift | 69 ------------------- .../Sources/Dijkstra.swift | 40 +++++++++++ .../Dijkstra.playground/Sources/Vertex.swift | 29 ++++++++ 3 files changed, 69 insertions(+), 69 deletions(-) create mode 100644 Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift create mode 100644 Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift index 13087a8f9..cd08e26fb 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -1,74 +1,5 @@ //: Playground - noun: a place where people can play - import Foundation -import UIKit - -open class Vertex: Hashable, Equatable { - - open var identifier: String! - open var neighbors: [(Vertex, Double)] = [] - open var pathLengthFromStart: Double = Double.infinity - open var pathVerticesFromStart: [Vertex] = [] - - public init(identifier: String) { - self.identifier = identifier - } - - open var hashValue: Int { - return self.identifier.hashValue - } - - public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { - if lhs.hashValue == rhs.hashValue { - return true - } - return false - } - - open func clearCache() { - self.pathLengthFromStart = Double.infinity - self.pathVerticesFromStart = [] - } -} - -public class Dijkstra { - private var totalVertices: Set - - public init(vertices: Set) { - self.totalVertices = vertices - } - - private func clearCache() { - self.totalVertices.forEach { $0.clearCache() } - } - - public func findShortestPaths(from startVertex: Vertex) { - self.clearCache() - startVertex.pathLengthFromStart = 0 - startVertex.pathVerticesFromStart.append(startVertex) - var currentVertex: Vertex! = startVertex - while currentVertex != nil { - totalVertices.remove(currentVertex) - let filteredNeighbors = currentVertex.neighbors.filter { totalVertices.contains($0.0) } - for neighbor in filteredNeighbors { - let neighborVertex = neighbor.0 - let weight = neighbor.1 - - let theoreticNewWeight = currentVertex.pathLengthFromStart + weight - if theoreticNewWeight < neighborVertex.pathLengthFromStart { - neighborVertex.pathLengthFromStart = theoreticNewWeight - neighborVertex.pathVerticesFromStart = currentVertex.pathVerticesFromStart - neighborVertex.pathVerticesFromStart.append(neighborVertex) - } - } - if totalVertices.isEmpty { - currentVertex = nil - break - } - currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } - } - } -} var _vertices: Set = Set() diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift new file mode 100644 index 000000000..0ae83589e --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift @@ -0,0 +1,40 @@ +import Foundation + +public class Dijkstra { + private var totalVertices: Set + + public init(vertices: Set) { + self.totalVertices = vertices + } + + private func clearCache() { + self.totalVertices.forEach { $0.clearCache() } + } + + public func findShortestPaths(from startVertex: Vertex) { + self.clearCache() + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(startVertex) + var currentVertex: Vertex! = startVertex + while currentVertex != nil { + totalVertices.remove(currentVertex) + let filteredNeighbors = currentVertex.neighbors.filter { totalVertices.contains($0.0) } + for neighbor in filteredNeighbors { + let neighborVertex = neighbor.0 + let weight = neighbor.1 + + let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + if theoreticNewWeight < neighborVertex.pathLengthFromStart { + neighborVertex.pathLengthFromStart = theoreticNewWeight + neighborVertex.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighborVertex.pathVerticesFromStart.append(neighborVertex) + } + } + if totalVertices.isEmpty { + currentVertex = nil + break + } + currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } + } + } +} diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift new file mode 100644 index 000000000..035db2713 --- /dev/null +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -0,0 +1,29 @@ +import Foundation + +open class Vertex: Hashable, Equatable { + + open var identifier: String! + open var neighbors: [(Vertex, Double)] = [] + open var pathLengthFromStart: Double = Double.infinity + open var pathVerticesFromStart: [Vertex] = [] + + public init(identifier: String) { + self.identifier = identifier + } + + open var hashValue: Int { + return self.identifier.hashValue + } + + public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { + if lhs.hashValue == rhs.hashValue { + return true + } + return false + } + + open func clearCache() { + self.pathLengthFromStart = Double.infinity + self.pathVerticesFromStart = [] + } +} From 3bdb63de34cba4abcc581980c83da650bc8d3ba4 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:17:45 +0300 Subject: [PATCH 0289/1039] Hashable, Equatable to Extensions --- .../Dijkstra.playground/Sources/Vertex.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index 035db2713..67ba3791e 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -1,6 +1,6 @@ import Foundation -open class Vertex: Hashable, Equatable { +open class Vertex { open var identifier: String! open var neighbors: [(Vertex, Double)] = [] @@ -11,19 +11,23 @@ open class Vertex: Hashable, Equatable { self.identifier = identifier } + open func clearCache() { + self.pathLengthFromStart = Double.infinity + self.pathVerticesFromStart = [] + } +} + +extension Vertex: Hashable { open var hashValue: Int { return self.identifier.hashValue } +} +extension Vertex: Equatable { public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { if lhs.hashValue == rhs.hashValue { return true } return false } - - open func clearCache() { - self.pathLengthFromStart = Double.infinity - self.pathVerticesFromStart = [] - } } From b2c5674b0c7d818cf061309e1cb7988e808d294b Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:18:44 +0300 Subject: [PATCH 0290/1039] Removed simplicity unwrapped for initialized variable --- Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index 67ba3791e..22c04a0e1 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -2,7 +2,7 @@ import Foundation open class Vertex { - open var identifier: String! + open var identifier: String open var neighbors: [(Vertex, Double)] = [] open var pathLengthFromStart: Double = Double.infinity open var pathVerticesFromStart: [Vertex] = [] From f0d057b89058c10cfe749990d5bdc3c669696610 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:19:34 +0300 Subject: [PATCH 0291/1039] Removed unnecessary explicit typing --- Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index 22c04a0e1..dcdc64691 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -4,7 +4,7 @@ open class Vertex { open var identifier: String open var neighbors: [(Vertex, Double)] = [] - open var pathLengthFromStart: Double = Double.infinity + open var pathLengthFromStart = Double.infinity open var pathVerticesFromStart: [Vertex] = [] public init(identifier: String) { From d0c68887780424e343f6663391eb5d70998fe166 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:20:05 +0300 Subject: [PATCH 0292/1039] Refactor Equatable extension --- Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index dcdc64691..89e66c68d 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -25,9 +25,6 @@ extension Vertex: Hashable { extension Vertex: Equatable { public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { - if lhs.hashValue == rhs.hashValue { - return true - } - return false + return lhs.hashValue == rhs.hashValue } } From 222e96d2f221c2f0549b5292be8b60adee93e1de Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:23:14 +0300 Subject: [PATCH 0293/1039] Made vertex optional --- .../Dijkstra.playground/Sources/Dijkstra.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift index 0ae83589e..f0a9386b4 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift @@ -15,18 +15,18 @@ public class Dijkstra { self.clearCache() startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) - var currentVertex: Vertex! = startVertex - while currentVertex != nil { - totalVertices.remove(currentVertex) - let filteredNeighbors = currentVertex.neighbors.filter { totalVertices.contains($0.0) } + var currentVertex: Vertex? = startVertex + while let vertex = currentVertex { + totalVertices.remove(vertex) + let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } for neighbor in filteredNeighbors { let neighborVertex = neighbor.0 let weight = neighbor.1 - let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + let theoreticNewWeight = vertex.pathLengthFromStart + weight if theoreticNewWeight < neighborVertex.pathLengthFromStart { neighborVertex.pathLengthFromStart = theoreticNewWeight - neighborVertex.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } From e2561032e31912df5dab472f7d63a3900d05ac70 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:26:57 +0300 Subject: [PATCH 0294/1039] Removed unnecessary self --- .../Dijkstra.playground/Sources/Dijkstra.swift | 6 +++--- Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift index f0a9386b4..f4cd8503a 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift @@ -4,15 +4,15 @@ public class Dijkstra { private var totalVertices: Set public init(vertices: Set) { - self.totalVertices = vertices + totalVertices = vertices } private func clearCache() { - self.totalVertices.forEach { $0.clearCache() } + totalVertices.forEach { $0.clearCache() } } public func findShortestPaths(from startVertex: Vertex) { - self.clearCache() + clearCache() startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) var currentVertex: Vertex? = startVertex diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift index 89e66c68d..a3587e04e 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Vertex.swift @@ -12,14 +12,14 @@ open class Vertex { } open func clearCache() { - self.pathLengthFromStart = Double.infinity - self.pathVerticesFromStart = [] + pathLengthFromStart = Double.infinity + pathVerticesFromStart = [] } } extension Vertex: Hashable { open var hashValue: Int { - return self.identifier.hashValue + return identifier.hashValue } } From 5060d788da63363809c93996aa9851751131e2d2 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:53:05 +0300 Subject: [PATCH 0295/1039] Removed self, unnecessary imports --- .../Sources/CustomUI/EdgeRepresentation.swift | 24 +- .../Sources/CustomUI/ErrorView.swift | 23 +- .../Sources/CustomUI/MyShapeLayer.swift | 1 - .../Sources/CustomUI/RoundedButton.swift | 8 +- .../Sources/CustomUI/VertexView.swift | 48 ++-- .../Sources/Graph.swift | 84 +++--- .../Sources/GraphView.swift | 62 ++-- .../Sources/SimpleObjects/Vertex.swift | 59 ++-- .../Sources/Window.swift | 272 +++++++++--------- 9 files changed, 291 insertions(+), 290 deletions(-) diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift index 5ff656dab..d827d3924 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/EdgeRepresentation.swift @@ -1,6 +1,6 @@ import UIKit -public class EdgeRepresentation: Equatable { +public class EdgeRepresentation { private var graphColors: GraphColors = GraphColors.sharedInstance public private(set)var label: UILabel! @@ -67,7 +67,7 @@ public class EdgeRepresentation: Equatable { let label = UILabel(frame: CGRect(origin: circleOrigin, size: CGSize(width: arcDiameter, height: arcDiameter))) label.textAlignment = .center - label.backgroundColor = self.graphColors.defaultEdgeColor + label.backgroundColor = graphColors.defaultEdgeColor label.clipsToBounds = true label.adjustsFontSizeToFitWidth = true label.layer.cornerRadius = arcDiameter / 2 @@ -75,35 +75,35 @@ public class EdgeRepresentation: Equatable { let shapeLayer = MyShapeLayer() shapeLayer.path = path.cgPath - shapeLayer.strokeColor = self.graphColors.defaultEdgeColor.cgColor + 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() { - self.layer.strokeColor = self.graphColors.checkingColor.cgColor - self.label.backgroundColor = self.graphColors.checkingColor + layer.strokeColor = graphColors.checkingColor.cgColor + label.backgroundColor = graphColors.checkingColor } public func setDefaultColor() { - self.layer.strokeColor = self.graphColors.defaultEdgeColor.cgColor - self.label.backgroundColor = self.graphColors.defaultEdgeColor + layer.strokeColor = graphColors.defaultEdgeColor.cgColor + label.backgroundColor = graphColors.defaultEdgeColor } public func setText(text: String) { - self.label.text = text + label.text = text } +} +extension EdgeRepresentation: Equatable { public static func ==(lhs: EdgeRepresentation, rhs: EdgeRepresentation) -> Bool { - if lhs.label.hashValue == rhs.label.hashValue && lhs.layer.hashValue == rhs.layer.hashValue { - return true - } - return false + return lhs.label.hashValue == rhs.label.hashValue && lhs.layer.hashValue == rhs.layer.hashValue } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift index 69874e5d7..a63655dd9 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/ErrorView.swift @@ -2,9 +2,10 @@ import UIKit public class ErrorView: UIView { private var label: UILabel! + public override init(frame: CGRect) { super.init(frame: frame) - self.commonInit() + commonInit() } public required init?(coder aDecoder: NSCoder) { @@ -12,19 +13,19 @@ public class ErrorView: UIView { } private func commonInit() { - self.backgroundColor = UIColor(red: 242/255, green: 156/255, blue: 84/255, alpha: 1) - self.layer.cornerRadius = 10 + backgroundColor = UIColor(red: 242/255, green: 156/255, blue: 84/255, alpha: 1) + layer.cornerRadius = 10 - let labelFrame = CGRect(x: 10, y: 10, width: self.frame.width - 20, height: self.frame.height - 20) - self.label = UILabel(frame: labelFrame) - self.label.numberOfLines = 0 - self.label.adjustsFontSizeToFitWidth = true - self.label.textAlignment = .center - self.label.textColor = UIColor.white - self.addSubview(self.label) + 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) { - self.label.text = text + label.text = text } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift index 54147f5e1..33bf4a515 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/MyShapeLayer.swift @@ -1,4 +1,3 @@ -import Foundation import UIKit public class MyShapeLayer: CAShapeLayer { diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift index 2647c4525..819fcfc5c 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/RoundedButton.swift @@ -5,7 +5,7 @@ public class RoundedButton: UIButton { public override init(frame: CGRect) { super.init(frame: frame) - self.commonInit() + commonInit() } public required init?(coder aDecoder: NSCoder) { @@ -13,8 +13,8 @@ public class RoundedButton: UIButton { } private func commonInit() { - self.backgroundColor = self.graphColors.buttonsBackgroundColor - self.titleLabel?.adjustsFontSizeToFitWidth = true - self.layer.cornerRadius = 7 + backgroundColor = graphColors.buttonsBackgroundColor + titleLabel?.adjustsFontSizeToFitWidth = true + layer.cornerRadius = 7 } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift index 29c971411..e785e120b 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/CustomUI/VertexView.swift @@ -15,49 +15,49 @@ public class VertexView: UIButton { precondition(frame.height == frame.width) precondition(frame.height >= 30) super.init(frame: frame) - self.backgroundColor = self.graphColors.defaultVertexColor - self.layer.cornerRadius = frame.width / 2 - self.clipsToBounds = true - self.setupIdLabel() - self.setupPathLengthFromStartLabel() + backgroundColor = graphColors.defaultVertexColor + layer.cornerRadius = frame.width / 2 + clipsToBounds = true + setupIdLabel() + setupPathLengthFromStartLabel() } private func setupIdLabel() { - let x: CGFloat = self.frame.width * 0.2 + let x: CGFloat = frame.width * 0.2 let y: CGFloat = 0 - let width: CGFloat = self.frame.width * 0.6 - let height: CGFloat = self.frame.height / 2 + let width: CGFloat = frame.width * 0.6 + let height: CGFloat = frame.height / 2 let idLabelFrame = CGRect(x: x, y: y, width: width, height: height) - self.idLabel = UILabel(frame: idLabelFrame) - self.idLabel.textAlignment = .center - self.idLabel.adjustsFontSizeToFitWidth = true - self.addSubview(self.idLabel) + idLabel = UILabel(frame: idLabelFrame) + idLabel.textAlignment = .center + idLabel.adjustsFontSizeToFitWidth = true + addSubview(idLabel) } private func setupPathLengthFromStartLabel() { - let x: CGFloat = self.frame.width * 0.2 - let y: CGFloat = self.frame.height / 2 - let width: CGFloat = self.frame.width * 0.6 - let height: CGFloat = self.frame.height / 2 + 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) - self.pathLengthLabel = UILabel(frame: pathLengthLabelFrame) - self.pathLengthLabel.textAlignment = .center - self.pathLengthLabel.adjustsFontSizeToFitWidth = true - self.addSubview(self.pathLengthLabel) + pathLengthLabel = UILabel(frame: pathLengthLabelFrame) + pathLengthLabel.textAlignment = .center + pathLengthLabel.adjustsFontSizeToFitWidth = true + addSubview(pathLengthLabel) } public func setIdLabel(text: String) { - self.idLabel.text = text + idLabel.text = text } public func setPathLengthLabel(text: String) { - self.pathLengthLabel.text = text + pathLengthLabel.text = text } public func setLabelsTextColor(color: UIColor) { - self.idLabel.textColor = color - self.pathLengthLabel.textColor = color + idLabel.textColor = color + pathLengthLabel.textColor = color } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift index 0b0b97b92..7c4a8e373 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift @@ -22,20 +22,20 @@ public class Graph { public var startVertex: Vertex! public var interactiveNeighborCheckAnimationDuration: Double = 1.8 { didSet { - self._interactiveOneSleepDuration = UInt32(self.interactiveNeighborCheckAnimationDuration * 1000000.0 / 3.0) + _interactiveOneSleepDuration = UInt32(interactiveNeighborCheckAnimationDuration * 1000000.0 / 3.0) } } private var _interactiveOneSleepDuration: UInt32 = 600000 public var visualizationNeighborCheckAnimationDuration: Double = 2.25 { didSet { - self._visualizationOneSleepDuration = UInt32(self.visualizationNeighborCheckAnimationDuration * 1000000.0 / 3.0) + _visualizationOneSleepDuration = UInt32(visualizationNeighborCheckAnimationDuration * 1000000.0 / 3.0) } } private var _visualizationOneSleepDuration: UInt32 = 750000 public var vertices: Set { - return self._vertices + return _vertices } public init(verticesCount: UInt) { @@ -43,46 +43,46 @@ public class Graph { } public func removeGraph() { - self._vertices.removeAll() - self.startVertex = nil + _vertices.removeAll() + startVertex = nil } public func createNewGraph() { - guard self._vertices.isEmpty, self.startVertex == nil else { + guard _vertices.isEmpty, startVertex == nil else { assertionFailure("Clear graph before creating new one") return } - self.createNotConnectedVertices() - self.setupConnections() - let offset = Int(arc4random_uniform(UInt32(self._vertices.count))) - let index = self._vertices.index(self._vertices.startIndex, offsetBy: offset) - self.startVertex = self._vertices[index] - self.setVertexLevels() + 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() { - self._vertices.forEach { $0.clearCache() } + _vertices.forEach { $0.clearCache() } } public func reset() { - for vertex in self._vertices { + for vertex in _vertices { vertex.clearCache() } } private func createNotConnectedVertices() { - for i in 0.. Vertex { - var newSet = self._vertices + var newSet = _vertices newSet.remove(vertex) let offset = Int(arc4random_uniform(UInt32(newSet.count))) let index = newSet.index(newSet.startIndex, offsetBy: offset) @@ -103,8 +103,8 @@ public class Graph { } private func setVertexLevels() { - self._vertices.forEach { $0.clearLevelInfo() } - guard let startVertex = self.startVertex else { + _vertices.forEach { $0.clearLevelInfo() } + guard let startVertex = startVertex else { assertionFailure() return } @@ -127,21 +127,21 @@ public class Graph { } public func findShortestPathsWithVisualization(completion: () -> Void) { - self.clearCache() + clearCache() startVertex.pathLengthFromStart = 0 - startVertex.pathVerticesFromStart.append(self.startVertex) - var currentVertex: Vertex! = self.startVertex + startVertex.pathVerticesFromStart.append(startVertex) + var currentVertex: Vertex! = startVertex - var totalVertices = self._vertices + var totalVertices = _vertices breakableLoop: while currentVertex != nil { totalVertices.remove(currentVertex) - while self.pauseVisualization == true { - if self.stopVisualization == true { + while pauseVisualization == true { + if stopVisualization == true { break breakableLoop } } - if self.stopVisualization == true { + if stopVisualization == true { break breakableLoop } DispatchQueue.main.async { @@ -155,12 +155,12 @@ public class Graph { let weight = edge.weight let edgeRepresentation = edge.edgeRepresentation - while self.pauseVisualization == true { - if self.stopVisualization == true { + while pauseVisualization == true { + if stopVisualization == true { break breakableLoop } } - if self.stopVisualization == true { + if stopVisualization == true { break breakableLoop } DispatchQueue.main.async { @@ -170,32 +170,32 @@ public class Graph { edgePathLength: weight, endVertexPathLength: neighbor.pathLengthFromStart) } - usleep(self._visualizationOneSleepDuration) + usleep(_visualizationOneSleepDuration) let theoreticNewWeight = currentVertex.pathLengthFromStart + weight if theoreticNewWeight < neighbor.pathLengthFromStart { - while self.pauseVisualization == true { - if self.stopVisualization == true { + while pauseVisualization == true { + if stopVisualization == true { break breakableLoop } } - if self.stopVisualization == true { + if stopVisualization == true { break breakableLoop } neighbor.pathLengthFromStart = theoreticNewWeight neighbor.pathVerticesFromStart = currentVertex.pathVerticesFromStart neighbor.pathVerticesFromStart.append(neighbor) } - usleep(self._visualizationOneSleepDuration) + usleep(_visualizationOneSleepDuration) DispatchQueue.main.async { self.delegate?.didFinishCompare() edge.edgeRepresentation?.setDefaultColor() edge.neighbor.setDefaultColor() } - usleep(self._visualizationOneSleepDuration) + usleep(_visualizationOneSleepDuration) } if totalVertices.isEmpty { currentVertex = nil @@ -203,7 +203,7 @@ public class Graph { } currentVertex = totalVertices.min { $0.pathLengthFromStart < $1.pathLengthFromStart } } - if self.stopVisualization == true { + if stopVisualization == true { DispatchQueue.main.async { self.delegate?.didStop() } @@ -294,10 +294,10 @@ public class Graph { } public func didTapVertex(vertex: Vertex) { - if self.nextVertices.contains(vertex) { - self.delegate?.willStartVertexNeighborsChecking() - self.state = .parsing - self.parseNeighborsFor(vertex: vertex) { + if nextVertices.contains(vertex) { + delegate?.willStartVertexNeighborsChecking() + state = .parsing + parseNeighborsFor(vertex: vertex) { self.state = .interactiveVisualization self.delegate?.didFinishVertexNeighborsChecking() } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift index 49bc6853f..bdeab7669 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift @@ -7,7 +7,7 @@ public class GraphView: UIView { public override init(frame: CGRect) { super.init(frame: frame) - self.backgroundColor = self.graphColors.graphBackgroundColor + backgroundColor = graphColors.graphBackgroundColor } public required init?(coder aDecoder: NSCoder) { @@ -20,13 +20,13 @@ public class GraphView: UIView { } public func removeGraph() { - for vertex in self.graph.vertices { + for vertex in graph.vertices { if let view = vertex.view { view.removeFromSuperview() vertex.view = nil } } - for vertex in self.graph.vertices { + for vertex in graph.vertices { for edge in vertex.edges { if let edgeRepresentation = edge.edgeRepresentation { edgeRepresentation.layer.removeFromSuperlayer() @@ -38,41 +38,41 @@ public class GraphView: UIView { } public func createNewGraph() { - self.setupVertexViews() - self.setupEdgeRepresentations() - self.addGraph() + setupVertexViews() + setupEdgeRepresentations() + addGraph() } public func reset() { - for vertex in self.graph.vertices { + for vertex in graph.vertices { vertex.edges.forEach { $0.edgeRepresentation?.setDefaultColor() } vertex.setDefaultColor() } } private func addGraph() { - for vertex in self.graph.vertices { + for vertex in graph.vertices { for edge in vertex.edges { if let edgeRepresentation = edge.edgeRepresentation { - self.layer.addSublayer(edgeRepresentation.layer) - self.addSubview(edgeRepresentation.label) + layer.addSublayer(edgeRepresentation.layer) + addSubview(edgeRepresentation.label) } } } - for vertex in self.graph.vertices { + for vertex in graph.vertices { if let view = vertex.view { - self.addSubview(view) + addSubview(view) } } } private func setupVertexViews() { var level = 0 - var buildViewQueue = [self.graph.startVertex!] + var buildViewQueue = [graph.startVertex!] let itemWidth: CGFloat = 40 while !buildViewQueue.isEmpty { let levelItemsCount = CGFloat(buildViewQueue.count) - let xStep = (self.frame.width - levelItemsCount * itemWidth) / (levelItemsCount + 1) + let xStep = (frame.width - levelItemsCount * itemWidth) / (levelItemsCount + 1) var previousVertexMaxX: CGFloat = 0.0 for vertex in buildViewQueue { let x: CGFloat = previousVertexMaxX + xStep @@ -84,12 +84,12 @@ public class GraphView: UIView { vertexView.vertex = vertex vertex.view?.setIdLabel(text: vertex.identifier) vertex.view?.setPathLengthLabel(text: "\(vertex.pathLengthFromStart)") - vertex.view?.addTarget(self, action: #selector(self.didTapVertex(sender:)), for: .touchUpInside) - let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:))) + 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 = self.graph.vertices.filter { $0.level == level } + buildViewQueue = graph.vertices.filter { $0.level == level } } } @@ -100,8 +100,8 @@ public class GraphView: UIView { guard let vertexView = recognizer.view as? VertexView, let vertex = vertexView.vertex else { return } - if self.panningView != nil { - if self.panningView != vertexView { + if panningView != nil { + if panningView != vertexView { return } } @@ -122,39 +122,39 @@ public class GraphView: UIView { } } } - self.panningView = vertexView + panningView = vertexView case .changed: - if self.movingVertexOutputEdges.isEmpty && self.movingVertexInputEdges.isEmpty { + 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) >= self.frame.width - || (vertexView.frame.origin.y + vertexView.frame.height + translation.y) >= self.frame.height { + || (vertexView.frame.origin.x + vertexView.frame.width + translation.x) >= frame.width + || (vertexView.frame.origin.y + vertexView.frame.height + translation.y) >= frame.height { break } - self.movingVertexInputEdges.forEach { edgeRepresentation in + 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 = self.path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: false) + let newPath = path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: false) edgeRepresentation.layer.path = newPath CATransaction.commit() } - self.movingVertexOutputEdges.forEach { edgeRepresentation in + 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 = self.path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: true) + let newPath = path(fromEdgeRepresentation: edgeRepresentation, movingVertex: vertex, translation: translation, outPath: true) edgeRepresentation.layer.path = newPath CATransaction.commit() } @@ -163,9 +163,9 @@ public class GraphView: UIView { y: vertexView.center.y + translation.y) recognizer.setTranslation(CGPoint.zero, in: self) case .ended: - self.movingVertexInputEdges = [] - self.movingVertexOutputEdges = [] - self.panningView = nil + movingVertexInputEdges = [] + movingVertexOutputEdges = [] + panningView = nil default: break } @@ -223,7 +223,7 @@ public class GraphView: UIView { } private func setupEdgeRepresentations() { - var edgeQueue: [Vertex] = [self.graph.startVertex!] + var edgeQueue: [Vertex] = [graph.startVertex!] //BFS while !edgeQueue.isEmpty { diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift index c9270b0df..f18ec3114 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/SimpleObjects/Vertex.swift @@ -1,10 +1,17 @@ import UIKit -public class Vertex: Hashable, Equatable { +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 { @@ -12,51 +19,45 @@ public class Vertex: Hashable, Equatable { } } } - 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 view: VertexView? public init(identifier: String) { self.identifier = identifier } - public var hashValue: Int { - return self.identifier.hashValue - } - - public static func ==(lhs: Vertex, rhs: Vertex) -> Bool { - if lhs.hashValue == rhs.hashValue { - return true - } - return false - } - public func clearCache() { - self.pathLengthFromStart = Double.infinity - self.pathVerticesFromStart = [] - self.visited = false + pathLengthFromStart = Double.infinity + pathVerticesFromStart = [] + visited = false } public func clearLevelInfo() { - self.level = 0 - self.levelChecked = false + level = 0 + levelChecked = false } public func setVisitedColor() { - self.view?.backgroundColor = self.graphColors.visitedColor - self.view?.setLabelsTextColor(color: UIColor.white) + view?.backgroundColor = graphColors.visitedColor + view?.setLabelsTextColor(color: UIColor.white) } public func setCheckingPathColor() { - self.view?.backgroundColor = self.graphColors.checkingColor + view?.backgroundColor = graphColors.checkingColor } public func setDefaultColor() { - self.view?.backgroundColor = self.graphColors.defaultVertexColor - self.view?.setLabelsTextColor(color: UIColor.black) + 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 } } diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift index e8aabad27..054b804c9 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift @@ -30,7 +30,7 @@ public class Window: UIView, GraphDelegate { public override init(frame: CGRect) { super.init(frame: frame) self.frame = frame - self.backgroundColor = self.graphColors.mainWindowBackgroundColor + backgroundColor = graphColors.mainWindowBackgroundColor } public required init?(coder aDecoder: NSCoder) { @@ -39,130 +39,130 @@ public class Window: UIView, GraphDelegate { public func configure(graph: Graph) { self.graph = graph - self.graph.createNewGraph() - self.graph.delegate = self + graph.createNewGraph() + graph.delegate = self let frame = CGRect(x: 10, y: 170, width: self.frame.width - 20, height: self.frame.height - 180) - self.graphView = GraphView(frame: frame) - self.graphView.layer.cornerRadius = 15 - - self.graphView.configure(graph: self.graph) - self.graphView.createNewGraph() - self.addSubview(self.graphView) - - self.configureCreateGraphButton() - self.configureStartVisualizationButton() - self.configureStartInteractiveVisualizationButton() - self.configureStartButton() - self.configurePauseButton() - self.configureStopButton() - self.configureComparisonLabel() - self.configureActivityIndicator() - - self.topView = UIView(frame: CGRect(x: 10, y: 10, width: self.frame.width - 20, height: 150)) - self.topView.backgroundColor = self.graphColors.topViewBackgroundColor - self.topView.layer.cornerRadius = 15 - self.addSubview(self.topView) - - self.topView.addSubview(self.createGraphButton) - self.topView.addSubview(self.startVisualizationButton) - self.topView.addSubview(self.startInteractiveVisualizationButton) - self.topView.addSubview(self.startButton) - self.topView.addSubview(self.pauseButton) - self.topView.addSubview(self.stopButton) - self.topView.addSubview(self.comparisonLabel) - self.topView.addSubview(self.activityIndicator) + graphView = GraphView(frame: frame) + graphView.layer.cornerRadius = 15 + + graphView.configure(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: self.center.x - 200, y: 12, width: 100, height: 34) - self.createGraphButton = RoundedButton(frame: frame) - self.createGraphButton.setTitle("New graph", for: .normal) - self.createGraphButton.addTarget(self, action: #selector(self.createGraphButtonTap), for: .touchUpInside) + 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: self.center.x - 50, y: 12, width: 100, height: 34) - self.startVisualizationButton = RoundedButton(frame: frame) - self.startVisualizationButton.setTitle("Auto", for: .normal) - self.startVisualizationButton.addTarget(self, action: #selector(self.startVisualizationButtonDidTap), for: .touchUpInside) + 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: self.center.x + 100, y: 12, width: 100, height: 34) - self.startInteractiveVisualizationButton = RoundedButton(frame: frame) - self.startInteractiveVisualizationButton.setTitle("Interactive", for: .normal) - self.startInteractiveVisualizationButton.addTarget(self, action: #selector(self.startInteractiveVisualizationButtonDidTap), for: .touchUpInside) + 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: self.center.x - 65, y: 56, width: 30, height: 30) - self.startButton = UIButton(frame: frame) + let frame = CGRect(x: center.x - 65, y: 56, width: 30, height: 30) + startButton = UIButton(frame: frame) let playImage = UIImage(named: "Start.png") - self.startButton.setImage(playImage, for: .normal) - self.startButton.isEnabled = false - self.startButton.addTarget(self, action: #selector(self.didTapStartButton), for: .touchUpInside) + startButton.setImage(playImage, for: .normal) + startButton.isEnabled = false + startButton.addTarget(self, action: #selector(didTapStartButton), for: .touchUpInside) } private func configurePauseButton() { - let frame = CGRect(x: self.center.x - 15, y: 56, width: 30, height: 30) - self.pauseButton = UIButton(frame: frame) + let frame = CGRect(x: center.x - 15, y: 56, width: 30, height: 30) + pauseButton = UIButton(frame: frame) let pauseImage = UIImage(named: "Pause.png") - self.pauseButton.setImage(pauseImage, for: .normal) - self.pauseButton.isEnabled = false - self.pauseButton.addTarget(self, action: #selector(self.didTapPauseButton), for: .touchUpInside) + pauseButton.setImage(pauseImage, for: .normal) + pauseButton.isEnabled = false + pauseButton.addTarget(self, action: #selector(didTapPauseButton), for: .touchUpInside) } private func configureStopButton() { - let frame = CGRect(x: self.center.x + 35, y: 56, width: 30, height: 30) - self.stopButton = UIButton(frame: frame) + let frame = CGRect(x: center.x + 35, y: 56, width: 30, height: 30) + stopButton = UIButton(frame: frame) let stopImage = UIImage(named: "Stop.png") - self.stopButton.setImage(stopImage, for: .normal) - self.stopButton.isEnabled = false - self.stopButton.addTarget(self, action: #selector(self.didTapStopButton), for: .touchUpInside) + 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: self.center.x - 125, y: 96) + let origin = CGPoint(x: center.x - 125, y: 96) let frame = CGRect(origin: origin, size: size) - self.comparisonLabel = UILabel(frame: frame) - self.comparisonLabel.textAlignment = .center - self.comparisonLabel.text = "Have fun!" + 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: self.center.x - 25, y: 100) + let origin = CGPoint(x: center.x - 25, y: 100) let activityIndicatorFrame = CGRect(origin: origin, size: size) - self.activityIndicator = UIActivityIndicatorView(frame: activityIndicatorFrame) - self.activityIndicator.activityIndicatorViewStyle = .whiteLarge + activityIndicator = UIActivityIndicatorView(frame: activityIndicatorFrame) + activityIndicator.activityIndicatorViewStyle = .whiteLarge } @objc private func createGraphButtonTap() { - self.comparisonLabel.text = "" - self.graphView.removeGraph() - self.graph.removeGraph() - self.graph.createNewGraph() - self.graphView.createNewGraph() - self.graph.state = .initial + comparisonLabel.text = "" + graphView.removeGraph() + graph.removeGraph() + graph.createNewGraph() + graphView.createNewGraph() + graph.state = .initial } @objc private func startVisualizationButtonDidTap() { - self.comparisonLabel.text = "" - self.pauseButton.isEnabled = true - self.stopButton.isEnabled = true - self.createGraphButton.isEnabled = false - self.startVisualizationButton.isEnabled = false - self.startInteractiveVisualizationButton.isEnabled = false - self.createGraphButton.alpha = 0.5 - self.startVisualizationButton.alpha = 0.5 - self.startInteractiveVisualizationButton.alpha = 0.5 - - if self.graph.state == .completed { - self.graphView.reset() - self.graph.reset() + 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() } - self.graph.state = .autoVisualization + graph.state = .autoVisualization DispatchQueue.global(qos: .background).async { self.graph.findShortestPathsWithVisualization { self.graph.state = .completed @@ -184,25 +184,25 @@ public class Window: UIView, GraphDelegate { } @objc private func startInteractiveVisualizationButtonDidTap() { - self.comparisonLabel.text = "" - self.pauseButton.isEnabled = true - self.stopButton.isEnabled = true - self.createGraphButton.isEnabled = false - self.startVisualizationButton.isEnabled = false - self.startInteractiveVisualizationButton.isEnabled = false - self.createGraphButton.alpha = 0.5 - self.startVisualizationButton.alpha = 0.5 - self.startInteractiveVisualizationButton.alpha = 0.5 - - if self.graph.state == .completed { - self.graphView.reset() - self.graph.reset() + 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() } - self.graph.startVertex.pathLengthFromStart = 0 - self.graph.startVertex.pathVerticesFromStart.append(self.graph.startVertex) - self.graph.state = .parsing - self.graph.parseNeighborsFor(vertex: self.graph.startVertex) { + graph.startVertex.pathLengthFromStart = 0 + graph.startVertex.pathVerticesFromStart.append(graph.startVertex) + graph.state = .parsing + graph.parseNeighborsFor(vertex: graph.startVertex) { self.graph.state = .interactiveVisualization DispatchQueue.main.async { self.comparisonLabel.text = "Pick next vertex" @@ -211,43 +211,43 @@ public class Window: UIView, GraphDelegate { } @objc private func didTapStartButton() { - self.startButton.isEnabled = false - self.pauseButton.isEnabled = true + startButton.isEnabled = false + pauseButton.isEnabled = true DispatchQueue.global(qos: .utility).async { self.graph.pauseVisualization = false } } @objc private func didTapPauseButton() { - self.startButton.isEnabled = true - self.pauseButton.isEnabled = false + startButton.isEnabled = true + pauseButton.isEnabled = false DispatchQueue.global(qos: .utility).async { self.graph.pauseVisualization = true } } @objc private func didTapStopButton() { - self.startButton.isEnabled = false - self.pauseButton.isEnabled = false - self.comparisonLabel.text = "" - self.activityIndicator.startAnimating() - if self.graph.state == .parsing || self.graph.state == .autoVisualization { - self.graph.stopVisualization = true - } else if self.graph.state == .interactiveVisualization { - self.didStop() + 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() { - self.createGraphButton.isEnabled = true - self.startVisualizationButton.isEnabled = true - self.startInteractiveVisualizationButton.isEnabled = true - self.startButton.isEnabled = false - self.pauseButton.isEnabled = false - self.stopButton.isEnabled = false - self.createGraphButton.alpha = 1 - self.startVisualizationButton.alpha = 1 - self.startInteractiveVisualizationButton.alpha = 1 + 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) { @@ -268,14 +268,14 @@ public class Window: UIView, GraphDelegate { // MARK: GraphDelegate public func didCompleteGraphParsing() { - self.graph.state = .completed - self.setButtonsToInitialState() - self.comparisonLabel.text = "Completed!" + graph.state = .completed + setButtonsToInitialState() + comparisonLabel.text = "Completed!" } public func didTapWrongVertex() { - if !self.subviews.contains { $0 is ErrorView } { - self.showError(error: "You have picked wrong next vertex") + if !subviews.contains { $0 is ErrorView } { + showError(error: "You have picked wrong next vertex") } } @@ -296,13 +296,13 @@ public class Window: UIView, GraphDelegate { } public func didStop() { - self.graph.state = .initial - self.graph.stopVisualization = false - self.graph.pauseVisualization = false - self.graphView.reset() - self.graph.reset() - self.setButtonsToInitialState() - self.activityIndicator.stopAnimating() + graph.state = .initial + graph.stopVisualization = false + graph.pauseVisualization = false + graphView.reset() + graph.reset() + setButtonsToInitialState() + activityIndicator.stopAnimating() } public func willStartVertexNeighborsChecking() { From 900b7caf229697f5666627bd7cdc34c6f1143702 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 12:56:12 +0300 Subject: [PATCH 0296/1039] Replaced with optional --- .../Sources/Graph.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift index 7c4a8e373..8bf2452cc 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift @@ -130,12 +130,12 @@ public class Graph { clearCache() startVertex.pathLengthFromStart = 0 startVertex.pathVerticesFromStart.append(startVertex) - var currentVertex: Vertex! = startVertex + var currentVertex: Vertex? = startVertex var totalVertices = _vertices - breakableLoop: while currentVertex != nil { - totalVertices.remove(currentVertex) + breakableLoop: while let vertex = currentVertex { + totalVertices.remove(vertex) while pauseVisualization == true { if stopVisualization == true { break breakableLoop @@ -145,11 +145,11 @@ public class Graph { break breakableLoop } DispatchQueue.main.async { - currentVertex.setVisitedColor() + vertex.setVisitedColor() } usleep(750000) - currentVertex.visited = true - let filteredEdges = currentVertex.edges.filter { !$0.neighbor.visited } + vertex.visited = true + let filteredEdges = vertex.edges.filter { !$0.neighbor.visited } for edge in filteredEdges { let neighbor = edge.neighbor let weight = edge.weight @@ -166,14 +166,14 @@ public class Graph { DispatchQueue.main.async { edgeRepresentation?.setCheckingColor() neighbor.setCheckingPathColor() - self.delegate?.willCompareVertices(startVertexPathLength: currentVertex.pathLengthFromStart, + self.delegate?.willCompareVertices(startVertexPathLength: vertex.pathLengthFromStart, edgePathLength: weight, endVertexPathLength: neighbor.pathLengthFromStart) } usleep(_visualizationOneSleepDuration) - let theoreticNewWeight = currentVertex.pathLengthFromStart + weight + let theoreticNewWeight = vertex.pathLengthFromStart + weight if theoreticNewWeight < neighbor.pathLengthFromStart { while pauseVisualization == true { @@ -185,7 +185,7 @@ public class Graph { break breakableLoop } neighbor.pathLengthFromStart = theoreticNewWeight - neighbor.pathVerticesFromStart = currentVertex.pathVerticesFromStart + neighbor.pathVerticesFromStart = vertex.pathVerticesFromStart neighbor.pathVerticesFromStart.append(neighbor) } usleep(_visualizationOneSleepDuration) From 2a1a2a1a7bbdf738b8643d49775ccf7895d476b6 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 13:27:18 +0300 Subject: [PATCH 0297/1039] Refactored a bit --- .../Sources/Graph.swift | 14 ++++++++------ .../Sources/GraphView.swift | 12 +++++------- .../Sources/Window.swift | 19 +++++++++++-------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift index 8bf2452cc..447b3dbe1 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Graph.swift @@ -10,16 +10,14 @@ public enum GraphState { } public class Graph { - private init() { } - - private var verticesCount: UInt! + 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: Bool = false - public var stopVisualization: Bool = false - public var startVertex: Vertex! + 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) @@ -127,6 +125,10 @@ public class Graph { } 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) diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift index bdeab7669..ec4f74705 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/GraphView.swift @@ -1,13 +1,15 @@ import UIKit public class GraphView: UIView { - private var graph: Graph! + private var graph: Graph private var panningView: VertexView? = nil - private var graphColors: GraphColors = GraphColors.sharedInstance + private var graphColors = GraphColors.sharedInstance - public override init(frame: CGRect) { + 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) { @@ -15,10 +17,6 @@ public class GraphView: UIView { } - public func configure(graph: Graph) { - self.graph = graph - } - public func removeGraph() { for vertex in graph.vertices { if let view = vertex.view { diff --git a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift index 054b804c9..73c512e6b 100644 --- a/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift +++ b/Dijkstra Algorithm/VisualizedDijkstra.playground/Sources/Window.swift @@ -25,7 +25,7 @@ public class Window: UIView, GraphDelegate { private var activityIndicator: UIActivityIndicatorView! private var graph: Graph! private var numberOfVertices: UInt! - private var graphColors: GraphColors = GraphColors.sharedInstance + private var graphColors = GraphColors.sharedInstance public override init(frame: CGRect) { super.init(frame: frame) @@ -42,10 +42,9 @@ public class Window: UIView, GraphDelegate { 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) - graphView.layer.cornerRadius = 15 + graphView = GraphView(frame: frame, graph: graph) + - graphView.configure(graph: graph) graphView.createNewGraph() addSubview(graphView) @@ -198,11 +197,15 @@ public class Window: UIView, GraphDelegate { graphView.reset() graph.reset() } - - graph.startVertex.pathLengthFromStart = 0 - graph.startVertex.pathVerticesFromStart.append(graph.startVertex) + + guard let startVertex = graph.startVertex else { + assertionFailure("startVertex is nil") + return + } + startVertex.pathLengthFromStart = 0 + startVertex.pathVerticesFromStart.append(startVertex) graph.state = .parsing - graph.parseNeighborsFor(vertex: graph.startVertex) { + graph.parseNeighborsFor(vertex: startVertex) { self.graph.state = .interactiveVisualization DispatchQueue.main.async { self.comparisonLabel.text = "Pick next vertex" From 846101720981de86abf8fe8f372715fa50f12dcb Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:02:43 +0300 Subject: [PATCH 0298/1039] Updated description --- Dijkstra Algorithm/README.md | 38 ++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index bf158def9..2bbf74b87 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,21 +1,39 @@ # Dijkstra-algorithm -## About -Dijkstra's algorithm is used for finding shortest paths from start vertex in graph(with weighted vertices) to all other vertices. -More algorithm's description can be found in playground or on wikipedia: -[Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) - -To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. - -If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. +## About this repository +This repository contains to playgrounds: +* To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. +* If you need only realization of the algorithm without visualization 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) ## Screenshots - +## Dijkstra's algorithm explanation + +Wikipedia's explanation: +Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. + +1. Assign to every node a tentative distance value: set it to zero for our initial node and to infinity for all other nodes. +2. Set the initial node as current. Mark all other nodes unvisited. Create a set of all the unvisited nodes called the unvisited set. +3. For the current node, consider all of its unvisited neighbors and calculate their tentative distances. Compare the newly calculated tentative distance to the current assigned value and assign the smaller one. For example, if the current node A is marked with a distance of 6, and the edge connecting it with a neighbor B has length 2, then the distance to B (through A) will be 6 + 2 = 8. If B was previously marked with a distance greater than 8 then change it to 8. Otherwise, keep the current value. +4. When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again. +5. If the destination node has been marked visited (when planning a route between two specific nodes) or if the smallest tentative distance among the nodes in the unvisited set is infinity (when planning a complete traversal; occurs when there is no connection between the initial node and remaining unvisited nodes), then stop. The algorithm has finished. +6. Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3. + +Explanation, that can be found in the **VisualizedDijkstra.playground** +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. + ## Credits -WWDC 2017 Scholarship Project +WWDC 2017 Scholarship Project Created by [Taras Nikulin](https://github.com/crabman448) From f7793cc6b6692000e4fd878afce62fd67d5b5f00 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:38:47 +0300 Subject: [PATCH 0299/1039] Added gif --- Dijkstra Algorithm/Images/Dijkstra_Animation.gif | Bin 0 -> 8561 bytes .../{Screenshots => Images}/screenshot1.jpg | Bin Dijkstra Algorithm/README.md | 8 +++++++- 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 Dijkstra Algorithm/Images/Dijkstra_Animation.gif rename Dijkstra Algorithm/{Screenshots => Images}/screenshot1.jpg (100%) diff --git a/Dijkstra Algorithm/Images/Dijkstra_Animation.gif b/Dijkstra Algorithm/Images/Dijkstra_Animation.gif new file mode 100644 index 0000000000000000000000000000000000000000..3b1a2ef434107efb104a9bc1a6a714af37367529 GIT binary patch literal 8561 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Screenshots/screenshot1.jpg b/Dijkstra Algorithm/Images/screenshot1.jpg similarity index 100% rename from Dijkstra Algorithm/Screenshots/screenshot1.jpg rename to Dijkstra Algorithm/Images/screenshot1.jpg diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 2bbf74b87..0ac4bc17e 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -9,10 +9,12 @@ This repository contains to playgrounds: Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Screenshots - + ## Dijkstra's algorithm explanation + + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. @@ -34,6 +36,10 @@ Cycle: 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. +## Usage + + + ## Credits WWDC 2017 Scholarship Project Created by [Taras Nikulin](https://github.com/crabman448) From 3f6be33a1750d6f9122ca8ab38b70c3a9e4d123b Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:40:34 +0300 Subject: [PATCH 0300/1039] Added link --- Dijkstra Algorithm/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 0ac4bc17e..b2606f0f9 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -13,7 +13,8 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Dijkstra's algorithm explanation - +GIF from Wikipedia + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. From a153067e60fcd90d8a8b6448fbc5d9e0c5753076 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:41:35 +0300 Subject: [PATCH 0301/1039] Updated link --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index b2606f0f9..cf939c7cc 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -14,7 +14,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Dijkstra's algorithm explanation GIF from Wikipedia - + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. From b59ffa53930e3021a22bee31923965a12f7031a3 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:42:10 +0300 Subject: [PATCH 0302/1039] Revert "Updated link" This reverts commit a153067e60fcd90d8a8b6448fbc5d9e0c5753076. --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index cf939c7cc..b2606f0f9 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -14,7 +14,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Dijkstra's algorithm explanation GIF from Wikipedia - + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. From ef13b5076e1741023c6d014e32266044d8d63d7b Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:42:40 +0300 Subject: [PATCH 0303/1039] Revert "Added link" This reverts commit 3f6be33a1750d6f9122ca8ab38b70c3a9e4d123b. --- Dijkstra Algorithm/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index b2606f0f9..0ac4bc17e 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -13,8 +13,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Dijkstra's algorithm explanation -GIF from Wikipedia - + Wikipedia's explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. From aea01e8b68d7fefd06ccae2d3afeb253a43abba0 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Mon, 17 Apr 2017 14:44:39 +0300 Subject: [PATCH 0304/1039] Added link to Wikipedia This reverts commit a153067e60fcd90d8a8b6448fbc5d9e0c5753076. --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 0ac4bc17e..325bab40f 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -15,7 +15,7 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) -Wikipedia's explanation: +[Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)'s explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. 1. Assign to every node a tentative distance value: set it to zero for our initial node and to infinity for all other nodes. From edafd431fab46087ff805f6ad419b076a076bf82 Mon Sep 17 00:00:00 2001 From: ph1ps Date: Mon, 17 Apr 2017 21:15:01 +0200 Subject: [PATCH 0305/1039] Add playground --- .../NaiveBayes.playground/Contents.swift | 60 ++++++ .../NaiveBayes.playground/Resources/wine.csv | 177 ++++++++++++++++ .../Sources/NaiveBayes.swift | 196 ++++++++++++++++++ .../contents.xcplayground | 4 + .../contents.xcworkspacedata | 7 + Naive Bayes Classifier/NaiveBayes.swift | 124 ++++------- 6 files changed, 479 insertions(+), 89 deletions(-) create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/Contents.swift create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift new file mode 100644 index 000000000..cb820272e --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift @@ -0,0 +1,60 @@ +import Foundation + +/*: + ## Naive Bayes Classifier + + This playground uses the given algorithm and utilizes its features with some example datasets + + ### Gaussian Naive Bayes + - Note: + When using Gaussian NB you have to have continuous features (Double). + + For this example we are going to use a famous dataset with different types of wine. The labels of the features can be viewed [here](https://gist.github.com/tijptjik/9408623) + */ +guard let wineCSV = Bundle.main.path(forResource: "wine", ofType: "csv") else { + print("Resource could not be found!") + exit(0) +} + +guard let csv = try? String(contentsOfFile: wineCSV) else { + print("File could not be read!") + exit(0) +} + +/*: + Reading the .csv file line per line + */ +let rows = csv.characters.split(separator: "\r\n").map { String($0) } +/*: + Splitting on the ; sign and converting the value to a Double + + - Important: + Do not force unwrap the mapped values in your real application. Carefully convert them! This is just for the sake of showing how the algorithm works. + */ +let wineData = rows.map { row -> [Double] in + let split = row.characters.split(separator: ";") + return split.map { Double(String($0))! } +} + +/*: + The algorithm wants the classes and the data seperated since this gives a huge performance boost. Also I haven't implemented this in the NB class itself since it is not in the scope of it. + */ +let rowOfClasses = 0 +let classes = wineData.map { Int($0[rowOfClasses]) } +let data = wineData.map { row in + return row.enumerated().filter { $0.offset != rowOfClasses }.map { $0.element } +} + +/*: + Again use `guard` on the result of a `try?` or simply `do-try-catch` because this would crash your application if an error occured. + + The array in the `classifyProba` method I passed is a former entry in the .csv file which I removed in order to classify it. + */ +let wineBayes = try! NaiveBayes(type: .gaussian, data: data, classes: classes).train() +let result = wineBayes.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015]) +print(result) +/*: + I can assure you that this is the correct result and as you can see the classifier thinks that its ***99.99%*** correct too. + + ### Multinomial Naive Bayes + */ diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv b/Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv new file mode 100644 index 000000000..89e14fd02 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/Resources/wine.csv @@ -0,0 +1,177 @@ +1;14.23;1.71;2.43;15.6;127;2.8;3.06;.28;2.29;5.64;1.04;3.92;1065 +1;13.2;1.78;2.14;11.2;100;2.65;2.76;.26;1.28;4.38;1.05;3.4;1050 +1;13.16;2.36;2.67;18.6;101;2.8;3.24;.3;2.81;5.68;1.03;3.17;1185 +1;14.37;1.95;2.5;16.8;113;3.85;3.49;.24;2.18;7.8;.86;3.45;1480 +1;13.24;2.59;2.87;21;118;2.8;2.69;.39;1.82;4.32;1.04;2.93;735 +1;14.2;1.76;2.45;15.2;112;3.27;3.39;.34;1.97;6.75;1.05;2.85;1450 +1;14.39;1.87;2.45;14.6;96;2.5;2.52;.3;1.98;5.25;1.02;3.58;1290 +1;14.06;2.15;2.61;17.6;121;2.6;2.51;.31;1.25;5.05;1.06;3.58;1295 +1;14.83;1.64;2.17;14;97;2.8;2.98;.29;1.98;5.2;1.08;2.85;1045 +1;13.86;1.35;2.27;16;98;2.98;3.15;.22;1.85;7.22;1.01;3.55;1045 +1;14.1;2.16;2.3;18;105;2.95;3.32;.22;2.38;5.75;1.25;3.17;1510 +1;14.12;1.48;2.32;16.8;95;2.2;2.43;.26;1.57;5;1.17;2.82;1280 +1;13.75;1.73;2.41;16;89;2.6;2.76;.29;1.81;5.6;1.15;2.9;1320 +1;14.75;1.73;2.39;11.4;91;3.1;3.69;.43;2.81;5.4;1.25;2.73;1150 +1;14.38;1.87;2.38;12;102;3.3;3.64;.29;2.96;7.5;1.2;3;1547 +1;13.63;1.81;2.7;17.2;112;2.85;2.91;.3;1.46;7.3;1.28;2.88;1310 +1;14.3;1.92;2.72;20;120;2.8;3.14;.33;1.97;6.2;1.07;2.65;1280 +1;13.83;1.57;2.62;20;115;2.95;3.4;.4;1.72;6.6;1.13;2.57;1130 +1;14.19;1.59;2.48;16.5;108;3.3;3.93;.32;1.86;8.7;1.23;2.82;1680 +1;13.64;3.1;2.56;15.2;116;2.7;3.03;.17;1.66;5.1;.96;3.36;845 +1;14.06;1.63;2.28;16;126;3;3.17;.24;2.1;5.65;1.09;3.71;780 +1;12.93;3.8;2.65;18.6;102;2.41;2.41;.25;1.98;4.5;1.03;3.52;770 +1;13.71;1.86;2.36;16.6;101;2.61;2.88;.27;1.69;3.8;1.11;4;1035 +1;13.5;1.81;2.61;20;96;2.53;2.61;.28;1.66;3.52;1.12;3.82;845 +1;13.05;2.05;3.22;25;124;2.63;2.68;.47;1.92;3.58;1.13;3.2;830 +1;13.39;1.77;2.62;16.1;93;2.85;2.94;.34;1.45;4.8;.92;3.22;1195 +1;13.3;1.72;2.14;17;94;2.4;2.19;.27;1.35;3.95;1.02;2.77;1285 +1;13.87;1.9;2.8;19.4;107;2.95;2.97;.37;1.76;4.5;1.25;3.4;915 +1;14.02;1.68;2.21;16;96;2.65;2.33;.26;1.98;4.7;1.04;3.59;1035 +1;13.73;1.5;2.7;22.5;101;3;3.25;.29;2.38;5.7;1.19;2.71;1285 +1;13.58;1.66;2.36;19.1;106;2.86;3.19;.22;1.95;6.9;1.09;2.88;1515 +1;13.68;1.83;2.36;17.2;104;2.42;2.69;.42;1.97;3.84;1.23;2.87;990 +1;13.76;1.53;2.7;19.5;132;2.95;2.74;.5;1.35;5.4;1.25;3;1235 +1;13.51;1.8;2.65;19;110;2.35;2.53;.29;1.54;4.2;1.1;2.87;1095 +1;13.48;1.81;2.41;20.5;100;2.7;2.98;.26;1.86;5.1;1.04;3.47;920 +1;13.28;1.64;2.84;15.5;110;2.6;2.68;.34;1.36;4.6;1.09;2.78;880 +1;13.05;1.65;2.55;18;98;2.45;2.43;.29;1.44;4.25;1.12;2.51;1105 +1;13.07;1.5;2.1;15.5;98;2.4;2.64;.28;1.37;3.7;1.18;2.69;1020 +1;14.22;3.99;2.51;13.2;128;3;3.04;.2;2.08;5.1;.89;3.53;760 +1;13.56;1.71;2.31;16.2;117;3.15;3.29;.34;2.34;6.13;.95;3.38;795 +1;13.41;3.84;2.12;18.8;90;2.45;2.68;.27;1.48;4.28;.91;3;1035 +1;13.88;1.89;2.59;15;101;3.25;3.56;.17;1.7;5.43;.88;3.56;1095 +1;13.24;3.98;2.29;17.5;103;2.64;2.63;.32;1.66;4.36;.82;3;680 +1;13.05;1.77;2.1;17;107;3;3;.28;2.03;5.04;.88;3.35;885 +1;14.21;4.04;2.44;18.9;111;2.85;2.65;.3;1.25;5.24;.87;3.33;1080 +1;14.38;3.59;2.28;16;102;3.25;3.17;.27;2.19;4.9;1.04;3.44;1065 +1;13.9;1.68;2.12;16;101;3.1;3.39;.21;2.14;6.1;.91;3.33;985 +1;14.1;2.02;2.4;18.8;103;2.75;2.92;.32;2.38;6.2;1.07;2.75;1060 +1;13.94;1.73;2.27;17.4;108;2.88;3.54;.32;2.08;8.90;1.12;3.1;1260 +1;13.05;1.73;2.04;12.4;92;2.72;3.27;.17;2.91;7.2;1.12;2.91;1150 +1;13.83;1.65;2.6;17.2;94;2.45;2.99;.22;2.29;5.6;1.24;3.37;1265 +1;13.82;1.75;2.42;14;111;3.88;3.74;.32;1.87;7.05;1.01;3.26;1190 +1;13.77;1.9;2.68;17.1;115;3;2.79;.39;1.68;6.3;1.13;2.93;1375 +1;13.74;1.67;2.25;16.4;118;2.6;2.9;.21;1.62;5.85;.92;3.2;1060 +1;13.56;1.73;2.46;20.5;116;2.96;2.78;.2;2.45;6.25;.98;3.03;1120 +1;14.22;1.7;2.3;16.3;118;3.2;3;.26;2.03;6.38;.94;3.31;970 +1;13.29;1.97;2.68;16.8;102;3;3.23;.31;1.66;6;1.07;2.84;1270 +1;13.72;1.43;2.5;16.7;108;3.4;3.67;.19;2.04;6.8;.89;2.87;1285 +2;12.37;.94;1.36;10.6;88;1.98;.57;.28;.42;1.95;1.05;1.82;520 +2;12.33;1.1;2.28;16;101;2.05;1.09;.63;.41;3.27;1.25;1.67;680 +2;12.64;1.36;2.02;16.8;100;2.02;1.41;.53;.62;5.75;.98;1.59;450 +2;13.67;1.25;1.92;18;94;2.1;1.79;.32;.73;3.8;1.23;2.46;630 +2;12.37;1.13;2.16;19;87;3.5;3.1;.19;1.87;4.45;1.22;2.87;420 +2;12.17;1.45;2.53;19;104;1.89;1.75;.45;1.03;2.95;1.45;2.23;355 +2;12.37;1.21;2.56;18.1;98;2.42;2.65;.37;2.08;4.6;1.19;2.3;678 +2;13.11;1.01;1.7;15;78;2.98;3.18;.26;2.28;5.3;1.12;3.18;502 +2;12.37;1.17;1.92;19.6;78;2.11;2;.27;1.04;4.68;1.12;3.48;510 +2;13.34;.94;2.36;17;110;2.53;1.3;.55;.42;3.17;1.02;1.93;750 +2;12.21;1.19;1.75;16.8;151;1.85;1.28;.14;2.5;2.85;1.28;3.07;718 +2;12.29;1.61;2.21;20.4;103;1.1;1.02;.37;1.46;3.05;906;1.82;870 +2;13.86;1.51;2.67;25;86;2.95;2.86;.21;1.87;3.38;1.36;3.16;410 +2;13.49;1.66;2.24;24;87;1.88;1.84;.27;1.03;3.74;.98;2.78;472 +2;12.99;1.67;2.6;30;139;3.3;2.89;.21;1.96;3.35;1.31;3.5;985 +2;11.96;1.09;2.3;21;101;3.38;2.14;.13;1.65;3.21;.99;3.13;886 +2;11.66;1.88;1.92;16;97;1.61;1.57;.34;1.15;3.8;1.23;2.14;428 +2;13.03;.9;1.71;16;86;1.95;2.03;.24;1.46;4.6;1.19;2.48;392 +2;11.84;2.89;2.23;18;112;1.72;1.32;.43;.95;2.65;.96;2.52;500 +2;12.33;.99;1.95;14.8;136;1.9;1.85;.35;2.76;3.4;1.06;2.31;750 +2;12.7;3.87;2.4;23;101;2.83;2.55;.43;1.95;2.57;1.19;3.13;463 +2;12;.92;2;19;86;2.42;2.26;.3;1.43;2.5;1.38;3.12;278 +2;12.72;1.81;2.2;18.8;86;2.2;2.53;.26;1.77;3.9;1.16;3.14;714 +2;12.08;1.13;2.51;24;78;2;1.58;.4;1.4;2.2;1.31;2.72;630 +2;13.05;3.86;2.32;22.5;85;1.65;1.59;.61;1.62;4.8;.84;2.01;515 +2;11.84;.89;2.58;18;94;2.2;2.21;.22;2.35;3.05;.79;3.08;520 +2;12.67;.98;2.24;18;99;2.2;1.94;.3;1.46;2.62;1.23;3.16;450 +2;12.16;1.61;2.31;22.8;90;1.78;1.69;.43;1.56;2.45;1.33;2.26;495 +2;11.65;1.67;2.62;26;88;1.92;1.61;.4;1.34;2.6;1.36;3.21;562 +2;11.64;2.06;2.46;21.6;84;1.95;1.69;.48;1.35;2.8;1;2.75;680 +2;12.08;1.33;2.3;23.6;70;2.2;1.59;.42;1.38;1.74;1.07;3.21;625 +2;12.08;1.83;2.32;18.5;81;1.6;1.5;.52;1.64;2.4;1.08;2.27;480 +2;12;1.51;2.42;22;86;1.45;1.25;.5;1.63;3.6;1.05;2.65;450 +2;12.69;1.53;2.26;20.7;80;1.38;1.46;.58;1.62;3.05;.96;2.06;495 +2;12.29;2.83;2.22;18;88;2.45;2.25;.25;1.99;2.15;1.15;3.3;290 +2;11.62;1.99;2.28;18;98;3.02;2.26;.17;1.35;3.25;1.16;2.96;345 +2;12.47;1.52;2.2;19;162;2.5;2.27;.32;3.28;2.6;1.16;2.63;937 +2;11.81;2.12;2.74;21.5;134;1.6;.99;.14;1.56;2.5;.95;2.26;625 +2;12.29;1.41;1.98;16;85;2.55;2.5;.29;1.77;2.9;1.23;2.74;428 +2;12.37;1.07;2.1;18.5;88;3.52;3.75;.24;1.95;4.5;1.04;2.77;660 +2;12.29;3.17;2.21;18;88;2.85;2.99;.45;2.81;2.3;1.42;2.83;406 +2;12.08;2.08;1.7;17.5;97;2.23;2.17;.26;1.4;3.3;1.27;2.96;710 +2;12.6;1.34;1.9;18.5;88;1.45;1.36;.29;1.35;2.45;1.04;2.77;562 +2;12.34;2.45;2.46;21;98;2.56;2.11;.34;1.31;2.8;.8;3.38;438 +2;11.82;1.72;1.88;19.5;86;2.5;1.64;.37;1.42;2.06;.94;2.44;415 +2;12.51;1.73;1.98;20.5;85;2.2;1.92;.32;1.48;2.94;1.04;3.57;672 +2;12.42;2.55;2.27;22;90;1.68;1.84;.66;1.42;2.7;.86;3.3;315 +2;12.25;1.73;2.12;19;80;1.65;2.03;.37;1.63;3.4;1;3.17;510 +2;12.72;1.75;2.28;22.5;84;1.38;1.76;.48;1.63;3.3;.88;2.42;488 +2;12.22;1.29;1.94;19;92;2.36;2.04;.39;2.08;2.7;.86;3.02;312 +2;11.61;1.35;2.7;20;94;2.74;2.92;.29;2.49;2.65;.96;3.26;680 +2;11.46;3.74;1.82;19.5;107;3.18;2.58;.24;3.58;2.9;.75;2.81;562 +2;12.52;2.43;2.17;21;88;2.55;2.27;.26;1.22;2;.9;2.78;325 +2;11.76;2.68;2.92;20;103;1.75;2.03;.6;1.05;3.8;1.23;2.5;607 +2;11.41;.74;2.5;21;88;2.48;2.01;.42;1.44;3.08;1.1;2.31;434 +2;12.08;1.39;2.5;22.5;84;2.56;2.29;.43;1.04;2.9;.93;3.19;385 +2;11.03;1.51;2.2;21.5;85;2.46;2.17;.52;2.01;1.9;1.71;2.87;407 +2;11.82;1.47;1.99;20.8;86;1.98;1.6;.3;1.53;1.95;.95;3.33;495 +2;12.42;1.61;2.19;22.5;108;2;2.09;.34;1.61;2.06;1.06;2.96;345 +2;12.77;3.43;1.98;16;80;1.63;1.25;.43;.83;3.4;.7;2.12;372 +2;12;3.43;2;19;87;2;1.64;.37;1.87;1.28;.93;3.05;564 +2;11.45;2.4;2.42;20;96;2.9;2.79;.32;1.83;3.25;.8;3.39;625 +2;11.56;2.05;3.23;28.5;119;3.18;5.08;.47;1.87;6;.93;3.69;465 +2;12.42;4.43;2.73;26.5;102;2.2;2.13;.43;1.71;2.08;.92;3.12;365 +2;13.05;5.8;2.13;21.5;86;2.62;2.65;.3;2.01;2.6;.73;3.1;380 +2;11.87;4.31;2.39;21;82;2.86;3.03;.21;2.91;2.8;.75;3.64;380 +2;12.07;2.16;2.17;21;85;2.6;2.65;.37;1.35;2.76;.86;3.28;378 +2;12.43;1.53;2.29;21.5;86;2.74;3.15;.39;1.77;3.94;.69;2.84;352 +2;11.79;2.13;2.78;28.5;92;2.13;2.24;.58;1.76;3;.97;2.44;466 +2;12.37;1.63;2.3;24.5;88;2.22;2.45;.4;1.9;2.12;.89;2.78;342 +2;12.04;4.3;2.38;22;80;2.1;1.75;.42;1.35;2.6;.79;2.57;580 +3;12.86;1.35;2.32;18;122;1.51;1.25;.21;.94;4.1;.76;1.29;630 +3;12.88;2.99;2.4;20;104;1.3;1.22;.24;.83;5.4;.74;1.42;530 +3;12.81;2.31;2.4;24;98;1.15;1.09;.27;.83;5.7;.66;1.36;560 +3;12.7;3.55;2.36;21.5;106;1.7;1.2;.17;.84;5;.78;1.29;600 +3;12.51;1.24;2.25;17.5;85;2;.58;.6;1.25;5.45;.75;1.51;650 +3;12.6;2.46;2.2;18.5;94;1.62;.66;.63;.94;7.1;.73;1.58;695 +3;12.25;4.72;2.54;21;89;1.38;.47;.53;.8;3.85;.75;1.27;720 +3;12.53;5.51;2.64;25;96;1.79;.6;.63;1.1;5;.82;1.69;515 +3;13.49;3.59;2.19;19.5;88;1.62;.48;.58;.88;5.7;.81;1.82;580 +3;12.84;2.96;2.61;24;101;2.32;.6;.53;.81;4.92;.89;2.15;590 +3;12.93;2.81;2.7;21;96;1.54;.5;.53;.75;4.6;.77;2.31;600 +3;13.36;2.56;2.35;20;89;1.4;.5;.37;.64;5.6;.7;2.47;780 +3;13.52;3.17;2.72;23.5;97;1.55;.52;.5;.55;4.35;.89;2.06;520 +3;13.62;4.95;2.35;20;92;2;.8;.47;1.02;4.4;.91;2.05;550 +3;12.25;3.88;2.2;18.5;112;1.38;.78;.29;1.14;8.21;.65;2;855 +3;13.16;3.57;2.15;21;102;1.5;.55;.43;1.3;4;.6;1.68;830 +3;13.88;5.04;2.23;20;80;.98;.34;.4;.68;4.9;.58;1.33;415 +3;12.87;4.61;2.48;21.5;86;1.7;.65;.47;.86;7.65;.54;1.86;625 +3;13.32;3.24;2.38;21.5;92;1.93;.76;.45;1.25;8.42;.55;1.62;650 +3;13.08;3.9;2.36;21.5;113;1.41;1.39;.34;1.14;9.40;.57;1.33;550 +3;13.5;3.12;2.62;24;123;1.4;1.57;.22;1.25;8.60;.59;1.3;500 +3;12.79;2.67;2.48;22;112;1.48;1.36;.24;1.26;10.8;.48;1.47;480 +3;13.11;1.9;2.75;25.5;116;2.2;1.28;.26;1.56;7.1;.61;1.33;425 +3;13.23;3.3;2.28;18.5;98;1.8;.83;.61;1.87;10.52;.56;1.51;675 +3;12.58;1.29;2.1;20;103;1.48;.58;.53;1.4;7.6;.58;1.55;640 +3;13.17;5.19;2.32;22;93;1.74;.63;.61;1.55;7.9;.6;1.48;725 +3;13.84;4.12;2.38;19.5;89;1.8;.83;.48;1.56;9.01;.57;1.64;480 +3;12.45;3.03;2.64;27;97;1.9;.58;.63;1.14;7.5;.67;1.73;880 +3;14.34;1.68;2.7;25;98;2.8;1.31;.53;2.7;13;.57;1.96;660 +3;13.48;1.67;2.64;22.5;89;2.6;1.1;.52;2.29;11.75;.57;1.78;620 +3;12.36;3.83;2.38;21;88;2.3;.92;.5;1.04;7.65;.56;1.58;520 +3;13.69;3.26;2.54;20;107;1.83;.56;.5;.8;5.88;.96;1.82;680 +3;12.85;3.27;2.58;22;106;1.65;.6;.6;.96;5.58;.87;2.11;570 +3;12.96;3.45;2.35;18.5;106;1.39;.7;.4;.94;5.28;.68;1.75;675 +3;13.78;2.76;2.3;22;90;1.35;.68;.41;1.03;9.58;.7;1.68;615 +3;13.73;4.36;2.26;22.5;88;1.28;.47;.52;1.15;6.62;.78;1.75;520 +3;13.45;3.7;2.6;23;111;1.7;.92;.43;1.46;10.68;.85;1.56;695 +3;12.82;3.37;2.3;19.5;88;1.48;.66;.4;.97;10.26;.72;1.75;685 +3;13.58;2.58;2.69;24.5;105;1.55;.84;.39;1.54;8.66;.74;1.8;750 +3;13.4;4.6;2.86;25;112;1.98;.96;.27;1.11;8.5;.67;1.92;630 +3;12.2;3.03;2.32;19;96;1.25;.49;.4;.73;5.5;.66;1.83;510 +3;12.77;2.39;2.28;19.5;86;1.39;.51;.48;.64;9.899999;.57;1.63;470 +3;14.16;2.51;2.48;20;91;1.68;.7;.44;1.24;9.7;.62;1.71;660 +3;13.71;5.65;2.45;20.5;95;1.68;.61;.52;1.06;7.7;.64;1.74;740 +3;13.4;3.91;2.48;23;102;1.8;.75;.43;1.41;7.3;.7;1.56;750 +3;13.27;4.28;2.26;20;120;1.59;.69;.43;1.35;10.2;.59;1.56;835 +3;13.17;2.59;2.37;20;120;1.65;.68;.53;1.46;9.3;.6;1.62;840 +3;14.13;4.1;2.74;24.5;96;2.05;.76;.56;1.35;9.2;.61;1.6;560 \ No newline at end of file diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift new file mode 100644 index 000000000..3af8102c7 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift @@ -0,0 +1,196 @@ +// +// NaiveBayes.swift +// NaiveBayes +// +// Created by Philipp Gabriel on 14.04.17. +// Copyright © 2017 ph1ps. All rights reserved. +// + +import Foundation + +extension String: Error {} + +extension Array where Element == Double { + + func mean() -> Double { + return self.reduce(0, +) / Double(count) + } + + func standardDeviation() -> Double { + let calculatedMean = mean() + + let sum = self.reduce(0.0) { (previous, next) in + return previous + pow(next - calculatedMean, 2) + } + + return sqrt(sum / Double(count - 1)) + } +} + +extension Array where Element == Int { + + func uniques() -> Set { + return Set(self) + } + +} + +public enum NBType { + + case gaussian + case multinomial + //case bernoulli --> TODO + + func calcLikelihood(variables: [Any], input: Any) -> Double? { + + if case .gaussian = self { + + guard let input = input as? Double else { + return nil + } + + guard let mean = variables[0] as? Double else { + return nil + } + + guard let stDev = variables[1] as? Double else { + return nil + } + + let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) + let distribution = eulerPart / sqrt(2 * .pi) / stDev + + return distribution + + } else if case .multinomial = self { + + guard let variables = variables as? [(category: Int, probability: Double)] else { + return nil + } + + guard let input = input as? Int else { + return nil + } + + return variables.first { variable in + return variable.category == input + }?.probability + + } + + return nil + } + + func train(values: [Any]) -> [Any]? { + + if case .gaussian = self { + + guard let values = values as? [Double] else { + return nil + } + + return [values.mean(), values.standardDeviation()] + + } else if case .multinomial = self { + + guard let values = values as? [Int] else { + return nil + } + + let count = values.count + let categoryProba = values.uniques().map { value -> (Int, Double) in + return (value, Double(values.filter { $0 == value }.count) / Double(count)) + } + return categoryProba + } + + return nil + } +} + +public class NaiveBayes { + + var variables: [Int: [(feature: Int, variables: [Any])]] + var type: NBType + + var data: [[T]] + var classes: [Int] + + public init(type: NBType, data: [[T]], classes: [Int]) throws { + self.type = type + self.data = data + self.classes = classes + self.variables = [Int: [(Int, [Any])]]() + + if case .gaussian = type, T.self != Double.self { + throw "When using Gaussian NB you have to have continuous features (Double)" + } else if case .multinomial = type, T.self != Int.self { + throw "When using Multinomial NB you have to have categorical features (Int)" + } + } + + public func train() throws -> Self { + + for `class` in classes.uniques() { + variables[`class`] = [(Int, [Any])]() + + let classDependent = data.enumerated().filter { (offset, _) in + return classes[offset] == `class` + } + + for feature in 0.. Int { + let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in + return first.1 < second.1 + } + + guard let `class` = likelihoods?.0 else { + return -1 + } + + return `class` + } + + public func classifyProba(with input: [T]) -> [(Int, Double)] { + + var probaClass = [Int: Double]() + let amount = classes.count + + classes.forEach { `class` in + let individual = classes.filter { $0 == `class` }.count + probaClass[`class`] = Double(individual) / Double(amount) + } + + let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in + let distribution = value.map { (feature, variables) -> Double in + return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 + } + return (`class`, distribution) + } + + let likelihoods = classesAndFeatures.map { (`class`, distribution) in + return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) + } + + let sum = likelihoods.map { $0.1 }.reduce(0, +) + let normalized = likelihoods.map { (`class`, likelihood) in + return (`class`, likelihood / sum) + } + + return normalized + } +} diff --git a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground new file mode 100644 index 000000000..b1148fc50 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata b/Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift index dbbf3cd9f..9b9ace86d 100644 --- a/Naive Bayes Classifier/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -8,6 +8,8 @@ import Foundation +extension String: Error {} + extension Array where Element == Double { func mean() -> Double { @@ -35,29 +37,9 @@ extension Array where Element == Int { enum NBType { - case gaussian(data: [[Double]], classes: [Int]) - case multinomial(data: [[Int]], classes: [Int]) - //case bernoulli(data: [[Bool]], classes: [Int]) --> TODO - - var classes: [Int] { - if case .gaussian(_, let classes) = self { - return classes - } else if case .multinomial(_, let classes) = self { - return classes - } - - return [] - } - - var data: [[Any]] { - if case .gaussian(let data, _) = self { - return data - } else if case .multinomial(let data, _) = self { - return data - } - - return [] - } + case gaussian + case multinomial + //case bernoulli --> TODO func calcLikelihood(variables: [Any], input: Any) -> Double? { @@ -86,12 +68,12 @@ enum NBType { return nil } - guard let input = input as? Double else { + guard let input = input as? Int else { return nil } return variables.first { variable in - return variable.category == Int(input) + return variable.category == input }?.probability } @@ -126,49 +108,52 @@ enum NBType { } } -class NaiveBayes { +class NaiveBayes { - private var variables: [Int: [(feature: Int, variables: [Any])]] - private var type: NBType + var variables: [Int: [(feature: Int, variables: [Any])]] + var type: NBType - init(type: NBType) { + var data: [[T]] + var classes: [Int] + + init(type: NBType, data: [[T]], classes: [Int]) throws { self.type = type + self.data = data + self.classes = classes self.variables = [Int: [(Int, [Any])]]() - } - - static func convert(dataAndClasses: [[T]], rowOfClasses: Int) -> (data: [[T]], classes: [Int]) { - let classes = dataAndClasses.map { Int($0[rowOfClasses] as! Double) } //TODO - let data = dataAndClasses.map { row in - return row.enumerated().filter { $0.offset != rowOfClasses }.map { $0.element } + if case .gaussian = type, T.self != Double.self { + throw "When using Gaussian NB you have to have continuous features (Double)" + } else if case .multinomial = type, T.self != Int.self { + throw "When using Multinomial NB you have to have categorical features (Int)" } - - return (data, classes) } - //TODO remake pliss, i dont like this at all - func train() { - - var classes = type.classes + func train() throws -> Self { for `class` in classes.uniques() { - variables[`class`] = [(Int, [Any])]() - for feature in 0.. Int { + func classify(with input: [T]) -> Int { let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } @@ -180,10 +165,8 @@ class NaiveBayes { return `class` } - //TODO fix this doesnt have to be a double - func classifyProba(with input: [Double]) -> [(Int, Double)] { + func classifyProba(with input: [T]) -> [(Int, Double)] { - let classes = type.classes var probaClass = [Int: Double]() let amount = classes.count @@ -200,7 +183,7 @@ class NaiveBayes { } let likelihoods = classesAndFeatures.map { (`class`, distribution) in - return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 1.0)) + return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) } let sum = likelihoods.map { $0.1 }.reduce(0, +) @@ -211,40 +194,3 @@ class NaiveBayes { return normalized } } - -guard let csv = try? String(contentsOfFile: "/Users/ph1ps/Desktop/wine.csv") else { - print("file not found") - exit(0) -} - -let rows = csv.characters.split(separator: "\r\n").map { String($0) } -let wineData = rows.map { row -> [Double] in - let split = row.characters.split(separator: ";") - return split.map { Double(String($0))! } -} - -let convertedWine = NaiveBayes.convert(dataAndClasses: wineData, rowOfClasses: 0) -let wineNaive = NaiveBayes(type: .gaussian(data: convertedWine.data, classes: convertedWine.classes)) -wineNaive.train() -print(wineNaive.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015])) - -let golfData = [ - [0, 0, 0, 0], - [0, 0, 0, 1], - [1, 0, 0, 0], - [2, 1, 0, 0], - [2, 2, 1, 0], - [2, 2, 1, 1], - [1, 2, 1, 1], - [0, 1, 0, 0], - [0, 2, 1, 0], - [2, 1, 1, 0], - [0, 1, 1, 1], - [1, 1, 0, 1], - [1, 0, 1, 0], - [2, 1, 0, 1] -] -let golfClasses = [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0] -let golfNaive = NaiveBayes(type: .multinomial(data: golfData, classes: golfClasses)) -golfNaive.train() -print(golfNaive.classifyProba(with: [0, 2, 0, 1])) From 8ac88ae7fe6134885956502bd9551e7b6cd0a083 Mon Sep 17 00:00:00 2001 From: ph1ps Date: Mon, 17 Apr 2017 21:29:43 +0200 Subject: [PATCH 0306/1039] Change macOS playground to iOS --- .../NaiveBayes.playground/Contents.swift | 51 +++++++++++++++++-- .../contents.xcplayground | 2 +- .../NaiveBayes.playground/timeline.xctimeline | 21 ++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift index cb820272e..321e7a04a 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift +++ b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift @@ -7,7 +7,7 @@ import Foundation ### Gaussian Naive Bayes - Note: - When using Gaussian NB you have to have continuous features (Double). + When using Gaussian NB you have to have continuous features (Double). For this example we are going to use a famous dataset with different types of wine. The labels of the features can be viewed [here](https://gist.github.com/tijptjik/9408623) */ @@ -52,9 +52,54 @@ let data = wineData.map { row in */ let wineBayes = try! NaiveBayes(type: .gaussian, data: data, classes: classes).train() let result = wineBayes.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015]) -print(result) /*: - I can assure you that this is the correct result and as you can see the classifier thinks that its ***99.99%*** correct too. + I can assure you that ***class 1*** is the correct result and as you can see the classifier thinks that its ***99.99%*** likely too. ### Multinomial Naive Bayes + + - Note: + When using Multinomial NB you have to have categorical features (Int). + + Now this dataset is commonly used to describe the classification problem and it is categorical which means you don't have real values you just have categorical data as stated before. The structure of this dataset is as follows. + + Outlook,Temperature,Humidity,Windy + + ***Outlook***: 0 = rainy, 1 = overcast, 2 = sunny + + ***Temperature***: 0 = hot, 1 = mild, 2 = cool + + ***Humidity***: 0 = high, 1 = normal + + ***Windy***: 0 = false, 1 = true + + The classes are either he will play golf or not depending on the weather conditions. (0 = won't play, 1 = will play) + */ + +let golfData = [ + [0, 0, 0, 0], + [0, 0, 0, 1], + [1, 0, 0, 0], + [2, 1, 0, 0], + [2, 2, 1, 0], + [2, 2, 1, 1], + [1, 2, 1, 1], + [0, 1, 0, 0], + [0, 2, 1, 0], + [2, 1, 1, 0], + [0, 1, 1, 1], + [1, 1, 0, 1], + [1, 0, 1, 0], + [2, 1, 0, 1] +] +let golfClasses = [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0] + +let golfNaive = try! NaiveBayes(type: .multinomial, data: golfData, classes: golfClasses).train() + +/*: + The weather conditions is as follows now: Outlook=rainy, Temperature=cool, Humidity=high, Windy=true + */ +let golfResult = golfNaive.classifyProba(with: [0, 2, 0, 1]) + +/*: + Naive Bayes tells us that the golf player will ***not*** play with a likelihood of almost ***80%***. Which is true of course. */ diff --git a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground index b1148fc50..35968656f 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground +++ b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline b/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline new file mode 100644 index 000000000..b15fdda55 --- /dev/null +++ b/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline @@ -0,0 +1,21 @@ + + + + + + + + + + + From d9e36fa2800c2c67e07df17048424903ab5a7eb6 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 18 Apr 2017 13:43:41 +0200 Subject: [PATCH 0307/1039] Missing word --- Huffman Coding/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 69e105c87..7058096d0 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -1,6 +1,6 @@ # Huffman Coding -The idea: To encode objects that occur with a smaller number of bits than objects that occur less frequently. +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: From 6c7e9de65cb84da86bb0a5de554f5d13fa6412e6 Mon Sep 17 00:00:00 2001 From: Matthijs Hollemans Date: Tue, 18 Apr 2017 13:45:16 +0200 Subject: [PATCH 0308/1039] Fix alignment --- Huffman Coding/README.markdown | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Huffman Coding/README.markdown b/Huffman Coding/README.markdown index 7058096d0..d1181d215 100644 --- a/Huffman Coding/README.markdown +++ b/Huffman Coding/README.markdown @@ -9,13 +9,13 @@ Although any type of objects can be encoded with this scheme, it is common to co 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 + 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: @@ -23,10 +23,10 @@ We can assign bit strings to each of these bytes. The more common a byte is, the 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 + 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: From 9fafc9278d72240fda1117d010b1544ff106dccb Mon Sep 17 00:00:00 2001 From: ph1ps Date: Tue, 18 Apr 2017 13:47:17 +0200 Subject: [PATCH 0309/1039] Add README with explanation --- .../NaiveBayes.playground/Contents.swift | 28 ++--- .../Sources/NaiveBayes.swift | 100 +++++++++--------- .../contents.xcplayground | 2 +- .../NaiveBayes.playground/timeline.xctimeline | 10 ++ Naive Bayes Classifier/NaiveBayes.swift | 100 +++++++++--------- Naive Bayes Classifier/README.md | 99 +++++++++++++++++ Naive Bayes Classifier/images/bayes.gif | Bin 0 -> 1095 bytes .../images/code_example.png | Bin 0 -> 122044 bytes Naive Bayes Classifier/images/mean.gif | Bin 0 -> 590 bytes Naive Bayes Classifier/images/multinomial.gif | Bin 0 -> 703 bytes .../images/normal_distribution.gif | Bin 0 -> 925 bytes .../images/standard_deviation.gif | Bin 0 -> 1125 bytes .../images/tennis_dataset.png | Bin 0 -> 61477 bytes 13 files changed, 224 insertions(+), 115 deletions(-) create mode 100644 Naive Bayes Classifier/images/bayes.gif create mode 100644 Naive Bayes Classifier/images/code_example.png create mode 100644 Naive Bayes Classifier/images/mean.gif create mode 100644 Naive Bayes Classifier/images/multinomial.gif create mode 100644 Naive Bayes Classifier/images/normal_distribution.gif create mode 100644 Naive Bayes Classifier/images/standard_deviation.gif create mode 100644 Naive Bayes Classifier/images/tennis_dataset.png diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift index 321e7a04a..66aefaa32 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift +++ b/Naive Bayes Classifier/NaiveBayes.playground/Contents.swift @@ -2,13 +2,13 @@ import Foundation /*: ## Naive Bayes Classifier - + This playground uses the given algorithm and utilizes its features with some example datasets - + ### Gaussian Naive Bayes - Note: When using Gaussian NB you have to have continuous features (Double). - + For this example we are going to use a famous dataset with different types of wine. The labels of the features can be viewed [here](https://gist.github.com/tijptjik/9408623) */ guard let wineCSV = Bundle.main.path(forResource: "wine", ofType: "csv") else { @@ -27,7 +27,7 @@ guard let csv = try? String(contentsOfFile: wineCSV) else { let rows = csv.characters.split(separator: "\r\n").map { String($0) } /*: Splitting on the ; sign and converting the value to a Double - + - Important: Do not force unwrap the mapped values in your real application. Carefully convert them! This is just for the sake of showing how the algorithm works. */ @@ -47,31 +47,31 @@ let data = wineData.map { row in /*: Again use `guard` on the result of a `try?` or simply `do-try-catch` because this would crash your application if an error occured. - + The array in the `classifyProba` method I passed is a former entry in the .csv file which I removed in order to classify it. */ let wineBayes = try! NaiveBayes(type: .gaussian, data: data, classes: classes).train() let result = wineBayes.classifyProba(with: [12.85, 1.6, 2.52, 17.8, 95, 2.48, 2.37, 0.26, 1.46, 3.93, 1.09, 3.63, 1015]) /*: I can assure you that ***class 1*** is the correct result and as you can see the classifier thinks that its ***99.99%*** likely too. - + ### Multinomial Naive Bayes - + - Note: When using Multinomial NB you have to have categorical features (Int). - + Now this dataset is commonly used to describe the classification problem and it is categorical which means you don't have real values you just have categorical data as stated before. The structure of this dataset is as follows. - + Outlook,Temperature,Humidity,Windy - + ***Outlook***: 0 = rainy, 1 = overcast, 2 = sunny - + ***Temperature***: 0 = hot, 1 = mild, 2 = cool - + ***Humidity***: 0 = high, 1 = normal - + ***Windy***: 0 = false, 1 = true - + The classes are either he will play golf or not depending on the weather conditions. (0 = won't play, 1 = will play) */ diff --git a/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift index 3af8102c7..6e6d7b4c0 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.playground/Sources/NaiveBayes.swift @@ -11,186 +11,186 @@ import Foundation extension String: Error {} extension Array where Element == Double { - + func mean() -> Double { return self.reduce(0, +) / Double(count) } - + func standardDeviation() -> Double { let calculatedMean = mean() - + let sum = self.reduce(0.0) { (previous, next) in return previous + pow(next - calculatedMean, 2) } - + return sqrt(sum / Double(count - 1)) } } extension Array where Element == Int { - + func uniques() -> Set { return Set(self) } - + } public enum NBType { - + case gaussian case multinomial //case bernoulli --> TODO - + func calcLikelihood(variables: [Any], input: Any) -> Double? { - + if case .gaussian = self { - + guard let input = input as? Double else { return nil } - + guard let mean = variables[0] as? Double else { return nil } - + guard let stDev = variables[1] as? Double else { return nil } - + let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) let distribution = eulerPart / sqrt(2 * .pi) / stDev - + return distribution - + } else if case .multinomial = self { - + guard let variables = variables as? [(category: Int, probability: Double)] else { return nil } - + guard let input = input as? Int else { return nil } - + return variables.first { variable in return variable.category == input }?.probability - + } - + return nil } - + func train(values: [Any]) -> [Any]? { - + if case .gaussian = self { - + guard let values = values as? [Double] else { return nil } - + return [values.mean(), values.standardDeviation()] - + } else if case .multinomial = self { - + guard let values = values as? [Int] else { return nil } - + let count = values.count let categoryProba = values.uniques().map { value -> (Int, Double) in return (value, Double(values.filter { $0 == value }.count) / Double(count)) } return categoryProba } - + return nil } } public class NaiveBayes { - + var variables: [Int: [(feature: Int, variables: [Any])]] var type: NBType - + var data: [[T]] var classes: [Int] - + public init(type: NBType, data: [[T]], classes: [Int]) throws { self.type = type self.data = data self.classes = classes self.variables = [Int: [(Int, [Any])]]() - + if case .gaussian = type, T.self != Double.self { throw "When using Gaussian NB you have to have continuous features (Double)" } else if case .multinomial = type, T.self != Int.self { throw "When using Multinomial NB you have to have categorical features (Int)" } } - + public func train() throws -> Self { - + for `class` in classes.uniques() { variables[`class`] = [(Int, [Any])]() - + let classDependent = data.enumerated().filter { (offset, _) in return classes[offset] == `class` } - + for feature in 0.. Int { let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } - + guard let `class` = likelihoods?.0 else { return -1 } - + return `class` } - + public func classifyProba(with input: [T]) -> [(Int, Double)] { - + var probaClass = [Int: Double]() let amount = classes.count - + classes.forEach { `class` in let individual = classes.filter { $0 == `class` }.count probaClass[`class`] = Double(individual) / Double(amount) } - + let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in let distribution = value.map { (feature, variables) -> Double in return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 } return (`class`, distribution) } - + let likelihoods = classesAndFeatures.map { (`class`, distribution) in return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) } - + let sum = likelihoods.map { $0.1 }.reduce(0, +) let normalized = likelihoods.map { (`class`, likelihood) in return (`class`, likelihood / sum) } - + return normalized } } diff --git a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground index 35968656f..89da2d470 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground +++ b/Naive Bayes Classifier/NaiveBayes.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline b/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline index b15fdda55..7bc414f58 100644 --- a/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline +++ b/Naive Bayes Classifier/NaiveBayes.playground/timeline.xctimeline @@ -17,5 +17,15 @@ selectedRepresentationIndex = "0" shouldTrackSuperviewWidth = "NO"> + + + + diff --git a/Naive Bayes Classifier/NaiveBayes.swift b/Naive Bayes Classifier/NaiveBayes.swift index 9b9ace86d..46a0bb4f5 100644 --- a/Naive Bayes Classifier/NaiveBayes.swift +++ b/Naive Bayes Classifier/NaiveBayes.swift @@ -11,186 +11,186 @@ import Foundation extension String: Error {} extension Array where Element == Double { - + func mean() -> Double { return self.reduce(0, +) / Double(count) } - + func standardDeviation() -> Double { let calculatedMean = mean() - + let sum = self.reduce(0.0) { (previous, next) in return previous + pow(next - calculatedMean, 2) } - + return sqrt(sum / Double(count - 1)) } } extension Array where Element == Int { - + func uniques() -> Set { return Set(self) } - + } enum NBType { - + case gaussian case multinomial //case bernoulli --> TODO - + func calcLikelihood(variables: [Any], input: Any) -> Double? { - + if case .gaussian = self { - + guard let input = input as? Double else { return nil } - + guard let mean = variables[0] as? Double else { return nil } - + guard let stDev = variables[1] as? Double else { return nil } - + let eulerPart = pow(M_E, -1 * pow(input - mean, 2) / (2 * pow(stDev, 2))) let distribution = eulerPart / sqrt(2 * .pi) / stDev - + return distribution - + } else if case .multinomial = self { - + guard let variables = variables as? [(category: Int, probability: Double)] else { return nil } - + guard let input = input as? Int else { return nil } - + return variables.first { variable in return variable.category == input }?.probability - + } - + return nil } - + func train(values: [Any]) -> [Any]? { - + if case .gaussian = self { - + guard let values = values as? [Double] else { return nil } - + return [values.mean(), values.standardDeviation()] - + } else if case .multinomial = self { - + guard let values = values as? [Int] else { return nil } - + let count = values.count let categoryProba = values.uniques().map { value -> (Int, Double) in return (value, Double(values.filter { $0 == value }.count) / Double(count)) } return categoryProba } - + return nil } } class NaiveBayes { - + var variables: [Int: [(feature: Int, variables: [Any])]] var type: NBType - + var data: [[T]] var classes: [Int] - + init(type: NBType, data: [[T]], classes: [Int]) throws { self.type = type self.data = data self.classes = classes self.variables = [Int: [(Int, [Any])]]() - + if case .gaussian = type, T.self != Double.self { throw "When using Gaussian NB you have to have continuous features (Double)" } else if case .multinomial = type, T.self != Int.self { throw "When using Multinomial NB you have to have categorical features (Int)" } } - + func train() throws -> Self { - + for `class` in classes.uniques() { variables[`class`] = [(Int, [Any])]() - + let classDependent = data.enumerated().filter { (offset, _) in return classes[offset] == `class` } - + for feature in 0.. Int { let likelihoods = classifyProba(with: input).max { (first, second) -> Bool in return first.1 < second.1 } - + guard let `class` = likelihoods?.0 else { return -1 } - + return `class` } - + func classifyProba(with input: [T]) -> [(Int, Double)] { - + var probaClass = [Int: Double]() let amount = classes.count - + classes.forEach { `class` in let individual = classes.filter { $0 == `class` }.count probaClass[`class`] = Double(individual) / Double(amount) } - + let classesAndFeatures = variables.map { (`class`, value) -> (Int, [Double]) in let distribution = value.map { (feature, variables) -> Double in return type.calcLikelihood(variables: variables, input: input[feature]) ?? 0.0 } return (`class`, distribution) } - + let likelihoods = classesAndFeatures.map { (`class`, distribution) in return (`class`, distribution.reduce(1, *) * (probaClass[`class`] ?? 0.0)) } - + let sum = likelihoods.map { $0.1 }.reduce(0, +) let normalized = likelihoods.map { (`class`, likelihood) in return (`class`, likelihood / sum) } - + return normalized } } diff --git a/Naive Bayes Classifier/README.md b/Naive Bayes Classifier/README.md index e69de29bb..9c0f0082a 100644 --- a/Naive Bayes Classifier/README.md +++ b/Naive Bayes Classifier/README.md @@ -0,0 +1,99 @@ +# Naive Bayes Classifier + +> ***Disclaimer:*** Do not get scared of complicated formulas or terms, I will describe them right after I use them. Also the math skills you need to understand this are very basic. + +The goal of a classifier is to predict the class of a given data entry based on previously fed data and its features. + +Now what is a class or a feature? The best I can do is to describe it with a table. +This is a dataset that uses height, weight and foot size of a person to illustrate the relationship between those values and the sex. + +| Sex | height (feet) | weight(lbs) | foot size (inches) | +| ------------- |:-------------:|:-----:|:---:| +| male | 6 | 180 | 12 | +| male | 5.92 | 190 | 11 | +| male | 5.58 | 170 | 12 | +| male | 5.92 | 165 | 10 | +| female | 5 | 100 | 6 | +| female | 5.5 | 150 | 8 | +| female | 5.42 | 130 | 7 | +| female | 5.75 | 150 | 9 | + +The ***classes*** of this table is the data in the sex column (male/female). You "classify" the rest of the data and bind them to a sex. + +The ***features*** of this table are the labels of the other columns (height, weight, foot size) and the numbers right under the labels. + +Now that I've told you what a classifier is I will tell you what exactly a ***Naive Bayes classifier*** is. There are a lot of other classifiers out there but what's so special about this specific is that it only needs a very small dataset to get good results. The others like Random Forests normally need a very large dataset. + +Why isn't this algorithm used more you might ask (or not). Because it is normally ***outperformed*** in accuracy by ***Random Forests*** or ***Boosted Trees***. + +## Theory + +The Naive Bayes classifier utilizes the ***Bayes Theorem*** (as its name suggests) which looks like this. + +![](images/bayes.gif) + +***P*** always means the probability of something. + +***A*** is the class, ***B*** is the data depending on a feature and the ***pipe*** symbol means given. + +P(A | B) therefore is: probability of the class given the data (which is dependent on the feature). + +This is all you have to know about the Bayes Theorem. The important thing for us is now how to calculate all those variables, plug them into this formula and you are ready to classify data. + +### **P(A)** +This is the probability of the class. To get back to the example I gave before: Let's say we want to classify this data entry: + +| height (feet) | weight(lbs) | foot size (inches) | +|:-------------:|:-----:|:---:| +| 6 | 130 | 8 | + +What Naive Bayes classifier now does: it checks the probability for every class possible which is in our case either male or female. Look back at the original table and count the male and the female entries. Then divide them by the overall count of data entries. + +P(male) = 4 / 8 = 0.5 + +P(female) = 4 / 8 = 0.5 + +This should be a very easy task to do. Basically just the probability of all classes. + +### **P(B)** +This variable is not needed in a Naive Bayes classifier. It is the probability of the data. It does not change, therefore it is a constant. And what can you do with a constant? Exactly! Discard it. This saves time and code. + +### **P(B | A)** +This is the probability of the data given the class. To calculate this I have to introduce you to the subtypes of NB. You have to decide which you use depending on your data which you want to classify. + +### **Gaussian Naive Bayes** +If you have a dataset like the one I showed you before (continuous features -> `Double`s) you have to use this subtype. There are 3 formulas you need for Gaussian NB to calculate P(B | A). + +![mean](images/mean.gif) + +![standard deviation](images/standard_deviation.gif) + +![normal distribution](images/normal_distribution.gif) + +and **P(x | y) = P(B | A)** + +Again, very complicated looking formulas but they are very easy. The first formula with µ is just the mean of the data (adding all data points and dividing them by the count). The second with σ is the standard deviation. You might have heard of it somewhen in school. It is just the sum of all values minus the mean, squared and that divided by the count of the data minus 1 and a sqaure root around it. The third equation is the Gaussian or normal distribution if you want to read more about it I suggest reading [this](https://en.wikipedia.org/wiki/Normal_distribution). + +Why the Gaussian distribution? Because we assume that the continuous values associated with each class are distributed according to the Gaussian distribution. Simple as that. + +### **Multinomial Naive Bayes** + +What do we do if we have this for examples: + +![tennis or golf](images/tennis_dataset.png) + +We can't just calculate the mean of sunny, overcast and rainy. This is why we need the categorical model which is the multinomial NB. This is the last formula, I promise! + +![multinomial](images/multinomial.gif) + +Now this is the number of times feature **i** appears in a sample **N** of class **y** in the data set divided by the count of the sample just depending on the class **y**. That θ is also just a fancy way of writing P(B | A). + +You might have noticed that there is still the α in this formula. This solves a problem called "zero-frequency-problem". Because what happens if there is no sample with feature **i** and class **y**? The whole equation would result in 0 (because 0 / something is always 0). This is a huge problem but there is a simple solution to this. Just add 1 to any count of the sample (α = 1). + +## Those formulas in action + +Enough talking! This is the code. If you want a deeper explanation of how the code works just look at the Playground I provided. + +![code example](images/code_example.png) + +*Written for Swift Algorithm Club by Philipp Gabriel* \ No newline at end of file diff --git a/Naive Bayes Classifier/images/bayes.gif b/Naive Bayes Classifier/images/bayes.gif new file mode 100644 index 0000000000000000000000000000000000000000..363ff3425836342c4e354a74454b4828c1fab6d3 GIT binary patch literal 1095 zcmV-N1i1T0Nk%w1Vb1_70OJ4v|Ns90004G&b|NAoW@ctYL`2NY%v4lVy1KgD+}xO$ znC|ZGh=_;~5D+plGODVoA^8LW00000EC2ui0M7s`000F35XecZy*TU5yI+boEg}$> z=mm;r>b`KC5oB4E3n8PlnD4+KOfU!tj)a1N!a!JvMr5IN(-54KM=J(B3X;o7b91F= zh3GV=aG)RpiHQSK&`lD7hop*mZvk^aY;JIJ8-5jmYKx2j0b2_J3=(G-c@;)`8VZsX z41X_=6p@nvl^L9+VxWz!FmG`a1_4+Fu@$p5l!X9%79j(6vc4Ar9IzC#wYL|*!V(6= zuG1+34HX26*B14m3J zr&6dow5$Yn85Xz%Ab=QCO%+xGKt^HhHvn@6oh{f}N{a#~oxTwKL7l82;k1`DtadXy zH#FNEdWZmy;fERl4mzfGy#;vys9z2UZz>_dfdCOHT_2!|!SYcVoEP{mK|u@a*mXVF z-hFu&DMmxifc>P1mn2(G30**(P6}_0@cvg%27^p67=RWaLY->Q;2{@+8VSHv2mNVf z+Hn&ea-k?AbYjYd<#`AfCY@!nN@34H&HgXjZ=;<(sbh*I2MFv7(!Rh^AJAzXi(8b3sPW@KMcL-NS0`( zDM3dd$+uHaas5PrG?R%z)?r0jG}E4ZCZy({L2Q+QS4TnDmROJ(h$sMWjg@C80Yob4 zq?A@_>7|%vs_CYjcG~F#XccFdV2=^g7Hg_B3FxZyAhrQ#l9faZV-z@cBLH?0&}W}~ zvFfW2zR_``Y^<&1OC&nIX2FlY_cptTc;uOI-gViT!rq9^L8t3$tbi!2 zXaR)ZrogReW~wP+xh@c!Zg}>=#{_0<)%(R1S%jNqyZ)gNWsL0Z8nS-t9B!@uGKiq*>E?O+<2Qbmz=iJ73p2veB)qlB7Fz$!MjWQE4bhQtC0BN Nhc~=Il0roQ06YAH(zpNs literal 0 HcmV?d00001 diff --git a/Naive Bayes Classifier/images/code_example.png b/Naive Bayes Classifier/images/code_example.png new file mode 100644 index 0000000000000000000000000000000000000000..a147ecdd6d5a9b542ac02cc1b778e279e183b229 GIT binary patch literal 122044 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%0AqlP%v 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 literal 0 HcmV?d00001 diff --git a/Naive Bayes Classifier/images/mean.gif b/Naive Bayes Classifier/images/mean.gif new file mode 100644 index 0000000000000000000000000000000000000000..7518c9995f8b5d2a33b4268aebfe9d8c9d90868f GIT binary patch literal 590 zcmV-U0hZ;sgm(P!LiW?r0MiU?!oEECS8T_EArNc1 zo1rg}gaRXCD4?~V0RsmPtT>=_swa&C3-P7X@Kx6@D%(%=F0vZiyQX43783hUy3kL~<76Sx%d?-p21_23@D-Q&n z1PThC1auS(k_rQC7F|7)DVhupY>-z)v~Z3VX*UyqycbY)u7wo?OcGWLKnj@v%D5T= z0Tm6T!#e_+2x=jT0Cx%A8ip7PzXsL9*EtUi3z{=dO#*=c4w@I_7YX+V1qcZU3 z)t+@Y9GGxGM;X2f2M!(?U?Lns9SI&3SRh5#uZ#W$Vn~>F5yzN2B`qu%lO|=01Pkz3 za|ytJxB@6?rU0W#X9EQc9V`&1vnUM)dtzm9gMpK%r!$Qr*)~BM!3tN61lY>8tJkk! z!-^eC_5(^zQq!(L5VH;gUbh_B5_!StQ%_OV?zlrhO0s3mp6N~dWq>0D-oOzZ%oxBI z0Q9arY@Al1y@m)T@8IBJj|dWeC|Ah1vEzV`WM0sf5RZioohM87_z{GLK7=r3f?UGp ziS1k$d6qnbMGKDG7rum%SU7WmzLd|TS#un?g*g)JAgf~_&6xv>)%pP>s5%^?iyGB* z+!nxqdV?!TxYSIA-A|$LS};Wcl`8BK2yWCEEV5`Jl3dVaunPsglrjh=0~T`(9?k%k zpdKXkVoggt#AF?8+HjLyVugG-fjO3>0|g=zVAoSo?Ytuc1&>8`AqM;u;156oL2*x2 l_hcp71eP&`LPSHlL>fm)iWXawjpbHAUQkLUoL&(C06Px_310vJ literal 0 HcmV?d00001 diff --git a/Naive Bayes Classifier/images/normal_distribution.gif b/Naive Bayes Classifier/images/normal_distribution.gif new file mode 100644 index 0000000000000000000000000000000000000000..b2f35e8ebf9e6e92c985176a946e5dbcce14a9a4 GIT binary patch literal 925 zcmV;O17iF~Nk%w1VZHz=0OJ4v|Ns90004G&b|NAoW@ctYL`2NY%v4lVy1KgD+}xO$ znC|ZGh=_;~5D+plGODVoA^8LW00000EC2ui0KNb!000F35XecZy*TU5yI+Ojjbzy= z4}q9$>%LYZD8UNfIAAb9GUUKuuqG^;5C@}j*&#AF29ax_pezWBr*;c)axFX<;vq>? zZQt||tp+d>I6|*67$n*L8VdqFVE_VId5brDYIh3@336Ev440QSC~jyB zQjDN1j%j@WRAg`&2XFU2JWK9g`LY zWI0$S1szwhgarW(0-tJ8BM;LP#T^0z0RrpViaR5+5j(@N*`MKMG*IC@GHu5)uxUGH}4F=|VUO z8jxuKZUVhxWF;IZdu8gdRAJi$Ro3oi#u+iHQiTMdd^!Wg{*0S{;`>};^EF_jGlOJ4?1 zRKPM*3LfGU;xk%8yr>CMw~xcD8@`o*J1UE0;e&8 znO*=|AV_QkJRpq#51^4iPlr(uRaCRVli?PM={68HGyE3e1;e3pk4zFUfFp@t98lqm zTzu2PW64O=7*ot3@SGM2;0Pos=-9HLDSZeq43&5g@Z*zPoa532f6SmEeoNF?AOr4H z#icCBDI=60iYT_?nsk0)<^Z1@kXoI528l)k$q0~QpM;jlBL#Yv;lMy%DWDEO))iW3 zHWe^1rzrtULjW8+JkZhsSb*T3qqNNyIqFNSL zrbU>OwAN`_a~N1+)Rbj-MZl=RP4YPaJsVb_xPtpKKss^Zlz!;@C zU_$`lq;|li+|t=VApJ2V5G1J;z=o*`c+xJd40N;azd2|WFTezspk~1rL;wIghTUnw literal 0 HcmV?d00001 diff --git a/Naive Bayes Classifier/images/standard_deviation.gif b/Naive Bayes Classifier/images/standard_deviation.gif new file mode 100644 index 0000000000000000000000000000000000000000..b917d9922e589300b796ba8cd32d2b6251d26089 GIT binary patch literal 1125 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
PPPq>4m!%z#o!=8IENk;buccYO#mSK|v> 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

D73NrvdrmS(1$?q|n9 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/image3.png b/Dijkstra Algorithm/Images/image3.png new file mode 100644 index 0000000000000000000000000000000000000000..493048ab7b37f907f7b1a89aeee868a543d00e91 GIT binary patch literal 65232 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�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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/image4.png b/Dijkstra Algorithm/Images/image4.png new file mode 100644 index 0000000000000000000000000000000000000000..9c47aaaaffabcd49f10fe5cda5aedf33431ce1a3 GIT binary patch literal 65286 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 )oiImBH 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 DI2Sh? literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/image5.png b/Dijkstra Algorithm/Images/image5.png new file mode 100644 index 0000000000000000000000000000000000000000..2494654449417fd46572395eafcdc21a10c1c812 GIT binary patch literal 66333 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/image7.png b/Dijkstra Algorithm/Images/image7.png new file mode 100644 index 0000000000000000000000000000000000000000..dd91cab0b84515792f0002c8c9fb360a78098357 GIT binary patch literal 66716 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 - ## Credits WWDC 2017 Scholarship Project Created by [Taras Nikulin](https://github.com/crabman448) From fb4c63bc92ac909159528e2e1c3f16d99eb9665a Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:32:05 +0300 Subject: [PATCH 0321/1039] Tables fix --- Dijkstra Algorithm/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 9a48bbeb3..132f4e5bd 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -12,6 +12,7 @@ When the algorithm starts to work initial graph looks like this: [image1.png] The table below will represent graph state + | | A | B | C | D | E | | ------------------------- | --- | --- | --- | --- | --- | | Visited | F | F | F | F | F | @@ -61,6 +62,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | [image4.jpg] + | | A | B | C | D | E | | ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | | Visited | T | F | F | T | F | @@ -68,6 +70,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | [image5.jpg] + | | A | B | C | D | E | | ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | | Visited | T | F | F | T | T | @@ -75,6 +78,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Vertices From Start | [A] | [A, B] |[A, D, E, C]| [A, D] | [A, D, E ] | [image6.jpg] + | | A | B | C | D | E | | ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | | Visited | T | T | F | T | T | @@ -82,6 +86,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | [image7.jpg] + | | A | B | C | D | E | | ------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- | | Visited | T | T | T | T | T | From cce96e2694e71e473f30817a535a97a6d59591f3 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:34:16 +0300 Subject: [PATCH 0322/1039] Updating --- Dijkstra Algorithm/README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 132f4e5bd..cb0683e5d 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -9,12 +9,12 @@ The best example is road network. If you wnat to find the shortest path from you I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. When the algorithm starts to work initial graph looks like this: -[image1.png] +[images/image1.png] The table below will represent 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 | [ ] | [ ] | [ ] | [ ] | [ ] | @@ -44,51 +44,51 @@ var checkingVertex = nonVisitedVertices.smallestPathLengthFromStartVertex() Then we set this vertex as visited | | 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] | [ ] | [ ] | [ ] | [ ] | checkingVertex.visited = true -[image2.jpg] +[images/image2.jpg] Then we check all of its neighbors. If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. -[image3.jpg] +[images/image3.jpg] | | 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] | [ ] | -[image4.jpg] +[images/image4.jpg] | | 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] | -[image5.jpg] +[images/image5.jpg] | | 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 ] | -[image6.jpg] +[images/image6.jpg] | | 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 ] | -[image7.jpg] +[images/image7.jpg] | | 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 ] | From 142ff2e866c89259c576b03b025b500e655cf028 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:35:00 +0300 Subject: [PATCH 0323/1039] Fix folder references --- Dijkstra Algorithm/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index cb0683e5d..677c97447 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -9,7 +9,7 @@ The best example is road network. If you wnat to find the shortest path from you I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. When the algorithm starts to work initial graph looks like this: -[images/image1.png] +[Images/image1.png] The table below will represent graph state @@ -50,10 +50,10 @@ Then we set this vertex as visited | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | checkingVertex.visited = true -[images/image2.jpg] +[Images/image2.jpg] Then we check all of its neighbors. If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. -[images/image3.jpg] +[Images/image3.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -61,7 +61,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -[images/image4.jpg] +[Images/image4.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -69,7 +69,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -[images/image5.jpg] +[Images/image5.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -77,7 +77,7 @@ If neighbor's path length from start is bigger than checking vertex path length | 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 ] | -[images/image6.jpg] +[Images/image6.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -85,7 +85,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -[images/image7.jpg] +[Images/image7.jpg] | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| From 8e0d77ff9f99812bb8de307b66f1d211ef4ea785 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:37:15 +0300 Subject: [PATCH 0324/1039] Images --- Dijkstra Algorithm/README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 677c97447..490b4de1d 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -9,7 +9,8 @@ The best example is road network. If you wnat to find the shortest path from you I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. When the algorithm starts to work initial graph looks like this: -[Images/image1.png] + + The table below will represent graph state @@ -50,10 +51,13 @@ Then we set this vertex as visited | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | checkingVertex.visited = true -[Images/image2.jpg] + + + Then we check all of its neighbors. If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. -[Images/image3.jpg] + + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -61,7 +65,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -[Images/image4.jpg] + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -69,7 +73,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -[Images/image5.jpg] + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -77,7 +81,7 @@ If neighbor's path length from start is bigger than checking vertex path length | 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 ] | -[Images/image6.jpg] + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| @@ -85,7 +89,7 @@ If neighbor's path length from start is bigger than checking vertex path length | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -[Images/image7.jpg] + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| From 37550365f6db8b980cfe1792a3122efe24a1ed91 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:55:29 +0300 Subject: [PATCH 0325/1039] Still improving description --- Dijkstra Algorithm/README.md | 73 ++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 490b4de1d..5541276fc 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,4 +1,4 @@ -# Dijkstra-algorithm +# Dijkstra's algorithm This algorithm was invented in 1956 by Edsger W. Dijkstra. @@ -6,13 +6,17 @@ This algorithm can be used, when you have one source vertex and want to find the The best example is road network. If you wnat to find the shortest path from your house to your job, then it is time for the Dijkstra's algorithm. -I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. -So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. +I have created **VisualizedDijkstra.playground** to help you to understand, how this algorithm works. Besides, I have described below step by step how does it works. + +So let's imagine, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. + +> Initialization + When the algorithm starts to work initial graph looks like this: -The table below will represent graph state +The table below represents graph state: | | A | B | C | D | E | |:------------------------- |:---:|:---:|:---:|:---:|:---:| @@ -20,11 +24,17 @@ The table below will represent graph state | Path Length From Start | inf | inf | inf | inf | inf | | Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | -Graph's array contains 5 vertices [A, B, C, D, E]. -Let's assume, that edge weight it is path length in kilometers between vertices. -A vertex has neighbors: B(path from A: 5.0), C(path from A: 0.0), D(path from A: 0.0) -And because algorithm has done nothing, then all vertices' path length from source vertex values are infinity (think about infinity as "I don't know, how long will it takes to get this vertex from source one") -Finally we have to set source vertex path length from source vertex to 0. +_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 out graph we have to set source vertex path length from source vertex to 0. + +| | A | B | C | D | E | +|:------------------------- |:---:|:---:|:---:|:---:|:---:| +| Visited | F | F | F | F | F | +| Path Length From Start | 0 | inf | inf | inf | inf | +| Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. @@ -37,12 +47,15 @@ Cycle: 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. Okay, let's start! -From now we will keep array which contains non visited vertices. Here they are: -var nonVisitedVertices = [A, B, C, D, E] -Let's follow the algorithm and pick the first vertex, which neighbors we want to check. -Imagine that we have function, that returns vertex with smallest path length from start. -var checkingVertex = nonVisitedVertices.smallestPathLengthFromStartVertex() -Then we set this vertex as visited +Let's follow the algorithm's cycle and pick the first vertex, which neighbors we want to check. +All our vertices are not visited, but there is only one have the smallest path length from start - A. This vertex is th 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 | |:------------------------- |:---:|:---:|:---:|:---:|:---:| @@ -50,21 +63,35 @@ Then we set this vertex as visited | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | -checkingVertex.visited = true - - +> Step 1 Then we check all of its neighbors. -If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. +If checking vertex path length from start + edge weigth is smaller than neighbor's path length from start, then we set neighbor'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 | @@ -73,6 +100,8 @@ If neighbor's path length from start is bigger than checking vertex path length | 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 | @@ -81,6 +110,8 @@ If neighbor's path length from start is bigger than checking vertex path length | 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 | @@ -89,8 +120,12 @@ If neighbor's path length from start is bigger than checking vertex path length | 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 + +> Step 6 + | | A | B | C | D | E | |:------------------------- |:----------:|:----------:|:----------:|:----------:|:----------:| | Visited | T | T | T | T | T | From 5e5e7a93188b79ee6693b19fd03d387635b87dbf Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:57:33 +0300 Subject: [PATCH 0326/1039] Description --- Dijkstra Algorithm/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 5541276fc..206507b7b 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -63,7 +63,7 @@ After this step graph has this state: | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | -> Step 1 +## Step 1 Then we check all of its neighbors. If checking vertex path length from start + edge weigth is smaller than neighbor's path length from start, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. @@ -88,7 +88,7 @@ And its state is here: | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -> Step 2 +## Step 2 From now we repeat all actions again and fill our table with new info! @@ -100,7 +100,7 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -> Step 3 +## Step 3 @@ -110,7 +110,7 @@ From now we repeat all actions again and fill our table with new info! | 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 +## Step 4 @@ -120,23 +120,23 @@ From now we repeat all actions again and fill our table with new info! | 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 +## Step 5 -> Step 6 - | | 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 ] | +## About + This repository contains to playgrounds: * To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. * If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. -## Dijkstra's algorithm explanation + From 2e7c34c8d59c003dffe5f51a5f035a8c9b1141ba Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:58:50 +0300 Subject: [PATCH 0327/1039] Probably final updates --- Dijkstra Algorithm/README.md | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 206507b7b..e73f95393 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -10,7 +10,7 @@ I have created **VisualizedDijkstra.playground** to help you to understand, how So let's imagine, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. -> Initialization +## Initialization When the algorithm starts to work initial graph looks like this: @@ -130,43 +130,17 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | 8 | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [A, B, C]| [A, D] | [A, D, E ] | -## About +## About this repository This repository contains to playgrounds: * To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. * If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. - - - - -[Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)'s explanation: -Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. - -1. Assign to every node a tentative distance value: set it to zero for our initial node and to infinity for all other nodes. -2. Set the initial node as current. Mark all other nodes unvisited. Create a set of all the unvisited nodes called the unvisited set. -3. For the current node, consider all of its unvisited neighbors and calculate their tentative distances. Compare the newly calculated tentative distance to the current assigned value and assign the smaller one. For example, if the current node A is marked with a distance of 6, and the edge connecting it with a neighbor B has length 2, then the distance to B (through A) will be 6 + 2 = 8. If B was previously marked with a distance greater than 8 then change it to 8. Otherwise, keep the current value. -4. When we are done considering all of the neighbors of the current node, mark the current node as visited and remove it from the unvisited set. A visited node will never be checked again. -5. If the destination node has been marked visited (when planning a route between two specific nodes) or if the smallest tentative distance among the nodes in the unvisited set is infinity (when planning a complete traversal; occurs when there is no connection between the initial node and remaining unvisited nodes), then stop. The algorithm has finished. -6. Otherwise, select the unvisited node that is marked with the smallest tentative distance, set it as the new "current node", and go back to step 3. - -Explanation, that can be found in the **VisualizedDijkstra.playground** -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. - -## Usage -This algorithm is popular in routing. For example, biggest Russian IT company Yandex uses it in [Яндекс.Карты](https://yandex.ru/company/technologies/routes/) - ## Demo video + Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Credits + WWDC 2017 Scholarship Project Created by [Taras Nikulin](https://github.com/crabman448) From dd9e998e4482ff9665e3964829569a0c5489daf4 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 16:01:01 +0300 Subject: [PATCH 0328/1039] Added reference to wikipedia --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index e73f95393..76cc4ca1d 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,6 +1,6 @@ # Dijkstra's algorithm -This algorithm was invented in 1956 by Edsger W. Dijkstra. +This [algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) was invented in 1956 by Edsger W. Dijkstra. This algorithm can be used, when you have one source vertex and want to find the shortest paths to all other vertices in the graph. From e2282045c04aeab0ff7eeb2c1df8edc33c92c76c Mon Sep 17 00:00:00 2001 From: Taras Date: Thu, 20 Apr 2017 16:07:33 +0300 Subject: [PATCH 0329/1039] Update README.md --- Dijkstra Algorithm/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 76cc4ca1d..61b47e97f 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -24,9 +24,11 @@ The table below represents graph state: | 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_ +>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 out graph we have to set source vertex path length from source vertex to 0. From b95331012e6fa880928b38a7606384e6b7a0db9a Mon Sep 17 00:00:00 2001 From: Taras Date: Thu, 20 Apr 2017 16:09:14 +0300 Subject: [PATCH 0330/1039] Update README.md --- Dijkstra Algorithm/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 61b47e97f..9999e224e 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -30,13 +30,13 @@ The table below represents graph state: >T states for True -To initialize out graph we have to set source vertex path length from source vertex to 0. +To initialize out graph we have to set source vertex path length from source vertex to 0, and append itself to path vertices ffrom 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 | [ ] | [ ] | [ ] | [ ] | [ ] | +| Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. From a44f84ecad941273df7472ef1c7de7aa93b1d1c8 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 16:26:33 +0300 Subject: [PATCH 0331/1039] Removed unnecessary images --- .../Images/Dijkstra_Animation.gif | Bin 8561 -> 0 bytes Dijkstra Algorithm/Images/screenshot1.jpg | Bin 224243 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Dijkstra Algorithm/Images/Dijkstra_Animation.gif delete mode 100644 Dijkstra Algorithm/Images/screenshot1.jpg diff --git a/Dijkstra Algorithm/Images/Dijkstra_Animation.gif b/Dijkstra Algorithm/Images/Dijkstra_Animation.gif deleted file mode 100644 index 3b1a2ef434107efb104a9bc1a6a714af37367529..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8561 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 diff --git a/Dijkstra Algorithm/Images/screenshot1.jpg b/Dijkstra Algorithm/Images/screenshot1.jpg deleted file mode 100644 index e9f7a1207f315e8f5aa20c72f3264c65edafd3a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224243 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 From 3395c01c00c80554be30f91310f2878d7faedcce Mon Sep 17 00:00:00 2001 From: darrellhz Date: Fri, 21 Apr 2017 16:04:19 +0900 Subject: [PATCH 0332/1039] Update README.markdown updated to Swift 3 syntax --- Linked List/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Linked List/README.markdown b/Linked List/README.markdown index c5a752e13..c03023c42 100644 --- a/Linked List/README.markdown +++ b/Linked List/README.markdown @@ -364,7 +364,7 @@ What else do we need? Removing nodes, of course! First we'll do `removeAll()`, w 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 `removeNode()` is the most optimal because you don't need to iterate through the list to find the node first. +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 { From b66e31825d9025916d9617073830f50284ebd488 Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 21 Apr 2017 19:25:23 +0100 Subject: [PATCH 0333/1039] Filters the potential change arrays for only the ones which add up to the exact value --- MinimumCoinChange/Sources/MinimumCoinChange.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MinimumCoinChange/Sources/MinimumCoinChange.swift b/MinimumCoinChange/Sources/MinimumCoinChange.swift index c995063ab..8b0da80ac 100644 --- a/MinimumCoinChange/Sources/MinimumCoinChange.swift +++ b/MinimumCoinChange/Sources/MinimumCoinChange.swift @@ -64,7 +64,10 @@ public struct MinimumCoinChange { if value - coin >= 0 { var potentialChange: [Int] = [coin] potentialChange.append(contentsOf: _changeDynamic(value - coin)) - potentialChangeArray.append(potentialChange) + + if potentialChange.reduce(0, +) == value { + potentialChangeArray.append(potentialChange) + } } } From d5c9d179f63767cfad7dda48faad914f808ca68b Mon Sep 17 00:00:00 2001 From: Jacopo Date: Fri, 21 Apr 2017 19:38:45 +0100 Subject: [PATCH 0334/1039] Optimisation: removed double check if the winner change is valid --- MinimumCoinChange/Sources/MinimumCoinChange.swift | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/MinimumCoinChange/Sources/MinimumCoinChange.swift b/MinimumCoinChange/Sources/MinimumCoinChange.swift index 8b0da80ac..55629d020 100644 --- a/MinimumCoinChange/Sources/MinimumCoinChange.swift +++ b/MinimumCoinChange/Sources/MinimumCoinChange.swift @@ -56,8 +56,6 @@ public struct MinimumCoinChange { return cached } - var change: [Int] = [] - var potentialChangeArray: [[Int]] = [] for coin in sortedCoinSet { @@ -73,14 +71,11 @@ public struct MinimumCoinChange { if potentialChangeArray.count > 0 { let sortedPotentialChangeArray = potentialChangeArray.sorted(by: { $0.count < $1.count }) - change = sortedPotentialChangeArray[0] + cache[value] = sortedPotentialChangeArray[0] + return sortedPotentialChangeArray[0] } - if change.reduce(0, +) == value { - cache[value] = change - } - - return change + return [] } let change: [Int] = _changeDynamic(value) From 2ff26a1365cce2d47e7cf8cc341eadf3134cfdac Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Fri, 21 Apr 2017 23:07:00 -0700 Subject: [PATCH 0335/1039] prettify some syntax around optionals --- AVL Tree/AVLTree.swift | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/AVL Tree/AVLTree.swift b/AVL Tree/AVLTree.swift index cfcf114c0..4feb691e4 100644 --- a/AVL Tree/AVLTree.swift +++ b/AVL Tree/AVLTree.swift @@ -99,17 +99,11 @@ open class AVLTree { extension TreeNode { public func minimum() -> TreeNode? { - if let leftChild = self.leftChild { - return leftChild.minimum() - } - return self + return leftChild?.minimum() ?? self } public func maximum() -> TreeNode? { - if let rightChild = self.rightChild { - return rightChild.maximum() - } - return self + return rightChild?.maximum() ?? self } } @@ -120,11 +114,7 @@ extension AVLTree { } public func search(input: Key) -> Payload? { - if let result = search(key: input, node: root) { - return result.payload - } else { - return nil - } + return search(key: input, node: root)?.payload } fileprivate func search(key: Key, node: Node?) -> Node? { @@ -385,11 +375,7 @@ extension TreeNode: CustomDebugStringConvertible { extension AVLTree: CustomDebugStringConvertible { public var debugDescription: String { - if let root = root { - return root.debugDescription - } else { - return "[]" - } + return root?.debugDescription ?? "[]" } } @@ -409,10 +395,6 @@ extension TreeNode: CustomStringConvertible { extension AVLTree: CustomStringConvertible { public var description: String { - if let root = root { - return root.description - } else { - return "[]" - } + return root?.description ?? "[]" } } From 7ecbb716fb9bd16f5f89bd491edc1fe81d3c85be Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Fri, 21 Apr 2017 23:15:30 -0700 Subject: [PATCH 0336/1039] prettify some syntax around optionals --- .../AVLTree.playground/Sources/AVLTree.swift | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/AVL Tree/AVLTree.playground/Sources/AVLTree.swift b/AVL Tree/AVLTree.playground/Sources/AVLTree.swift index b4b97f0d6..56ba81608 100644 --- a/AVL Tree/AVLTree.playground/Sources/AVLTree.swift +++ b/AVL Tree/AVLTree.playground/Sources/AVLTree.swift @@ -99,17 +99,11 @@ open class AVLTree { extension TreeNode { public func minimum() -> TreeNode? { - if let leftChild = self.leftChild { - return leftChild.minimum() - } - return self + return leftChild?.minimum() ?? self } public func maximum() -> TreeNode? { - if let rightChild = self.rightChild { - return rightChild.maximum() - } - return self + return rightChild?.maximum() ?? self } } @@ -120,11 +114,7 @@ extension AVLTree { } public func search(input: Key) -> Payload? { - if let result = search(key: input, node: root) { - return result.payload - } else { - return nil - } + return search(key: input, node: root)?.payload } fileprivate func search(key: Key, node: Node?) -> Node? { @@ -385,11 +375,7 @@ extension TreeNode: CustomDebugStringConvertible { extension AVLTree: CustomDebugStringConvertible { public var debugDescription: String { - if let root = root { - return root.debugDescription - } else { - return "[]" - } + return root?.debugDescription ?? "[]" } } @@ -409,10 +395,6 @@ extension TreeNode: CustomStringConvertible { extension AVLTree: CustomStringConvertible { public var description: String { - if let root = root { - return root.description - } else { - return "[]" - } + return root?.description ?? "[]" } } From 3d48ed411d872b5b3f03c114e6b1c074bb4293e8 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Sun, 23 Apr 2017 23:36:55 +0300 Subject: [PATCH 0337/1039] Credits --- Dijkstra Algorithm/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 9999e224e..086e60c55 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -144,5 +144,4 @@ Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) ## Credits -WWDC 2017 Scholarship Project -Created by [Taras Nikulin](https://github.com/crabman448) +WWDC 2017 Scholarship Project (Rejected) created by [Taras Nikulin](https://github.com/crabman448) From 83f7a32ccf0a2fe4b6223305bf89a7724b666a65 Mon Sep 17 00:00:00 2001 From: Antonio081014 Date: Mon, 24 Apr 2017 11:23:09 -0700 Subject: [PATCH 0338/1039] Add variety implementation with complexity analysis. --- Union-Find/README.markdown | 63 ++++++++++---- .../UnionFind.playground/Contents.swift | 82 ++++--------------- .../Sources/UnionFindQuickFind.swift | 50 +++++++++++ .../Sources/UnionFindQuickUnion.swift | 51 ++++++++++++ .../Sources/UnionFindWeightedQuickFind.swift | 59 +++++++++++++ .../Sources/UnionFindWeightedQuickUnion.swift | 56 +++++++++++++ ...indWeightedQuickUnionPathCompression.swift | 53 ++++++++++++ .../UnionFind.playground/timeline.xctimeline | 6 -- Union-Find/UnionFind.swift | 59 ------------- 9 files changed, 330 insertions(+), 149 deletions(-) create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift create mode 100644 Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift delete mode 100644 Union-Find/UnionFind.playground/timeline.xctimeline delete mode 100644 Union-Find/UnionFind.swift diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index 5102f6b89..03e082507 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -23,7 +23,8 @@ The most common application of this data structure is keeping track of the conne ## Implementation -Union-Find can be implemented in many ways but we'll look at the most efficient. +Union-Find can be implemented in many ways but we'll look at an efficient and easy to understand implementation: Weighted Quick Union. +> __PS: Variety implementation of Union-Find has been included in playground.__ ```swift public struct UnionFind { @@ -141,24 +142,24 @@ public mutating func inSameSet(_ firstElement: T, and secondElement: T) -> Bool Since this calls `setOf()` it also optimizes the tree. -## Union +## 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] - } + 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: @@ -167,7 +168,7 @@ Here is how it works: 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. 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. +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. @@ -185,10 +186,40 @@ Note that, because we call `setOf()` at the start of the method, the larger tree 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 of Variety Implementation + +##### 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)* +*Written for Swift Algorithm Club by [Artur Antonov](https://github.com/goingreen)*, *modified by [Yi Ding](https://github.com/antonio081014).* \ No newline at end of file diff --git a/Union-Find/UnionFind.playground/Contents.swift b/Union-Find/UnionFind.playground/Contents.swift index 09649b938..9ad5215b3 100644 --- a/Union-Find/UnionFind.playground/Contents.swift +++ b/Union-Find/UnionFind.playground/Contents.swift @@ -1,73 +1,19 @@ //: Playground - noun: a place where people can play -public struct UnionFind { - private var index = [T: Int]() - private var parent = [Int]() - private var size = [Int]() - - 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 - } - } -} - - - - -var dsu = UnionFind() +var dsu = UnionFindQuickUnion() for i in 1...10 { - dsu.addSetWith(i) + 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) - } + if i % 2 == 0 { + dsu.unionSetsContaining(2, and: i) + } else { + dsu.unionSetsContaining(1, and: i) + } } // check our division @@ -88,7 +34,7 @@ print(dsu.inSameSet(3, and: 6)) -var dsuForStrings = UnionFind() +var dsuForStrings = UnionFindQuickUnion() let words = ["all", "border", "boy", "afternoon", "amazing", "awesome", "best"] dsuForStrings.addSetWith("a") @@ -96,12 +42,12 @@ 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) - } + 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")) diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift b/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift new file mode 100644 index 000000000..25d7f5b5d --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift @@ -0,0 +1,50 @@ +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 + } + } +} diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift b/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift new file mode 100644 index 000000000..4c848e61d --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift @@ -0,0 +1,51 @@ +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 + } + } +} diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift new file mode 100644 index 000000000..02bec94a8 --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift @@ -0,0 +1,59 @@ +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 + } + } +} diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift new file mode 100644 index 000000000..b3ac7445e --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift @@ -0,0 +1,56 @@ +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 + } + } +} diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift new file mode 100644 index 000000000..892f46a3c --- /dev/null +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift @@ -0,0 +1,53 @@ +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 + } + } +} diff --git a/Union-Find/UnionFind.playground/timeline.xctimeline b/Union-Find/UnionFind.playground/timeline.xctimeline deleted file mode 100644 index bf468afec..000000000 --- a/Union-Find/UnionFind.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/Union-Find/UnionFind.swift b/Union-Find/UnionFind.swift deleted file mode 100644 index 506cdc1fe..000000000 --- a/Union-Find/UnionFind.swift +++ /dev/null @@ -1,59 +0,0 @@ -/* - 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 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 - } - } -} From 0de6055763a91902d3a52ef4857930aec6dbd0d7 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 25 Apr 2017 17:36:09 +0300 Subject: [PATCH 0339/1039] Added code description --- Dijkstra Algorithm/README.md | 138 +++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 086e60c55..a72843e69 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -132,6 +132,144 @@ From now we repeat all actions again and fill our table with new info! | 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, lets 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 use cases, + //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. + //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. + open var neighbors: [(Vertex, Double)] = [] + + //As it was mentioned in 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 algorithm execution. + open var pathLengthFromStart = Double.infinity + + //This array containt 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 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 andd recalculate paths, then we will simply clear graph vertices' cashes. + open func clearCache() { + pathLengthFromStart = Double.infinity + pathVerticesFromStart = [] + } +} +``` + +Because every vertex should be unique it is usefull to make them Hashable and according Equatable. We use 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 realization is really straightforward. +```swift +public class Dijkstra { + //It 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 shortes path from startVertex, + //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. + //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 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 { + + //Nex 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) + + //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited + let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } + + //Let's iterate through them + for neighbor in filteredNeighbors { + //These variable are more representative, than neighbor.0 or neighbor.1 + let neighborVertex = neighbor.0 + let weight = neighbor.1 + + //Here we calculate new weight, that we can offer to neighbor. + let theoreticNewWeight = vertex.pathLengthFromStart + weight + + //If it is smaller than neighbor's current pathLengthFromStart + //Then we perform this code + if theoreticNewWeight < neighborVertex.pathLengthFromStart { + + //set new pathLengthFromStart + neighborVertex.pathLengthFromStart = theoreticNewWeight + + //set new pathVerticesFromStart + neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart + + //append current vertex to neighbor's pathVerticesFromStart + neighborVertex.pathVerticesFromStart.append(neighborVertex) + } + } + + //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 random graph. + +Also there is a **VisualizedDijkstra.playground**. Use it to figure out algorithm flow in real (slowed :)) time. + ## About this repository This repository contains to playgrounds: From aac4f8fbf24f6996b70ea5c1f792ba7b81cd9e98 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 25 Apr 2017 17:54:34 +0300 Subject: [PATCH 0340/1039] Fixed code comments --- Dijkstra Algorithm/README.md | 76 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index a72843e69..2b6bc3875 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -139,28 +139,28 @@ It is pretty simple ```swift open class Vertex { - //Every vertex should be unique, that's why we set up identifier +//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 use cases, - //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. - //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. +//For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, +//when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. +//Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. open var neighbors: [(Vertex, Double)] = [] - //As it was mentioned in 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 algorithm execution. +//As it was mentioned in 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 algorithm execution. open var pathLengthFromStart = Double.infinity - //This array containt 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 algorithm execution. +//This array containt 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 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 andd recalculate paths, then we will simply clear graph vertices' cashes. +//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 andd recalculate paths, then we will simply clear graph vertices' cashes. open func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] @@ -187,79 +187,79 @@ We've created a base for our algorithm. Now let's create a house :) Dijkstra's realization is really straightforward. ```swift public class Dijkstra { - //It 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. +//It 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. +//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 shortes path from startVertex, - //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. - //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 +//Before we start searching shortes path from startVertex, +//we need to clear vertices cache just to be sure, that out graph is as clean as a baby. +//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 empty pathVerticesFromStart array. +//Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. - //The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart +//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. +//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 { - //Nex 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"* +//Nex 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) - //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited +//filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } - //Let's iterate through them +//Let's iterate through them for neighbor in filteredNeighbors { - //These variable are more representative, than neighbor.0 or neighbor.1 +//These variable are more representative, than neighbor.0 or neighbor.1 let neighborVertex = neighbor.0 let weight = neighbor.1 - //Here we calculate new weight, that we can offer to neighbor. +//Here we calculate new weight, that we can offer to neighbor. let theoreticNewWeight = vertex.pathLengthFromStart + weight - //If it is smaller than neighbor's current pathLengthFromStart - //Then we perform this code +//If it is smaller than neighbor's current pathLengthFromStart +//Then we perform this code if theoreticNewWeight < neighborVertex.pathLengthFromStart { - //set new pathLengthFromStart +//set new pathLengthFromStart neighborVertex.pathLengthFromStart = theoreticNewWeight - //set new pathVerticesFromStart +//set new pathVerticesFromStart neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart - //append current vertex to neighbor's pathVerticesFromStart +//append current vertex to neighbor's pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } - //If totalVertices is empty, i.e. all vertices are visited - //Than break the loop +//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. +//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 } } } From edbccd3b4fee79fe55ce2d741833dbef431bf466 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 25 Apr 2017 17:57:12 +0300 Subject: [PATCH 0341/1039] Fixed comments again --- Dijkstra Algorithm/README.md | 76 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 2b6bc3875..a8ed3c827 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -139,28 +139,28 @@ It is pretty simple ```swift open class Vertex { -//Every vertex should be unique, that's why we set up identifier + //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 use cases, -//when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. -//Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. + //For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, + //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. + //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. open var neighbors: [(Vertex, Double)] = [] -//As it was mentioned in 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 algorithm execution. + //As it was mentioned in 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 algorithm execution. open var pathLengthFromStart = Double.infinity -//This array containt 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 algorithm execution. + //This array containt 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 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 andd recalculate paths, then we will simply clear graph vertices' cashes. + //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 andd recalculate paths, then we will simply clear graph vertices' cashes. open func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] @@ -187,79 +187,79 @@ We've created a base for our algorithm. Now let's create a house :) Dijkstra's realization is really straightforward. ```swift public class Dijkstra { -//It 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. + //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. + //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 shortes path from startVertex, -//we need to clear vertices cache just to be sure, that out graph is as clean as a baby. -//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 + //Before we start searching shortes path from startVertex, + //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. + //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 empty pathVerticesFromStart array. + //Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. -//The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart + //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. + //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 { -//Nex 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"* + //Nex 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) -//filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited + //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } -//Let's iterate through them + //Let's iterate through them for neighbor in filteredNeighbors { -//These variable are more representative, than neighbor.0 or neighbor.1 + //These variable are more representative, than neighbor.0 or neighbor.1 let neighborVertex = neighbor.0 let weight = neighbor.1 -//Here we calculate new weight, that we can offer to neighbor. + //Here we calculate new weight, that we can offer to neighbor. let theoreticNewWeight = vertex.pathLengthFromStart + weight -//If it is smaller than neighbor's current pathLengthFromStart -//Then we perform this code + //If it is smaller than neighbor's current pathLengthFromStart + //Then we perform this code if theoreticNewWeight < neighborVertex.pathLengthFromStart { -//set new pathLengthFromStart + //set new pathLengthFromStart neighborVertex.pathLengthFromStart = theoreticNewWeight -//set new pathVerticesFromStart + //set new pathVerticesFromStart neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart -//append current vertex to neighbor's pathVerticesFromStart + //append current vertex to neighbor's pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } -//If totalVertices is empty, i.e. all vertices are visited -//Than break the loop + //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. + //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 } } } From b6c5b820be7506bbbfec04b230bbedcda1b6f5d0 Mon Sep 17 00:00:00 2001 From: Taras Date: Tue, 25 Apr 2017 18:02:52 +0300 Subject: [PATCH 0342/1039] Update README.md --- Dijkstra Algorithm/README.md | 80 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index a8ed3c827..f8ac37cf0 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -139,28 +139,28 @@ It is pretty simple ```swift open class Vertex { - //Every vertex should be unique, that's why we set up identifier + //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 use cases, - //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. - //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. + //For dijkstra every vertex in the graph should be connected with at least one other vertex. But there can be some use cases, + //when you firstly initialize all vertices without neighbors. And then on next interation set up thei neighbors. So, initially neighbors is an empty array. + //Array contains tuples (Vertex, Double). Vertex is a neighbor and Double is as edge weight to that neighbor. open var neighbors: [(Vertex, Double)] = [] - //As it was mentioned in 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 algorithm execution. + //As it was mentioned in 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 algorithm execution. open var pathLengthFromStart = Double.infinity - - //This array containt 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 algorithm execution. + + //This array containt 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 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 andd recalculate paths, then we will simply clear graph vertices' cashes. + //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 andd recalculate paths, then we will simply clear graph vertices' cashes. open func clearCache() { pathLengthFromStart = Double.infinity pathVerticesFromStart = [] @@ -187,79 +187,79 @@ We've created a base for our algorithm. Now let's create a house :) Dijkstra's realization 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. + //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. + //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 shortes path from startVertex, - //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. - //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 + //Before we start searching shortes path from startVertex, + //we need to clear vertices cache just to be sure, that out graph is as clean as a baby. + //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 empty pathVerticesFromStart array. + //Now all our vertices have Double.infinity pathLengthFromStart and empty pathVerticesFromStart array. - //The next step in the algorithm is to set startVertex pathLengthFromStart and pathVerticesFromStart + //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. + //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 { - - //Nex 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"* + + //Nex 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) - //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited + //filteredNeighbors is and arrray, that contains current vertex neighbors, which aren't yet visited let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } - //Let's iterate through them + //Let's iterate through them for neighbor in filteredNeighbors { - //These variable are more representative, than neighbor.0 or neighbor.1 + //These variable are more representative, than neighbor.0 or neighbor.1 let neighborVertex = neighbor.0 let weight = neighbor.1 - //Here we calculate new weight, that we can offer to neighbor. + //Here we calculate new weight, that we can offer to neighbor. let theoreticNewWeight = vertex.pathLengthFromStart + weight - //If it is smaller than neighbor's current pathLengthFromStart - //Then we perform this code + //If it is smaller than neighbor's current pathLengthFromStart + //Then we perform this code if theoreticNewWeight < neighborVertex.pathLengthFromStart { - //set new pathLengthFromStart + //set new pathLengthFromStart neighborVertex.pathLengthFromStart = theoreticNewWeight - //set new pathVerticesFromStart + //set new pathVerticesFromStart neighborVertex.pathVerticesFromStart = vertex.pathVerticesFromStart - //append current vertex to neighbor's pathVerticesFromStart + //append current vertex to neighbor's pathVerticesFromStart neighborVertex.pathVerticesFromStart.append(neighborVertex) } } - //If totalVertices is empty, i.e. all vertices are visited - //Than break the loop + //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. + //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 } } } From 9575a6745caa33bc5d864d6e406682af2f5f9515 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Tue, 25 Apr 2017 18:22:00 +0300 Subject: [PATCH 0343/1039] Added some comments to playground --- Dijkstra Algorithm/Dijkstra.playground/Contents.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift index 1c12245bd..7c7f1a4b0 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -14,13 +14,18 @@ func createNotConnectedVertices() { func setupConnections() { for vertex in vertices { + //the amount of edges each vertex can have let randomEdgesCount = arc4random_uniform(4) + 1 for _ in 0.. Date: Wed, 26 Apr 2017 10:31:44 +0300 Subject: [PATCH 0344/1039] Final edits --- Dijkstra Algorithm/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index f8ac37cf0..db1726b1f 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -2,13 +2,13 @@ This [algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) was invented in 1956 by Edsger W. Dijkstra. -This algorithm can be used, when you have one source vertex and want to find the shortest paths to all other vertices in the graph. +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 road network. If you wnat to find the shortest path from your house to your job, then it is time for the Dijkstra's algorithm. -I have created **VisualizedDijkstra.playground** to help you to understand, how this algorithm works. Besides, I have described below step by step how does it works. +I have created **VisualizedDijkstra.playground** to improve your understanding of the algorithm's flow. Besides, below is step by step algorithm's description. -So let's imagine, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. +Let's imagine, 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 graph, that connects your house with all these stores. So, you know what to do :) ## Initialization @@ -30,7 +30,7 @@ The table below represents graph state: >T states for True -To initialize out graph we have to set source vertex path length from source vertex to 0, and append itself to path vertices ffrom start. +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 | |:------------------------- |:---:|:---:|:---:|:---:|:---:| @@ -40,7 +40,7 @@ To initialize out graph we have to set source vertex path length from source ver Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. -But before we will go through all process side by side let me explain how algorithm works. +But before we will go through all process side by side read this explanation. 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) @@ -50,7 +50,7 @@ When all vertices are marked as visited, the algorithm's job is done. Now, you c Okay, let's start! Let's follow the algorithm's cycle and pick the first vertex, which neighbors we want to check. -All our vertices are not visited, but there is only one have the smallest path length from start - A. This vertex is th first one, which neighbors we will check. +All our vertices are not visited, but there is only one has the smallest path length from start - A. This vertex is the first one, which neighbors we will check. First of all, set this vertex as visited A.visited = true @@ -268,7 +268,9 @@ public class Dijkstra { That's all! Now you can check this algorithm in the playground. On the main page there is a code for creating random graph. -Also there is a **VisualizedDijkstra.playground**. Use it to figure out algorithm flow in real (slowed :)) time. +Also there is a **VisualizedDijkstra.playground**. Use it to figure out algorithm's flow in real (slowed :)) time. + +It is up to you how to implement some specific parts of 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 From d79a076ea901657161392a4fc3b53b0e2df65cdd Mon Sep 17 00:00:00 2001 From: Lucy Jeong Date: Thu, 27 Apr 2017 11:31:57 +0900 Subject: [PATCH 0345/1039] Update README.markdown changed enumerate() -> enumerated() --- Hash Table/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hash Table/README.markdown b/Hash Table/README.markdown index bc9636195..8f1eaaf70 100644 --- a/Hash Table/README.markdown +++ b/Hash Table/README.markdown @@ -202,7 +202,7 @@ The code to insert a new element or update an existing element lives in `updateV let index = self.index(forKey: key) // Do we already have this key in the bucket? - for (i, element) in buckets[index].enumerate() { + for (i, element) in buckets[index].enumerated() { if element.key == key { let oldValue = element.value buckets[index][i].value = value From 03393a86a3864221ff1f0b7137eefb619bf19698 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 06:17:13 +0500 Subject: [PATCH 0346/1039] Fix "found unknown escape character" while trying to run swiftlint 0.18.1 Also update the smiley face regex check to have a space before the colon so that it doesn't match: fatalError("init(coder:) has not been implemented") --- .swiftlint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 1434bf637..6cb714110 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -17,8 +17,8 @@ disabled_rules: custom_rules: smiley_face: name: "Smiley Face" - regex: "(\:\))" - match_kinds: + regex: '( :\))' + match_kinds: - comment - string message: "A closing parenthesis smiley :) creates a half-hearted smile, and thus is not preferred. Use :]" From 018ddaccfc0276ac8740c093731b92aeae122a9d Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:42:15 +0500 Subject: [PATCH 0347/1039] [swiftlint] Fix: MARK comment should be in valid format. --- .../TST.playground/Sources/TernarySearchTree.swift | 4 ++-- Ternary Search Tree/TernarySearchTree.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift index fed8f9710..21b8f0dc3 100644 --- a/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift +++ b/Ternary Search Tree/TST.playground/Sources/TernarySearchTree.swift @@ -15,7 +15,7 @@ public class TernarySearchTree { public init() {} - //MARK: - Insertion + // MARK: - Insertion public func insert(data: Element, withKey key: String) -> Bool { return insert(node: &root, withData: data, andKey: key, atIndex: 0) @@ -59,7 +59,7 @@ public class TernarySearchTree { } - //MARK: - Finding + // MARK: - Finding public func find(key: String) -> Element? { diff --git a/Ternary Search Tree/TernarySearchTree.swift b/Ternary Search Tree/TernarySearchTree.swift index 2e2ca2917..0fa6d9634 100644 --- a/Ternary Search Tree/TernarySearchTree.swift +++ b/Ternary Search Tree/TernarySearchTree.swift @@ -23,7 +23,7 @@ public class TernarySearchTree { */ public init() {} - //MARK: - Insertion + // MARK: - Insertion /** Public insertion method. @@ -85,7 +85,7 @@ public class TernarySearchTree { } - //MARK: - Finding + // MARK: - Finding /** Public find method. From 29c5952fadf80e8ac3f0c717d7d7ae08620b0dcb Mon Sep 17 00:00:00 2001 From: Felipe Naranjo Date: Fri, 28 Apr 2017 10:57:48 -0400 Subject: [PATCH 0348/1039] Update README.markdown Though "indexes" is grammatically correct, the word "indices" is used in Apple documentation. --- Union-Find/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index 5102f6b89..68698f39e 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -119,7 +119,7 @@ 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 indexes of the elements are marked in red.) +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: From 137c36051dff6a1e3965dad4959ad0a742fc01b4 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:46:49 +0500 Subject: [PATCH 0349/1039] [swiftlint] Fix: Else and catch should be on the same line warning: Statement Position Violation: Else and catch should be on the same line, one space after the previous declaration. --- DiningPhilosophers/Sources/main.swift | 3 +-- Skip-List/SkipList.swift | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/DiningPhilosophers/Sources/main.swift b/DiningPhilosophers/Sources/main.swift index 285402d53..338a9074d 100755 --- a/DiningPhilosophers/Sources/main.swift +++ b/DiningPhilosophers/Sources/main.swift @@ -22,8 +22,7 @@ struct ForkPair { if leftIndex > rightIndex { leftFork = ForkPair.forksSemaphore[leftIndex] rightFork = ForkPair.forksSemaphore[rightIndex] - } - else { + } else { leftFork = ForkPair.forksSemaphore[rightIndex] rightFork = ForkPair.forksSemaphore[leftIndex] } diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 5fc61bf8e..c5fe2b821 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -118,8 +118,7 @@ extension SkipList { if value.key == key { isFound = true break - } - else { + } else { if key < value.key! { currentNode = node.down } else { From c3a05c6bfe865554261fbb0b641651f7dcfffff4 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:49:54 +0500 Subject: [PATCH 0350/1039] [swiftlint] Fix: trailing_semicolon warning: Trailing Semicolon Violation: Lines should not have trailing semicolons. --- Trie/Trie/TrieTests/TrieTests.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index a75c35c62..50a30a552 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -175,21 +175,21 @@ class TrieTests: XCTestCase { trie.insert(word: "another") trie.insert(word: "exam") let wordsAll = trie.findWordsWithPrefix(prefix: "") - XCTAssertEqual(wordsAll.sorted(), ["another", "exam", "test"]); + XCTAssertEqual(wordsAll.sorted(), ["another", "exam", "test"]) let words = trie.findWordsWithPrefix(prefix: "ex") - XCTAssertEqual(words, ["exam"]); + XCTAssertEqual(words, ["exam"]) trie.insert(word: "examination") let words2 = trie.findWordsWithPrefix(prefix: "exam") - XCTAssertEqual(words2, ["exam", "examination"]); + XCTAssertEqual(words2, ["exam", "examination"]) let noWords = trie.findWordsWithPrefix(prefix: "tee") - XCTAssertEqual(noWords, []); + XCTAssertEqual(noWords, []) let unicodeWord = "😬😎" trie.insert(word: unicodeWord) let wordsUnicode = trie.findWordsWithPrefix(prefix: "😬") - XCTAssertEqual(wordsUnicode, [unicodeWord]); + XCTAssertEqual(wordsUnicode, [unicodeWord]) trie.insert(word: "Team") let wordsUpperCase = trie.findWordsWithPrefix(prefix: "Te") - XCTAssertEqual(wordsUpperCase.sorted(), ["team", "test"]); + XCTAssertEqual(wordsUpperCase.sorted(), ["team", "test"]) } } From 4eb7ac1975dfbd2f3d9059d649af3ab6f90d97a2 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:52:12 +0500 Subject: [PATCH 0351/1039] [swiftlint] Fix control_statement (i.e. parens around if statement) warning: Control Statement Violation: if,for,while,do statements shouldn't wrap their conditionals in parentheses. --- Rootish Array Stack/Tests/RootishArrayStackTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rootish Array Stack/Tests/RootishArrayStackTests.swift b/Rootish Array Stack/Tests/RootishArrayStackTests.swift index f73857d0f..9ffc4ebb9 100755 --- a/Rootish Array Stack/Tests/RootishArrayStackTests.swift +++ b/Rootish Array Stack/Tests/RootishArrayStackTests.swift @@ -4,7 +4,7 @@ fileprivate extension RootishArrayStack { func equal(toArray array: Array) -> Bool{ for index in 0.. Date: Fri, 28 Apr 2017 09:53:16 +0500 Subject: [PATCH 0352/1039] [swiftlint] Fix redundant_optional_initialization (i.e. don't need "= nil") warning: Redundant Optional Initialization Violation: Initializing an optional variable with nil is redundant. --- Graph/Graph/AdjacencyListGraph.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index e5e9fc2db..edb754c97 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -12,7 +12,7 @@ import Foundation private class EdgeList where T: Equatable, T: Hashable { var vertex: Vertex - var edges: [Edge]? = nil + var edges: [Edge]? init(vertex: Vertex) { self.vertex = vertex From 55eba6e7d86e468b1cb0f114c25f5439cf2d4702 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:55:51 +0500 Subject: [PATCH 0353/1039] [swiftlint] Fix: closure_parameter_position warning: Closure Parameter Position Violation: Closure parameters should be on the same line as opening brace. --- B-Tree/BTree.playground/Contents.swift | 3 +-- Shunting Yard/ShuntingYard.playground/Sources/Stack.swift | 3 +-- Skip-List/SkipList.swift | 7 +++---- Stack/Stack.swift | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/B-Tree/BTree.playground/Contents.swift b/B-Tree/BTree.playground/Contents.swift index 8238fe5a5..710ace701 100644 --- a/B-Tree/BTree.playground/Contents.swift +++ b/B-Tree/BTree.playground/Contents.swift @@ -14,8 +14,7 @@ bTree[3] bTree.remove(2) -bTree.traverseKeysInOrder { - key in +bTree.traverseKeysInOrder { key in print(key) } diff --git a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift index a67bb9d64..27286fdbd 100644 --- a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift +++ b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift @@ -31,8 +31,7 @@ public struct Stack { extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self - return AnyIterator { - _ -> T? in + return AnyIterator { _ -> T? in return curr.pop() } } diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index c5fe2b821..1418656f3 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -52,10 +52,9 @@ public struct Stack { extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self - return AnyIterator { - _ -> T? in - return curr.pop() - } + return AnyIterator { _ -> T? in + return curr.pop() + } } } diff --git a/Stack/Stack.swift b/Stack/Stack.swift index 974d5a443..c3f42ea44 100644 --- a/Stack/Stack.swift +++ b/Stack/Stack.swift @@ -30,8 +30,7 @@ public struct Stack { extension Stack: Sequence { public func makeIterator() -> AnyIterator { var curr = self - return AnyIterator { - _ -> T? in + return AnyIterator { _ -> T? in return curr.pop() } } From 6c3dcd4be40058e09875d4bcd3f6086e021380e4 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:57:19 +0500 Subject: [PATCH 0354/1039] [swiftlint] Fix: leading_whitespace warning: Leading Whitespace Violation: File shouldn't start with whitespace. --- HaversineDistance/HaversineDistance.playground/Contents.swift | 1 - QuadTree/QuadTree.playground/Contents.swift | 1 - QuadTree/QuadTree.playground/Sources/QuadTree.swift | 1 - Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift | 1 - 4 files changed, 4 deletions(-) diff --git a/HaversineDistance/HaversineDistance.playground/Contents.swift b/HaversineDistance/HaversineDistance.playground/Contents.swift index f46d7c394..a6effb7b0 100644 --- a/HaversineDistance/HaversineDistance.playground/Contents.swift +++ b/HaversineDistance/HaversineDistance.playground/Contents.swift @@ -1,4 +1,3 @@ - import UIKit func haversineDinstance(la1: Double, lo1: Double, la2: Double, lo2: Double, radius: Double = 6367444.7) -> Double { diff --git a/QuadTree/QuadTree.playground/Contents.swift b/QuadTree/QuadTree.playground/Contents.swift index 41e73147f..ad8ee31f8 100644 --- a/QuadTree/QuadTree.playground/Contents.swift +++ b/QuadTree/QuadTree.playground/Contents.swift @@ -1,4 +1,3 @@ - import Foundation let tree = QuadTree(rect: Rect(origin: Point(0, 0), size: Size(xLength: 10, yLength: 10))) diff --git a/QuadTree/QuadTree.playground/Sources/QuadTree.swift b/QuadTree/QuadTree.playground/Sources/QuadTree.swift index 65c55d49e..14d0dbba7 100644 --- a/QuadTree/QuadTree.playground/Sources/QuadTree.swift +++ b/QuadTree/QuadTree.playground/Sources/QuadTree.swift @@ -1,4 +1,3 @@ - public struct Point { let x: Double let y: Double diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift index 1735798d5..b0f440809 100644 --- a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -1,4 +1,3 @@ - private enum RBTColor { case red case black From 932b453d5b0ce1b5ad058323bed79728f92dfd52 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 09:58:51 +0500 Subject: [PATCH 0355/1039] [swiftlint] Fix rule: trailing_newline warning: Trailing Newline Violation: Files should have a single trailing newline. --- B-Tree/Tests/Tests/BTreeNodeTests.swift | 1 - Comb Sort/Comb Sort.playground/Contents.swift | 2 -- Convex Hull/Convex Hull/AppDelegate.swift | 1 - Fixed Size Array/FixedSizeArray.playground/Contents.swift | 1 - Insertion Sort/InsertionSort.playground/Contents.swift | 2 +- Linked List/LinkedList.playground/Contents.swift | 1 - .../MRPrimality.playground/Contents.swift | 2 +- Run-Length Encoding/RLE.playground/Contents.swift | 2 +- Trie/Trie/Trie/AppDelegate.swift | 1 - Trie/Trie/Trie/ViewController.swift | 1 - 10 files changed, 3 insertions(+), 11 deletions(-) diff --git a/B-Tree/Tests/Tests/BTreeNodeTests.swift b/B-Tree/Tests/Tests/BTreeNodeTests.swift index da6ebe9f6..fd3ba10e8 100644 --- a/B-Tree/Tests/Tests/BTreeNodeTests.swift +++ b/B-Tree/Tests/Tests/BTreeNodeTests.swift @@ -51,4 +51,3 @@ class BTreeNodeTests: XCTestCase { XCTAssertEqual(root.children!.count, 2) } } - diff --git a/Comb Sort/Comb Sort.playground/Contents.swift b/Comb Sort/Comb Sort.playground/Contents.swift index d6add44f5..40176be9f 100644 --- a/Comb Sort/Comb Sort.playground/Contents.swift +++ b/Comb Sort/Comb Sort.playground/Contents.swift @@ -16,5 +16,3 @@ while i < 1000 { i += 1 } combSort(bigArray) - - diff --git a/Convex Hull/Convex Hull/AppDelegate.swift b/Convex Hull/Convex Hull/AppDelegate.swift index 1901083a8..4f8496cd5 100644 --- a/Convex Hull/Convex Hull/AppDelegate.swift +++ b/Convex Hull/Convex Hull/AppDelegate.swift @@ -54,4 +54,3 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } - diff --git a/Fixed Size Array/FixedSizeArray.playground/Contents.swift b/Fixed Size Array/FixedSizeArray.playground/Contents.swift index f1bc63315..4bc5d66df 100644 --- a/Fixed Size Array/FixedSizeArray.playground/Contents.swift +++ b/Fixed Size Array/FixedSizeArray.playground/Contents.swift @@ -53,4 +53,3 @@ array.append(2) array[1] array.removeAt(index: 0) array.removeAll() - diff --git a/Insertion Sort/InsertionSort.playground/Contents.swift b/Insertion Sort/InsertionSort.playground/Contents.swift index b25916b23..df1822b8f 100644 --- a/Insertion Sort/InsertionSort.playground/Contents.swift +++ b/Insertion Sort/InsertionSort.playground/Contents.swift @@ -16,4 +16,4 @@ func insertionSort(_ array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { let list = [ 10, -1, 3, 9, 2, 27, 8, 5, 1, 3, 0, 26 ] insertionSort(list, <) -insertionSort(list, >) \ No newline at end of file +insertionSort(list, >) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index b86fbf0b4..10677935a 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -389,4 +389,3 @@ let listArrayLiteral2: LinkedList = ["Swift", "Algorithm", "Club"] listArrayLiteral2.count // 3 listArrayLiteral2[0] // "Swift" listArrayLiteral2.removeLast() // "Club" - diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift b/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift index 8d97dc409..98032bd59 100644 --- a/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift +++ b/Miller-Rabin Primality Test/MRPrimality.playground/Contents.swift @@ -21,4 +21,4 @@ mrPrimalityTest(178426363) mrPrimalityTest(32415187747) // With iteration -mrPrimalityTest(32416190071, iteration: 10) \ No newline at end of file +mrPrimalityTest(32416190071, iteration: 10) diff --git a/Run-Length Encoding/RLE.playground/Contents.swift b/Run-Length Encoding/RLE.playground/Contents.swift index 62b4ef437..11e177d0d 100644 --- a/Run-Length Encoding/RLE.playground/Contents.swift +++ b/Run-Length Encoding/RLE.playground/Contents.swift @@ -113,4 +113,4 @@ func runTests() -> Bool { return result } -runTests() \ No newline at end of file +runTests() diff --git a/Trie/Trie/Trie/AppDelegate.swift b/Trie/Trie/Trie/AppDelegate.swift index 4da9dc345..b2b4c0c5f 100644 --- a/Trie/Trie/Trie/AppDelegate.swift +++ b/Trie/Trie/Trie/AppDelegate.swift @@ -23,4 +23,3 @@ class AppDelegate: NSObject, NSApplicationDelegate { } - diff --git a/Trie/Trie/Trie/ViewController.swift b/Trie/Trie/Trie/ViewController.swift index b2e9d9105..e24a812cb 100644 --- a/Trie/Trie/Trie/ViewController.swift +++ b/Trie/Trie/Trie/ViewController.swift @@ -24,4 +24,3 @@ class ViewController: NSViewController { } - From a025c0cc27b3fa4b8bfa2255f59eceb8447ad9b3 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 10:00:27 +0500 Subject: [PATCH 0356/1039] [swiftlint] Fix rule: opening_brace warning: Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration. --- .../BruteForceStringSearch.playground/Contents.swift | 2 +- Brute-Force String Search/BruteForceStringSearch.swift | 2 +- .../KaratsubaMultiplication.playground/Contents.swift | 6 +++--- .../Red-Black Tree 2.playground/Sources/RBTree.swift | 2 +- Rootish Array Stack/Tests/RootishArrayStackTests.swift | 2 +- Shell Sort/ShellSortExample.swift | 2 +- Skip-List/SkipList.swift | 2 +- .../Sources/Number.swift | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift index 61064c698..00ac6da97 100644 --- a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift +++ b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift @@ -6,7 +6,7 @@ extension String { for i in self.characters.indices { var j = i var found = true - for p in pattern.characters.indices{ + for p in pattern.characters.indices { if j == self.characters.endIndex || self[j] != pattern[p] { found = false break diff --git a/Brute-Force String Search/BruteForceStringSearch.swift b/Brute-Force String Search/BruteForceStringSearch.swift index 03a2dff13..016292304 100644 --- a/Brute-Force String Search/BruteForceStringSearch.swift +++ b/Brute-Force String Search/BruteForceStringSearch.swift @@ -6,7 +6,7 @@ extension String { for i in self.characters.indices { var j = i var found = true - for p in pattern.characters.indices{ + for p in pattern.characters.indices { if j == self.characters.endIndex || self[j] != pattern[p] { found = false break diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift index bde8fd9f9..3ac29301a 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -15,8 +15,8 @@ func ^^ (radix: Int, power: Int) -> Int { // Long Multiplication - O(n^2) 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))! } + 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) @@ -30,7 +30,7 @@ func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { product[i + num2Array.count] += carry } - return Int(product.reversed().map{ String($0) }.reduce("", +))! + return Int(product.reversed().map { String($0) }.reduce("", +))! } // Karatsuba Multiplication - O(n^log2(3)) diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift index b0f440809..0038494d3 100644 --- a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -22,7 +22,7 @@ public class RBTNode: CustomStringConvertible { // If the value is encapsulated by double pipes it is double black (This should not occur in a verified RBTree) if self.isRed { nodeValue = "(\(self.value!))" - } else if self.isBlack{ + } else if self.isBlack { nodeValue = "|\(self.value!)|" } else { nodeValue = "||\(self.value!)||" diff --git a/Rootish Array Stack/Tests/RootishArrayStackTests.swift b/Rootish Array Stack/Tests/RootishArrayStackTests.swift index 9ffc4ebb9..f0aaa8bca 100755 --- a/Rootish Array Stack/Tests/RootishArrayStackTests.swift +++ b/Rootish Array Stack/Tests/RootishArrayStackTests.swift @@ -1,7 +1,7 @@ import XCTest fileprivate extension RootishArrayStack { - func equal(toArray array: Array) -> Bool{ + func equal(toArray array: Array) -> Bool { for index in 0.. 0 else { continue } - while list[index - 1] > list[index] && index - 1 > 0 { + while list[index - 1] > list[index] && index - 1 > 0 { swap(&list[index - 1], &list[index]) index -= 1 } diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 1418656f3..52de1412e 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -283,7 +283,7 @@ extension SkipList { extension SkipList { - public func get(key:Key) -> Payload?{ + public func get(key:Key) -> Payload? { return search(key: key) } } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift index 7da1eee60..69afe76e4 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift @@ -37,7 +37,7 @@ 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] } + let c = a.indices.map { a[$0] * b[$0] } return c.reduce(Element.zero, { $0 + $1 }) } } From 44adf5a8f6ac5e14ca74b761fbdd01083100ccf8 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 10:01:33 +0500 Subject: [PATCH 0357/1039] [swiftlint] Fix rule: empty_parentheses_with_trailing_closure warning: Empty Parentheses with Trailing Closure Violation: When using trailing closures, empty parentheses should be avoided after the method call. --- All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift | 2 +- Bloom Filter/BloomFilter.playground/Contents.swift | 4 ++-- Bloom Filter/BloomFilter.swift | 4 ++-- Graph/Graph/AdjacencyListGraph.swift | 2 +- Graph/Graph/AdjacencyMatrixGraph.swift | 2 +- .../SSSP/BellmanFord.swift | 4 ++-- Trie/Trie/TrieTests/TrieTests.swift | 8 ++++---- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift index b1a870f2a..7bc78f326 100644 --- a/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift +++ b/All-Pairs Shortest Paths/APSP/APSP/FloydWarshall.swift @@ -175,7 +175,7 @@ public struct FloydWarshallResult: APSPResult where T: Hashable { 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 + let pathValues = path.map { vertex in vertex.data } return pathValues diff --git a/Bloom Filter/BloomFilter.playground/Contents.swift b/Bloom Filter/BloomFilter.playground/Contents.swift index d5e7d2dc6..06022c9b3 100644 --- a/Bloom Filter/BloomFilter.playground/Contents.swift +++ b/Bloom Filter/BloomFilter.playground/Contents.swift @@ -10,7 +10,7 @@ public class BloomFilter { } private func computeHashes(_ value: T) -> [Int] { - return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } + return hashFunctions.map { hashFunc in abs(hashFunc(value) % array.count) } } public func insert(_ element: T) { @@ -29,7 +29,7 @@ public class BloomFilter { let hashValues = computeHashes(value) // Map hashes to indices in the Bloom Filter - let results = hashValues.map() { hashValue in array[hashValue] } + let results = hashValues.map { hashValue in array[hashValue] } // All values must be 'true' for the query to return true diff --git a/Bloom Filter/BloomFilter.swift b/Bloom Filter/BloomFilter.swift index 03b5333f1..56c3be328 100644 --- a/Bloom Filter/BloomFilter.swift +++ b/Bloom Filter/BloomFilter.swift @@ -8,7 +8,7 @@ public class BloomFilter { } private func computeHashes(_ value: T) -> [Int] { - return hashFunctions.map() { hashFunc in abs(hashFunc(value) % array.count) } + return hashFunctions.map { hashFunc in abs(hashFunc(value) % array.count) } } public func insert(_ element: T) { @@ -27,7 +27,7 @@ public class BloomFilter { let hashValues = computeHashes(value) // Map hashes to indices in the Bloom Filter - let results = hashValues.map() { hashValue in array[hashValue] } + let results = hashValues.map { hashValue in array[hashValue] } // All values must be 'true' for the query to return true diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index edb754c97..3d86c78f7 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -64,7 +64,7 @@ open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashab open override func createVertex(_ data: T) -> Vertex { // check if the vertex already exists - let matchingVertices = vertices.filter() { vertex in + let matchingVertices = vertices.filter { vertex in return vertex.data == data } diff --git a/Graph/Graph/AdjacencyMatrixGraph.swift b/Graph/Graph/AdjacencyMatrixGraph.swift index 8f357bc8c..a9b43fb6d 100644 --- a/Graph/Graph/AdjacencyMatrixGraph.swift +++ b/Graph/Graph/AdjacencyMatrixGraph.swift @@ -46,7 +46,7 @@ open class AdjacencyMatrixGraph: AbstractGraph where T: Equatable, T: Hash // 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 + let matchingVertices = vertices.filter { vertex in return vertex.data == data } diff --git a/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift b/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift index 5b6670806..41be9759b 100644 --- a/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift +++ b/Single-Source Shortest Paths (Weighted)/SSSP/BellmanFord.swift @@ -41,7 +41,7 @@ extension BellmanFord: SSSPAlgorithm { for _ in 0 ..< vertices.count - 1 { var weightsUpdated = false - edges.forEach() { edge in + edges.forEach { edge in let weight = edge.weight! let relaxedDistance = weights[edge.from.index] + weight let nextVertexIdx = edge.to.index @@ -116,7 +116,7 @@ extension BellmanFordResult: SSSPResult { return nil } - return path.map() { vertex in + return path.map { vertex in return vertex.data } } diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 50a30a552..960b65791 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -101,7 +101,7 @@ class TrieTests: XCTestCase { /// Tests the performance of the insert method. func testInsertPerformance() { - self.measure() { + self.measure { let trie = Trie() for word in self.wordArray! { trie.insert(word: word) @@ -114,7 +114,7 @@ class TrieTests: XCTestCase { /// Tests the performance of the insert method when the words are already /// present. func testInsertAgainPerformance() { - self.measure() { + self.measure { for word in self.wordArray! { self.trie.insert(word: word) } @@ -123,7 +123,7 @@ class TrieTests: XCTestCase { /// Tests the performance of the contains method. func testContainsPerformance() { - self.measure() { + self.measure { for word in self.wordArray! { XCTAssertTrue(self.trie.contains(word: word)) } @@ -136,7 +136,7 @@ class TrieTests: XCTestCase { for word in self.wordArray! { self.trie.remove(word: word) } - self.measure() { + self.measure { self.insertWordsIntoTrie() for word in self.wordArray! { self.trie.remove(word: word) From 71c0e32fbc9794289199c3a8bbe0e1719a9b2ece Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Fri, 28 Apr 2017 10:05:34 +0500 Subject: [PATCH 0358/1039] [swiftlint] Fix rule: colon (i.e. should be next to identifier) warning: Colon Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals. --- .../BucketSort.playground/Sources/BucketSort.swift | 2 +- Bucket Sort/BucketSort.swift | 2 +- Convex Hull/Convex Hull/View.swift | 2 +- Deque/Deque-Optimized.swift | 2 +- Linked List/LinkedList.playground/Contents.swift | 2 +- Linked List/LinkedList.swift | 2 +- .../Red-Black Tree 2.playground/Sources/RBTree.swift | 8 ++++---- Skip-List/SkipList.swift | 2 +- Topological Sort/Graph.swift | 4 ++-- .../Topological Sort.playground/Sources/Graph.swift | 4 ++-- .../Sources/TopologicalSort1.swift | 2 +- Topological Sort/TopologicalSort1.swift | 2 +- 12 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift b/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift index e510e51b4..08962c0e1 100644 --- a/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift +++ b/Bucket Sort/BucketSort.playground/Sources/BucketSort.swift @@ -122,7 +122,7 @@ public struct InsertionSorter: Sorter { // MARK: Bucket ////////////////////////////////////// -public struct Bucket { +public struct Bucket { var elements: [T] let capacity: Int diff --git a/Bucket Sort/BucketSort.swift b/Bucket Sort/BucketSort.swift index ef72c67dc..ff36b372a 100644 --- a/Bucket Sort/BucketSort.swift +++ b/Bucket Sort/BucketSort.swift @@ -173,7 +173,7 @@ public struct InsertionSorter: Sorter { // MARK: Bucket ////////////////////////////////////// -public struct Bucket { +public struct Bucket { var elements: [T] let capacity: Int diff --git a/Convex Hull/Convex Hull/View.swift b/Convex Hull/Convex Hull/View.swift index 2d7157e6f..f9f9f6ef4 100644 --- a/Convex Hull/Convex Hull/View.swift +++ b/Convex Hull/Convex Hull/View.swift @@ -150,7 +150,7 @@ class View: UIView { let context = UIGraphicsGetCurrentContext() // Draw hull - let lineWidth:CGFloat = 2.0 + let lineWidth: CGFloat = 2.0 context!.setFillColor(UIColor.black.cgColor) context!.setLineWidth(lineWidth) diff --git a/Deque/Deque-Optimized.swift b/Deque/Deque-Optimized.swift index f565458c7..4eea01f1a 100644 --- a/Deque/Deque-Optimized.swift +++ b/Deque/Deque-Optimized.swift @@ -7,7 +7,7 @@ public struct Deque { private var array: [T?] private var head: Int private var capacity: Int - private let originalCapacity:Int + private let originalCapacity: Int public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 10677935a..08e14ef70 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -177,7 +177,7 @@ public final class LinkedList { if list.isEmpty { return } var (prev, next) = nodesBeforeAndAfter(index: index) var nodeToCopy = list.head - var newNode:Node? + var newNode: Node? while let node = nodeToCopy { newNode = Node(value: node.value) newNode?.previous = prev diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index a7ef9bf5e..783e650e8 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -129,7 +129,7 @@ public final class LinkedList { if list.isEmpty { return } var (prev, next) = nodesBeforeAndAfter(index: index) var nodeToCopy = list.head - var newNode:Node? + var newNode: Node? while let node = nodeToCopy { newNode = Node(value: node.value) newNode?.previous = prev diff --git a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift index 0038494d3..42a68237e 100644 --- a/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift +++ b/Red-Black Tree/Red-Black Tree 2.playground/Sources/RBTree.swift @@ -7,9 +7,9 @@ private enum RBTColor { public class RBTNode: CustomStringConvertible { fileprivate var color: RBTColor = .red public var value: T! = nil - public var right: RBTNode! - public var left: RBTNode! - public var parent: RBTNode! + public var right: RBTNode! + public var left: RBTNode! + public var parent: RBTNode! public var description: String { if self.value == nil { @@ -435,7 +435,7 @@ public class RBTree: CustomStringConvertible { private func property3() { let bDepth = blackDepth(root: self.root) - let leaves:[RBTNode] = getLeaves(n: self.root) + let leaves: [RBTNode] = getLeaves(n: self.root) for leaflet in leaves { var leaf = leaflet diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 52de1412e..14b5a4076 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -283,7 +283,7 @@ extension SkipList { extension SkipList { - public func get(key:Key) -> Payload? { + public func get(key: Key) -> Payload? { return search(key: key) } } diff --git a/Topological Sort/Graph.swift b/Topological Sort/Graph.swift index 1e1be6919..5032ba1d1 100644 --- a/Topological Sort/Graph.swift +++ b/Topological Sort/Graph.swift @@ -4,7 +4,7 @@ public class Graph: CustomStringConvertible { private(set) public var adjacencyLists: [Node : [Node]] public init() { - adjacencyLists = [Node : [Node]]() + adjacencyLists = [Node: [Node]]() } public func addNode(_ value: Node) -> Node { @@ -35,7 +35,7 @@ extension Graph { typealias InDegree = Int func calculateInDegreeOfNodes() -> [Node : InDegree] { - var inDegrees = [Node : InDegree]() + var inDegrees = [Node: InDegree]() for (node, _) in adjacencyLists { inDegrees[node] = 0 diff --git a/Topological Sort/Topological Sort.playground/Sources/Graph.swift b/Topological Sort/Topological Sort.playground/Sources/Graph.swift index 1e1be6919..5032ba1d1 100644 --- a/Topological Sort/Topological Sort.playground/Sources/Graph.swift +++ b/Topological Sort/Topological Sort.playground/Sources/Graph.swift @@ -4,7 +4,7 @@ public class Graph: CustomStringConvertible { private(set) public var adjacencyLists: [Node : [Node]] public init() { - adjacencyLists = [Node : [Node]]() + adjacencyLists = [Node: [Node]]() } public func addNode(_ value: Node) -> Node { @@ -35,7 +35,7 @@ extension Graph { typealias InDegree = Int func calculateInDegreeOfNodes() -> [Node : InDegree] { - var inDegrees = [Node : InDegree]() + var inDegrees = [Node: InDegree]() for (node, _) in adjacencyLists { inDegrees[node] = 0 diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index 0f9566f6a..4d3717fe6 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -23,7 +23,7 @@ extension Graph { return node }) - var visited = [Node : Bool]() + var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false } diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index 0f9566f6a..4d3717fe6 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -23,7 +23,7 @@ extension Graph { return node }) - var visited = [Node : Bool]() + var visited = [Node: Bool]() for (node, _) in adjacencyLists { visited[node] = false } From c4fdd035df77487756eee2389d18c89f9dc652cd Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 00:52:39 -0700 Subject: [PATCH 0359/1039] switch removeFirst to dropFirst we don't need a mutable copy of `array` to alter it, instead we can just drop the first element --- Select Minimum Maximum/Maximum.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Select Minimum Maximum/Maximum.swift b/Select Minimum Maximum/Maximum.swift index 991a0544e..c999504fb 100644 --- a/Select Minimum Maximum/Maximum.swift +++ b/Select Minimum Maximum/Maximum.swift @@ -3,13 +3,12 @@ */ func maximum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - var maximum = array.removeFirst() - for element in array { + var maximum = array.first! + for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum From 5e7fc5487f833fd96852d21d7f856c300956a62b Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 00:56:51 -0700 Subject: [PATCH 0360/1039] switch removeFirst to dropFirst we don't need to alter a mutable copy of `array`, instead we can just drop the first element. --- Select Minimum Maximum/Minimum.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Select Minimum Maximum/Minimum.swift b/Select Minimum Maximum/Minimum.swift index 90dfbd54b..88a562170 100644 --- a/Select Minimum Maximum/Minimum.swift +++ b/Select Minimum Maximum/Minimum.swift @@ -3,13 +3,12 @@ */ func minimum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - var minimum = array.removeFirst() - for element in array { + var minimum = array.first! + for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum From e15e1330417dcbe2222d2606a35dd5462eac6b2c Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 18:14:37 -0700 Subject: [PATCH 0361/1039] switch from removeFirst to stride for pairing We don't need to alter a local copy of `array` to generate each pair, instead use stride(from:to:by). In my simple [tests](https://gist.github.com/TheIronBorn/cc0507b36fddad291aa34674eb52ad8f), this can be up to an order of magnitude faster. --- Select Minimum Maximum/MinimumMaximumPairs.swift | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Select Minimum Maximum/MinimumMaximumPairs.swift b/Select Minimum Maximum/MinimumMaximumPairs.swift index b7deb570a..2c7b5bb5f 100644 --- a/Select Minimum Maximum/MinimumMaximumPairs.swift +++ b/Select Minimum Maximum/MinimumMaximumPairs.swift @@ -3,7 +3,6 @@ */ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { - var array = array guard !array.isEmpty else { return nil } @@ -11,13 +10,11 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { 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 hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } - - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) + let start = hasOddNumberOfItems ? 1 : 0 + 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 { @@ -35,6 +32,6 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { } } } - + return (minimum, maximum) } From b8d668d3883f79754aa83f5944a3e3d97e13d3a6 Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 18:19:43 -0700 Subject: [PATCH 0362/1039] update to match source --- Select Minimum Maximum/README.markdown | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Select Minimum Maximum/README.markdown b/Select Minimum Maximum/README.markdown index fa0f8fed8..3c29b5764 100644 --- a/Select Minimum Maximum/README.markdown +++ b/Select Minimum Maximum/README.markdown @@ -24,26 +24,24 @@ Here is a simple implementation in Swift: ```swift func minimum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - var minimum = array.removeFirst() - for element in array { + var minimum = array.first! + for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum } func maximum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - var maximum = array.removeFirst() - for element in array { + var maximum = array.first! + for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum @@ -99,7 +97,6 @@ Here is a simple implementation in Swift: ```swift func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { - var array = array guard !array.isEmpty else { return nil } @@ -107,13 +104,12 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { 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 hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } + let start = hasOddNumberOfItems ? 1 : 0 + for i in stride(from: start, to: array.count, by: 2) { + let pair = (array[i], array[i+1]) - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 From 5ddf933c48da612a9489c77b095496b0c80c1b66 Mon Sep 17 00:00:00 2001 From: TheIronBorn Date: Sat, 29 Apr 2017 18:21:35 -0700 Subject: [PATCH 0363/1039] update to match source --- .../Contents.swift | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index 182060805..427ccdb9e 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -1,12 +1,11 @@ // Compare each item to find minimum func minimum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - - var minimum = array.removeFirst() - for element in array { + + var minimum = array.first! + for element in array.dropFirst() { minimum = element < minimum ? element : minimum } return minimum @@ -14,13 +13,12 @@ func minimum(_ array: [T]) -> T? { // Compare each item to find maximum func maximum(_ array: [T]) -> T? { - var array = array guard !array.isEmpty else { return nil } - - var maximum = array.removeFirst() - for element in array { + + var maximum = array.first! + for element in array.dropFirst() { maximum = element > maximum ? element : maximum } return maximum @@ -28,22 +26,19 @@ func maximum(_ array: [T]) -> T? { // Compare in pairs to find minimum and maximum func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { - var array = array 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 hasOddNumberOfItems = array.count % 2 != 0 - if hasOddNumberOfItems { - array.removeFirst() - } - - while !array.isEmpty { - let pair = (array.removeFirst(), array.removeFirst()) - + let start = hasOddNumberOfItems ? 1 : 0 + 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 @@ -60,7 +55,7 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { } } } - + return (minimum, maximum) } From 3f156498b0cb043f103eef22216f2e4e9df6edd6 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 1 May 2017 01:03:09 +0500 Subject: [PATCH 0364/1039] Fix alignment by adding an additional tab --- Tree/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tree/README.markdown b/Tree/README.markdown index 440d9c9a4..566864a8f 100644 --- a/Tree/README.markdown +++ b/Tree/README.markdown @@ -153,7 +153,7 @@ 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 + 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 From 32457ce5aca5bcdee4acc1f8d6f6c0c6a075daba Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 1 May 2017 02:03:34 +0500 Subject: [PATCH 0365/1039] Fix misindented return statement --- Trie/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Trie/ReadMe.md b/Trie/ReadMe.md index 7caa927a7..356f6887e 100644 --- a/Trie/ReadMe.md +++ b/Trie/ReadMe.md @@ -46,7 +46,7 @@ func contains(word: String) -> Bool { if currentIndex == characters.count && currentNode.isTerminating { return true } else { - return false + return false } } ``` From 09f2c8fb8564bd956beb1a067b6ad21255bad97c Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 1 May 2017 05:25:13 +0500 Subject: [PATCH 0366/1039] [swiftlint] Fix rule: force_cast (Force casts should be avoided) --- Trie/Trie/TrieTests/TrieTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Trie/Trie/TrieTests/TrieTests.swift b/Trie/Trie/TrieTests/TrieTests.swift index 960b65791..b69c5666e 100644 --- a/Trie/Trie/TrieTests/TrieTests.swift +++ b/Trie/Trie/TrieTests/TrieTests.swift @@ -164,8 +164,8 @@ class TrieTests: XCTestCase { 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) + let trieCopy = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? Trie + XCTAssertEqual(trieCopy?.count, trie.count) } From b1319ce90d5288e20ee02b56390c61895d1d7765 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:23:06 +0500 Subject: [PATCH 0367/1039] [swiftlint] Fix violation: unused_closure_parameter warning: Unused Closure Parameter Violation: Unused parameters in a closure should be replaced with _. --- B-Tree/Tests/Tests/BTreeTests.swift | 2 +- .../Topological Sort.playground/Sources/TopologicalSort1.swift | 2 +- .../Topological Sort.playground/Sources/TopologicalSort2.swift | 2 +- Topological Sort/TopologicalSort1.swift | 2 +- Topological Sort/TopologicalSort2.swift | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/B-Tree/Tests/Tests/BTreeTests.swift b/B-Tree/Tests/Tests/BTreeTests.swift index c8db17fa3..f2dac7511 100644 --- a/B-Tree/Tests/Tests/BTreeTests.swift +++ b/B-Tree/Tests/Tests/BTreeTests.swift @@ -31,7 +31,7 @@ class BTreeTests: XCTestCase { } func testInorderTraversalOfEmptyTree() { - bTree.traverseKeysInOrder { i in + bTree.traverseKeysInOrder { _ in XCTFail("Inorder travelsal fail.") } } diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift index 4d3717fe6..2ad9b51a0 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort1.swift @@ -19,7 +19,7 @@ extension Graph { let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 - }).map({ node, indegree in + }).map({ node, _ in return node }) diff --git a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift index f4c1cdd6f..589801d33 100644 --- a/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift +++ b/Topological Sort/Topological Sort.playground/Sources/TopologicalSort2.swift @@ -8,7 +8,7 @@ extension Graph { // topologically sorted list. var leaders = nodes.filter({ _, indegree in return indegree == 0 - }).map({ node, indegree in + }).map({ node, _ in return node }) diff --git a/Topological Sort/TopologicalSort1.swift b/Topological Sort/TopologicalSort1.swift index 4d3717fe6..2ad9b51a0 100644 --- a/Topological Sort/TopologicalSort1.swift +++ b/Topological Sort/TopologicalSort1.swift @@ -19,7 +19,7 @@ extension Graph { let startNodes = calculateInDegreeOfNodes().filter({ _, indegree in return indegree == 0 - }).map({ node, indegree in + }).map({ node, _ in return node }) diff --git a/Topological Sort/TopologicalSort2.swift b/Topological Sort/TopologicalSort2.swift index f4c1cdd6f..589801d33 100644 --- a/Topological Sort/TopologicalSort2.swift +++ b/Topological Sort/TopologicalSort2.swift @@ -8,7 +8,7 @@ extension Graph { // topologically sorted list. var leaders = nodes.filter({ _, indegree in return indegree == 0 - }).map({ node, indegree in + }).map({ node, _ in return node }) From 9107542b7753210cef8eaf982373db377f6a8a62 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:25:35 +0500 Subject: [PATCH 0368/1039] [swiftlint] Fix violation: redundant_discardable_let warning: Redundant Discardable Let Violation: Prefer `_ = foo()` over `let _ = foo()` when discarding a result from a function. --- Breadth-First Search/Tests/Graph.swift | 2 +- Palindromes/Test/Test/Test.swift | 6 +++--- Treap/TreapCollectionType.swift | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Breadth-First Search/Tests/Graph.swift b/Breadth-First Search/Tests/Graph.swift index 5e0837160..a8c34b3f6 100644 --- a/Breadth-First Search/Tests/Graph.swift +++ b/Breadth-First Search/Tests/Graph.swift @@ -86,7 +86,7 @@ public class Graph: CustomStringConvertible, Equatable { let duplicated = Graph() for node in nodes { - let _ = duplicated.addNode(node.label) + _ = duplicated.addNode(node.label) } for node in nodes { diff --git a/Palindromes/Test/Test/Test.swift b/Palindromes/Test/Test/Test.swift index e86a40cfb..1dd79ea97 100644 --- a/Palindromes/Test/Test/Test.swift +++ b/Palindromes/Test/Test/Test.swift @@ -29,9 +29,9 @@ class PalindromeTests: XCTestCase { // This is an example of a performance test case. self.measure { // Put the code you want to measure the time of here. - let _ = isPalindrome("abbcbba") - let _ = isPalindrome("asdkfaksjdfasjkdfhaslkjdfakjsdfhakljsdhflkjasdfhkasdjhfklajsdfhkljasdf") - let _ = isPalindrome("abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa") + _ = isPalindrome("abbcbba") + _ = isPalindrome("asdkfaksjdfasjkdfhaslkjdfakjsdfhakljsdhflkjasdfhkasdjhfklajsdfhkljasdf") + _ = isPalindrome("abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa") } } diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index de40464d1..9f7f81905 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -50,7 +50,7 @@ extension Treap: MutableCollection { mutating set { guard let value = newValue else { - let _ = try? self.delete(key: key) + _ = try? self.delete(key: key) return } From c67a277487e3611ad51b0c88855540d3f56f58bb Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:34:24 +0500 Subject: [PATCH 0369/1039] [swiftlint] Fix violation: operator_whitespace warning: Operator Function Whitespace Violation: Operators should be surrounded by a single whitespace when defining them. Apple has also used spacing in The Swift Programming Language book https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html#//apple_ref/doc/uid/TP40014097-CH27-ID42 --- QuadTree/Tests/Tests/Tests.swift | 2 +- .../Sources/Matrix.swift | 2 +- .../Sources/Number.swift | 6 +++--- Treap/TreapCollectionType.swift | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/QuadTree/Tests/Tests/Tests.swift b/QuadTree/Tests/Tests/Tests.swift index b7bcda4e6..b408c4f7e 100644 --- a/QuadTree/Tests/Tests/Tests.swift +++ b/QuadTree/Tests/Tests/Tests.swift @@ -12,7 +12,7 @@ extension Point: Equatable { } -public func ==(lhs: Point, rhs: Point) -> Bool { +public func == (lhs: Point, rhs: Point) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift index c13b3eeee..ccfa58b09 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift @@ -19,7 +19,7 @@ public struct Matrix { public struct Size: Equatable { let rows: Int, columns: Int - public static func ==(lhs: Size, rhs: Size) -> Bool { + public static func == (lhs: Size, rhs: Size) -> Bool { return lhs.columns == rhs.columns && lhs.rows == rhs.rows } } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift index 69afe76e4..d53ef75bd 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Number.swift @@ -13,12 +13,12 @@ public protocol Number: Multipliable, Addable { } public protocol Addable { - static func +(lhs: Self, rhs: Self) -> Self - static func -(lhs: Self, rhs: Self) -> Self + static func + (lhs: Self, rhs: Self) -> Self + static func - (lhs: Self, rhs: Self) -> Self } public protocol Multipliable { - static func *(lhs: Self, rhs: Self) -> Self + static func * (lhs: Self, rhs: Self) -> Self } extension Int: Number { diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index 9f7f81905..7292c5f0a 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -85,7 +85,7 @@ extension Treap: MutableCollection { public struct TreapIndex: Comparable { - public static func <(lhs: TreapIndex, rhs: TreapIndex) -> Bool { + public static func < (lhs: TreapIndex, rhs: TreapIndex) -> Bool { return lhs.keyIndex < rhs.keyIndex } From 18c7b435cec0eafb657f28f7c80345d8a7aa513a Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:41:07 +0500 Subject: [PATCH 0370/1039] [swiftlint] Fix violation: Colons should be next to the identifier warning: Colon Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals. --- Bucket Sort/BucketSort.swift | 4 ++-- Skip-List/SkipList.swift | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Bucket Sort/BucketSort.swift b/Bucket Sort/BucketSort.swift index ff36b372a..5845819f2 100644 --- a/Bucket Sort/BucketSort.swift +++ b/Bucket Sort/BucketSort.swift @@ -23,7 +23,7 @@ import Foundation // FIXME: comparison operators with optionals were removed from the Swift Standard Libary. // Consider refactoring the code to use the non-optional operators. -fileprivate func < (lhs: T?, rhs: T?) -> Bool { +fileprivate func < (lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): return l < r @@ -36,7 +36,7 @@ fileprivate func < (lhs: T?, rhs: T?) -> Bool { // FIXME: comparison operators with optionals were removed from the Swift Standard Libary. // Consider refactoring the code to use the non-optional operators. -fileprivate func >= (lhs: T?, rhs: T?) -> Bool { +fileprivate func >= (lhs: T?, rhs: T?) -> Bool { switch (lhs, rhs) { case let (l?, r?): return l >= r diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index 14b5a4076..e844f9959 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -71,10 +71,10 @@ private func coinFlip() -> Bool { public class DataNode { public typealias Node = DataNode - var data : Payload? - fileprivate var key : Key? - var next : Node? - var down : Node? + var data: Payload? + fileprivate var key: Key? + var next: Node? + var down: Node? public init(key: Key, data: Payload) { self.key = key @@ -102,8 +102,8 @@ open class SkipList { extension SkipList { func findNode(key: Key) -> Node? { - var currentNode : Node? = head - var isFound : Bool = false + var currentNode: Node? = head + var isFound: Bool = false while !isFound { if let node = currentNode { From e3a4494138ca4776aab23bed0428b3e4063395ca Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:47:57 +0500 Subject: [PATCH 0371/1039] [swiftlint] Fix violation: Computed properties should avoid using get Rule: implicit_getter warning: Implicit Getter Violation: Computed read-only properties should avoid using the get keyword. --- Graph/Graph/AdjacencyListGraph.swift | 58 ++++++++++++-------------- Graph/Graph/AdjacencyMatrixGraph.swift | 44 +++++++++---------- Graph/Graph/Edge.swift | 19 ++++----- Graph/Graph/Graph.swift | 12 ++---- Graph/Graph/Vertex.swift | 8 +--- Treap/Treap.swift | 31 ++++++-------- Treap/TreapMergeSplit.swift | 4 +- 7 files changed, 71 insertions(+), 105 deletions(-) diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index 3d86c78f7..57fd75fed 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -37,29 +37,25 @@ open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashab } open override var vertices: [Vertex] { - get { - var vertices = [Vertex]() - for edgeList in adjacencyList { - vertices.append(edgeList.vertex) - } - return vertices + var vertices = [Vertex]() + for edgeList in adjacencyList { + vertices.append(edgeList.vertex) } + return vertices } open override var edges: [Edge] { - get { - var allEdges = Set>() - for edgeList in adjacencyList { - guard let edges = edgeList.edges else { - continue - } + var allEdges = Set>() + for edgeList in adjacencyList { + guard let edges = edgeList.edges else { + continue + } - for edge in edges { - allEdges.insert(edge) - } + for edge in edges { + allEdges.insert(edge) } - return Array(allEdges) } + return Array(allEdges) } open override func createVertex(_ data: T) -> Vertex { @@ -114,27 +110,25 @@ open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashab } open override var description: String { - get { - var rows = [String]() - for edgeList in adjacencyList { + var rows = [String]() + for edgeList in adjacencyList { - guard let edges = edgeList.edges else { - continue - } + 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) + var row = [String]() + for edge in edges { + var value = "\(edge.to.data)" + if edge.weight != nil { + value = "(\(value): \(edge.weight!))" } - - rows.append("\(edgeList.vertex.data) -> [\(row.joined(separator: ", "))]") + row.append(value) } - return rows.joined(separator: "\n") + rows.append("\(edgeList.vertex.data) -> [\(row.joined(separator: ", "))]") } + + return rows.joined(separator: "\n") } } diff --git a/Graph/Graph/AdjacencyMatrixGraph.swift b/Graph/Graph/AdjacencyMatrixGraph.swift index a9b43fb6d..1b12790d8 100644 --- a/Graph/Graph/AdjacencyMatrixGraph.swift +++ b/Graph/Graph/AdjacencyMatrixGraph.swift @@ -23,23 +23,19 @@ open class AdjacencyMatrixGraph: AbstractGraph where T: Equatable, T: Hash } open override var vertices: [Vertex] { - get { - return _vertices - } + return _vertices } open override var edges: [Edge] { - get { - 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)) - } + 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 } + return edges } // Adds a new vertex to the matrix. @@ -96,23 +92,21 @@ open class AdjacencyMatrixGraph: AbstractGraph where T: Equatable, T: Hash } open override var description: String { - get { - var grid = [String]() - let n = self.adjacencyMatrix.count - for i in 0..: Equatable where T: Equatable, T: Hashable { extension Edge: CustomStringConvertible { public var description: String { - get { - guard let unwrappedWeight = weight else { - return "\(from.description) -> \(to.description)" - } - return "\(from.description) -(\(unwrappedWeight))-> \(to.description)" + guard let unwrappedWeight = weight else { + return "\(from.description) -> \(to.description)" } + return "\(from.description) -(\(unwrappedWeight))-> \(to.description)" } } @@ -32,15 +30,12 @@ extension Edge: CustomStringConvertible { extension Edge: Hashable { public var hashValue: Int { - get { - var string = "\(from.description)\(to.description)" - if weight != nil { - string.append("\(weight!)") - } - return string.hashValue + var string = "\(from.description)\(to.description)" + if weight != nil { + string.append("\(weight!)") } + return string.hashValue } - } public func == (lhs: Edge, rhs: Edge) -> Bool { diff --git a/Graph/Graph/Graph.swift b/Graph/Graph/Graph.swift index 2ad91608b..13d6802b9 100644 --- a/Graph/Graph/Graph.swift +++ b/Graph/Graph/Graph.swift @@ -21,21 +21,15 @@ open class AbstractGraph: CustomStringConvertible where T: Equatable, T: Hash } open var description: String { - get { - fatalError("abstract property accessed") - } + fatalError("abstract property accessed") } open var vertices: [Vertex] { - get { - fatalError("abstract property accessed") - } + fatalError("abstract property accessed") } open var edges: [Edge] { - get { - fatalError("abstract property accessed") - } + fatalError("abstract property accessed") } // Adds a new vertex to the matrix. diff --git a/Graph/Graph/Vertex.swift b/Graph/Graph/Vertex.swift index 43cabcd1f..42a7dad7b 100644 --- a/Graph/Graph/Vertex.swift +++ b/Graph/Graph/Vertex.swift @@ -17,9 +17,7 @@ public struct Vertex: Equatable where T: Equatable, T: Hashable { extension Vertex: CustomStringConvertible { public var description: String { - get { - return "\(index): \(data)" - } + return "\(index): \(data)" } } @@ -27,9 +25,7 @@ extension Vertex: CustomStringConvertible { extension Vertex: Hashable { public var hashValue: Int { - get { - return "\(data)\(index)".hashValue - } + return "\(data)\(index)".hashValue } } diff --git a/Treap/Treap.swift b/Treap/Treap.swift index 478f248df..6e80abfb2 100644 --- a/Treap/Treap.swift +++ b/Treap/Treap.swift @@ -63,27 +63,22 @@ public indirect enum Treap { } public var depth: Int { - get { - 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 - } - + 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 { - get { - return Treap.countHelper(self) - } + return Treap.countHelper(self) } fileprivate static func countHelper(_ treap: Treap) -> Int { diff --git a/Treap/TreapMergeSplit.swift b/Treap/TreapMergeSplit.swift index 660bd4932..34cfec3d2 100644 --- a/Treap/TreapMergeSplit.swift +++ b/Treap/TreapMergeSplit.swift @@ -94,9 +94,7 @@ internal func merge(_ left: Treap, right extension Treap: CustomStringConvertible { public var description: String { - get { - return Treap.descHelper(self, indent: 0) - } + return Treap.descHelper(self, indent: 0) } fileprivate static func descHelper(_ treap: Treap, indent: Int) -> String { From 9af41f20ed8318739bd4f1d582a6789fe650e9b5 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:49:49 +0500 Subject: [PATCH 0372/1039] [swiftlint] Fix violation: trailing_whitespace --- Array2D/Array2D.playground/Contents.swift | 4 +- Array2D/Array2D.swift | 4 +- B-Tree/BTree.playground/Sources/BTree.swift | 108 +++++++------- B-Tree/BTree.swift | 108 +++++++------- B-Tree/Tests/Tests/BTreeNodeTests.swift | 18 +-- B-Tree/Tests/Tests/BTreeTests.swift | 112 +++++++------- .../Contents.swift | 2 +- .../Sources/Comb Sort.swift | 4 +- Comb Sort/Comb Sort.swift | 4 +- Comb Sort/Tests/CombSortTests.swift | 2 +- Convex Hull/Convex Hull/AppDelegate.swift | 8 +- Convex Hull/Convex Hull/View.swift | 80 +++++----- .../FixedSizeArray.playground/Contents.swift | 10 +- Graph/Graph.playground/Contents.swift | 2 +- .../HashSet.playground/Sources/HashSet.swift | 16 +- .../Sources/HashTable.swift | 28 ++-- .../Contents.swift | 10 +- Heap/Heap.swift | 4 +- Heap/Tests/HeapTests.swift | 4 +- Huffman Coding/Huffman.swift | 34 ++--- Huffman Coding/NSData+Bits.swift | 8 +- .../Contents.swift | 16 +- .../KaratsubaMultiplication.swift | 12 +- Knuth-Morris-Pratt/KnuthMorrisPratt.swift | 26 ++-- .../LinkedList.playground/Contents.swift | 62 ++++---- Linked List/LinkedList.swift | 62 ++++---- Linked List/Tests/LinkedListTests.swift | 18 +-- .../Sources/MRPrimality.swift | 28 ++-- Miller-Rabin Primality Test/MRPrimality.swift | 28 ++-- .../Contents.swift | 8 +- .../OrderedArray.playground/Contents.swift | 2 +- .../Palindromes.playground/Contents.swift | 8 +- Palindromes/Palindromes.swift | 8 +- Palindromes/Test/Palindromes.swift | 8 +- Palindromes/Test/Test/Test.swift | 18 +-- .../Sources/QuadTree.swift | 88 +++++------ QuadTree/Tests/Tests/Tests.swift | 34 ++--- .../Sources/radixSort.swift | 18 +-- Radix Sort/RadixSortExample.swift | 12 +- Radix Sort/radixSort.swift | 18 +-- .../Contents.swift | 2 +- .../Sources/RBTree.swift | 138 +++++++++--------- .../RLE.playground/Contents.swift | 14 +- .../RLE.playground/Sources/RLE.swift | 12 +- .../SegmentTree.playground/Contents.swift | 18 +-- Segment Tree/SegmentTree.swift | 16 +- .../MinimumMaximumPairs.swift | 2 +- .../Contents.swift | 14 +- Shell Sort/ShellSortExample.swift | 10 +- Shortest Path (Unweighted)/Tests/Graph.swift | 32 ++-- .../ShuntingYard.playground/Contents.swift | 52 +++---- .../Sources/Stack.swift | 14 +- Shunting Yard/ShuntingYard.swift | 52 +++---- Skip-List/SkipList.swift | 84 +++++------ .../Sources/Matrix.swift | 88 +++++------ .../TST.playground/Sources/Utils.swift | 8 +- .../Tests/TernarySearchTreeTests.swift | 18 +-- Ternary Search Tree/Utils.swift | 8 +- .../Sources/ThreadedBinaryTree.swift | 52 +++---- Treap/Treap.swift | 18 +-- Treap/Treap/TreapTests/TreapTests.swift | 12 +- Treap/TreapCollectionType.swift | 34 ++--- Treap/TreapMergeSplit.swift | 14 +- Trie/Trie/Trie/Trie.swift | 16 +- Trie/Trie/TrieUITests/TrieUITests.swift | 12 +- Z-Algorithm/ZAlgorithm.swift | 22 +-- .../ZetaAlgorithm.playground/Contents.swift | 34 ++--- Z-Algorithm/ZetaAlgorithm.swift | 12 +- 68 files changed, 926 insertions(+), 926 deletions(-) diff --git a/Array2D/Array2D.playground/Contents.swift b/Array2D/Array2D.playground/Contents.swift index d088c99af..1a6a439bd 100644 --- a/Array2D/Array2D.playground/Contents.swift +++ b/Array2D/Array2D.playground/Contents.swift @@ -7,13 +7,13 @@ 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))") diff --git a/Array2D/Array2D.swift b/Array2D/Array2D.swift index df4822916..caff8373c 100644 --- a/Array2D/Array2D.swift +++ b/Array2D/Array2D.swift @@ -7,13 +7,13 @@ 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))") diff --git a/B-Tree/BTree.playground/Sources/BTree.swift b/B-Tree/BTree.playground/Sources/BTree.swift index 52cda4e43..2693eb308 100644 --- a/B-Tree/BTree.playground/Sources/BTree.swift +++ b/B-Tree/BTree.playground/Sources/BTree.swift @@ -33,23 +33,23 @@ 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) @@ -62,7 +62,7 @@ class BTreeNode { // MARK: BTreeNode extesnion: Searching extension BTreeNode { - + /** * Returns the value for a given `key`, returns nil if the `key` is not found. * @@ -71,11 +71,11 @@ extension BTreeNode { */ 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] { @@ -89,7 +89,7 @@ extension BTreeNode { // MARK: BTreeNode extension: Travelsals extension BTreeNode { - + /** * Traverses the keys in order, executes `process` for every key. * @@ -101,7 +101,7 @@ extension BTreeNode { children?[i].traverseKeysInOrder(process) process(keys[i]) } - + children?.last?.traverseKeysInOrder(process) } } @@ -109,7 +109,7 @@ extension BTreeNode { // MARK: BTreeNode extension: Insertion extension BTreeNode { - + /** * Inserts `value` for `key` to the node, or to one if its descendants. * @@ -119,16 +119,16 @@ extension BTreeNode { */ func insert(_ value: Value, for key: Key) { var index = keys.startIndex - + while index < keys.endIndex && keys[index] < key { index = (index + 1) } - + if index < keys.endIndex && keys[index] == key { values[index] = value return } - + if isLeaf { keys.insert(key, at: index) values.insert(value, at: index) @@ -140,7 +140,7 @@ extension BTreeNode { } } } - + /** * Splits `child` at `index`. * The key-value pair at `index` gets moved up to the parent node, @@ -156,7 +156,7 @@ extension BTreeNode { 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)]), @@ -164,9 +164,9 @@ extension BTreeNode { ) 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))] @@ -198,7 +198,7 @@ extension BTreeNode { return children!.last!.inorderPredecessor } } - + /** * Removes `key` and the value associated with it from the node * or one of its descendants. @@ -208,11 +208,11 @@ extension BTreeNode { */ 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) @@ -229,7 +229,7 @@ extension BTreeNode { } } else if key < keys[index] { // We should go to left child... - + if let leftChild = children?[index] { leftChild.remove(key) if leftChild.numberOfKeys < owner.order { @@ -240,7 +240,7 @@ extension BTreeNode { } } else { // We should go to right child... - + if let rightChild = children?[(index + 1)] { rightChild.remove(key) if rightChild.numberOfKeys < owner.order { @@ -251,7 +251,7 @@ extension BTreeNode { } } } - + /** * Fixes `childWithTooFewKeys` by either moving a key to it from * one of its neighbouring nodes, or by merging. @@ -264,7 +264,7 @@ extension BTreeNode { * - 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 { @@ -275,7 +275,7 @@ extension BTreeNode { merge(child: child, atIndex: index, to: .right) } } - + /** * Moves the key at the specified `index` from `node` to * the `targetNode` at `position` @@ -301,7 +301,7 @@ extension BTreeNode { 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) @@ -316,7 +316,7 @@ extension BTreeNode { } } } - + /** * Merges `child` at `position` to the node at the `position`. * @@ -329,33 +329,33 @@ extension BTreeNode { 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! @@ -374,18 +374,18 @@ extension BTreeNode { */ var inorderArrayFromKeys: [Key] { var array = [Key] () - + for i in 0.. { * 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 * @@ -484,7 +484,7 @@ extension BTree { guard rootNode.numberOfKeys > 0 else { return nil } - + return rootNode.value(for: key) } } @@ -501,12 +501,12 @@ extension BTree { */ 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. * @@ -515,7 +515,7 @@ extension BTree { */ private func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 - + let newRoot = BTreeNode( owner: self, keys: [rootNode.keys[middleIndexOfOldRoot]], @@ -524,7 +524,7 @@ extension BTree { ) 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)]), @@ -532,7 +532,7 @@ extension BTree { ) 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))] @@ -541,7 +541,7 @@ extension BTree { rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1)) ) } - + newRoot.children!.append(newRightChild) rootNode = newRoot } @@ -560,9 +560,9 @@ extension BTree { guard rootNode.numberOfKeys > 0 else { return } - + rootNode.remove(key) - + if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { rootNode = rootNode.children!.first! } diff --git a/B-Tree/BTree.swift b/B-Tree/BTree.swift index 52cda4e43..2693eb308 100644 --- a/B-Tree/BTree.swift +++ b/B-Tree/BTree.swift @@ -33,23 +33,23 @@ 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) @@ -62,7 +62,7 @@ class BTreeNode { // MARK: BTreeNode extesnion: Searching extension BTreeNode { - + /** * Returns the value for a given `key`, returns nil if the `key` is not found. * @@ -71,11 +71,11 @@ extension BTreeNode { */ 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] { @@ -89,7 +89,7 @@ extension BTreeNode { // MARK: BTreeNode extension: Travelsals extension BTreeNode { - + /** * Traverses the keys in order, executes `process` for every key. * @@ -101,7 +101,7 @@ extension BTreeNode { children?[i].traverseKeysInOrder(process) process(keys[i]) } - + children?.last?.traverseKeysInOrder(process) } } @@ -109,7 +109,7 @@ extension BTreeNode { // MARK: BTreeNode extension: Insertion extension BTreeNode { - + /** * Inserts `value` for `key` to the node, or to one if its descendants. * @@ -119,16 +119,16 @@ extension BTreeNode { */ func insert(_ value: Value, for key: Key) { var index = keys.startIndex - + while index < keys.endIndex && keys[index] < key { index = (index + 1) } - + if index < keys.endIndex && keys[index] == key { values[index] = value return } - + if isLeaf { keys.insert(key, at: index) values.insert(value, at: index) @@ -140,7 +140,7 @@ extension BTreeNode { } } } - + /** * Splits `child` at `index`. * The key-value pair at `index` gets moved up to the parent node, @@ -156,7 +156,7 @@ extension BTreeNode { 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)]), @@ -164,9 +164,9 @@ extension BTreeNode { ) 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))] @@ -198,7 +198,7 @@ extension BTreeNode { return children!.last!.inorderPredecessor } } - + /** * Removes `key` and the value associated with it from the node * or one of its descendants. @@ -208,11 +208,11 @@ extension BTreeNode { */ 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) @@ -229,7 +229,7 @@ extension BTreeNode { } } else if key < keys[index] { // We should go to left child... - + if let leftChild = children?[index] { leftChild.remove(key) if leftChild.numberOfKeys < owner.order { @@ -240,7 +240,7 @@ extension BTreeNode { } } else { // We should go to right child... - + if let rightChild = children?[(index + 1)] { rightChild.remove(key) if rightChild.numberOfKeys < owner.order { @@ -251,7 +251,7 @@ extension BTreeNode { } } } - + /** * Fixes `childWithTooFewKeys` by either moving a key to it from * one of its neighbouring nodes, or by merging. @@ -264,7 +264,7 @@ extension BTreeNode { * - 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 { @@ -275,7 +275,7 @@ extension BTreeNode { merge(child: child, atIndex: index, to: .right) } } - + /** * Moves the key at the specified `index` from `node` to * the `targetNode` at `position` @@ -301,7 +301,7 @@ extension BTreeNode { 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) @@ -316,7 +316,7 @@ extension BTreeNode { } } } - + /** * Merges `child` at `position` to the node at the `position`. * @@ -329,33 +329,33 @@ extension BTreeNode { 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! @@ -374,18 +374,18 @@ extension BTreeNode { */ var inorderArrayFromKeys: [Key] { var array = [Key] () - + for i in 0.. { * 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 * @@ -484,7 +484,7 @@ extension BTree { guard rootNode.numberOfKeys > 0 else { return nil } - + return rootNode.value(for: key) } } @@ -501,12 +501,12 @@ extension BTree { */ 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. * @@ -515,7 +515,7 @@ extension BTree { */ private func splitRoot() { let middleIndexOfOldRoot = rootNode.numberOfKeys / 2 - + let newRoot = BTreeNode( owner: self, keys: [rootNode.keys[middleIndexOfOldRoot]], @@ -524,7 +524,7 @@ extension BTree { ) 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)]), @@ -532,7 +532,7 @@ extension BTree { ) 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))] @@ -541,7 +541,7 @@ extension BTree { rootNode.children!.indices.suffix(from: (middleIndexOfOldRoot + 1)) ) } - + newRoot.children!.append(newRightChild) rootNode = newRoot } @@ -560,9 +560,9 @@ extension BTree { guard rootNode.numberOfKeys > 0 else { return } - + rootNode.remove(key) - + if rootNode.numberOfKeys == 0 && !rootNode.isLeaf { rootNode = rootNode.children!.first! } diff --git a/B-Tree/Tests/Tests/BTreeNodeTests.swift b/B-Tree/Tests/Tests/BTreeNodeTests.swift index fd3ba10e8..8eff926b5 100644 --- a/B-Tree/Tests/Tests/BTreeNodeTests.swift +++ b/B-Tree/Tests/Tests/BTreeNodeTests.swift @@ -9,44 +9,44 @@ import XCTest class BTreeNodeTests: XCTestCase { - + let owner = BTree(order: 2)! var root: BTreeNode! var leftChild: BTreeNode! var rightChild: BTreeNode! - + 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) } diff --git a/B-Tree/Tests/Tests/BTreeTests.swift b/B-Tree/Tests/Tests/BTreeTests.swift index f2dac7511..1e94bfd7d 100644 --- a/B-Tree/Tests/Tests/BTreeTests.swift +++ b/B-Tree/Tests/Tests/BTreeTests.swift @@ -10,201 +10,201 @@ import XCTest class BTreeTests: XCTestCase { var bTree: BTree! - + 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) } } @@ -221,7 +221,7 @@ extension BTreeNode { } else if !root && numberOfKeys < owner.order { throw BTreeError.tooFewNodes } - + if !isLeaf { for child in children! { try child.checkBalance(isRoot: false) @@ -234,14 +234,14 @@ 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) } diff --git a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift index 00ac6da97..b9f2b1432 100644 --- a/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift +++ b/Brute-Force String Search/BruteForceStringSearch.playground/Contents.swift @@ -2,7 +2,7 @@ extension String { func indexOf(_ pattern: String) -> String.Index? { - + for i in self.characters.indices { var j = i var found = true diff --git a/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift b/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift index b6e85fa2b..f7c4eec61 100644 --- a/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift +++ b/Comb Sort/Comb Sort.playground/Sources/Comb Sort.swift @@ -11,13 +11,13 @@ 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] { diff --git a/Comb Sort/Comb Sort.swift b/Comb Sort/Comb Sort.swift index b6e85fa2b..f7c4eec61 100644 --- a/Comb Sort/Comb Sort.swift +++ b/Comb Sort/Comb Sort.swift @@ -11,13 +11,13 @@ 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] { diff --git a/Comb Sort/Tests/CombSortTests.swift b/Comb Sort/Tests/CombSortTests.swift index 1bcc67fd0..b9287f84a 100644 --- a/Comb Sort/Tests/CombSortTests.swift +++ b/Comb Sort/Tests/CombSortTests.swift @@ -16,7 +16,7 @@ class CombSortTests: XCTestCase { super.setUp() sequence = [2, 32, 9, -1, 89, 101, 55, -10, -12, 67] } - + override func tearDown() { super.tearDown() } diff --git a/Convex Hull/Convex Hull/AppDelegate.swift b/Convex Hull/Convex Hull/AppDelegate.swift index 4f8496cd5..bfe15e1a7 100644 --- a/Convex Hull/Convex Hull/AppDelegate.swift +++ b/Convex Hull/Convex Hull/AppDelegate.swift @@ -17,16 +17,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> 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 } diff --git a/Convex Hull/Convex Hull/View.swift b/Convex Hull/Convex Hull/View.swift index f9f9f6ef4..2f2c3e046 100644 --- a/Convex Hull/Convex Hull/View.swift +++ b/Convex Hull/Convex Hull/View.swift @@ -9,24 +9,24 @@ import UIKit class View: UIView { - + let MAX_POINTS = 100 - + var points = [CGPoint]() - + var convexHull = [CGPoint]() - + override init(frame: CGRect) { super.init(frame: frame) - + generatePoints() quickHull(points: points) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + func generatePoints() { 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 - + // calculate parameters of general line equation y = a * x + b let a = (p1.y - p2.y) / (p1.x - p2.x) let b = p1.y - a * p1.x - + // calculate normal line's growth factor let a1 = -1 / a - + var maxDist: CGFloat = -1 var maxPoint: CGPoint = pts.first! - + for p in pts { // for every point check the distance from our line let b1 = p.y - a1 * p.x // calculate offset to line equation for given point p let x = -(b - b1)/(a - a1) // calculate x where the two lines intersect let y = a * x + b // calculate y value of this intersect point - + let dist = pow(x - p.x, 2) + pow(y - p.y, 2) // calculate distance squared between intersection point and point p 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 @@ -139,34 +139,34 @@ class View: UIView { s2.append(p) } } - + // find new hull points findHull(s1, p1, maxPoint) findHull(s2, maxPoint, p2) } 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 diff --git a/Fixed Size Array/FixedSizeArray.playground/Contents.swift b/Fixed Size Array/FixedSizeArray.playground/Contents.swift index 4bc5d66df..8ef545e45 100644 --- a/Fixed Size Array/FixedSizeArray.playground/Contents.swift +++ b/Fixed Size Array/FixedSizeArray.playground/Contents.swift @@ -10,25 +10,25 @@ struct FixedSizeArray { 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) @@ -38,7 +38,7 @@ struct FixedSizeArray { array[count] = defaultValue return result } - + mutating func removeAll() { for i in 0..(), AdjacencyListGraph()] { - + let v1 = graph.createVertex(1) let v2 = graph.createVertex(2) let v3 = graph.createVertex(3) diff --git a/Hash Set/HashSet.playground/Sources/HashSet.swift b/Hash Set/HashSet.playground/Sources/HashSet.swift index c3365110b..3ccaa94ea 100644 --- a/Hash Set/HashSet.playground/Sources/HashSet.swift +++ b/Hash Set/HashSet.playground/Sources/HashSet.swift @@ -2,31 +2,31 @@ 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 } diff --git a/Hash Table/HashTable.playground/Sources/HashTable.swift b/Hash Table/HashTable.playground/Sources/HashTable.swift index 947737c32..2383b8192 100644 --- a/Hash Table/HashTable.playground/Sources/HashTable.swift +++ b/Hash Table/HashTable.playground/Sources/HashTable.swift @@ -34,19 +34,19 @@ public struct HashTable: CustomStringConvertible { 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 } - + /// 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 { @@ -57,7 +57,7 @@ public struct HashTable: CustomStringConvertible { } return str } - + /** Create a hash table with the given capacity. */ @@ -65,7 +65,7 @@ public struct HashTable: CustomStringConvertible { assert(capacity > 0) buckets = Array(repeatElement([], count: capacity)) } - + /** Accesses the value associated with the given key for reading and writing. @@ -82,7 +82,7 @@ public struct HashTable: CustomStringConvertible { } } } - + /** Returns the value for the given key. */ @@ -95,14 +95,14 @@ public struct HashTable: CustomStringConvertible { } 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 { @@ -111,20 +111,20 @@ public struct HashTable: CustomStringConvertible { 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 { @@ -135,7 +135,7 @@ public struct HashTable: CustomStringConvertible { } return nil // key not in hash table } - + /** Removes all key-value pairs from the hash table. */ @@ -143,7 +143,7 @@ public struct HashTable: CustomStringConvertible { buckets = Array(repeatElement([], count: buckets.count)) count = 0 } - + /** Returns the given key's array index. */ diff --git a/HaversineDistance/HaversineDistance.playground/Contents.swift b/HaversineDistance/HaversineDistance.playground/Contents.swift index a6effb7b0..449fa366d 100644 --- a/HaversineDistance/HaversineDistance.playground/Contents.swift +++ b/HaversineDistance/HaversineDistance.playground/Contents.swift @@ -1,25 +1,25 @@ import UIKit func haversineDinstance(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 * M_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)) } diff --git a/Heap/Heap.swift b/Heap/Heap.swift index fa30df362..80b40c65f 100644 --- a/Heap/Heap.swift +++ b/Heap/Heap.swift @@ -113,7 +113,7 @@ public struct Heap { */ 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) @@ -144,7 +144,7 @@ public struct Heap { */ public mutating func removeAt(_ index: Int) -> T? { guard index < elements.count else { return nil } - + let size = elements.count - 1 if index != size { swap(&elements[index], &elements[size]) diff --git a/Heap/Tests/HeapTests.swift b/Heap/Tests/HeapTests.swift index 0e6c504f3..cac934406 100644 --- a/Heap/Tests/HeapTests.swift +++ b/Heap/Tests/HeapTests.swift @@ -201,7 +201,7 @@ class HeapTests: XCTestCase { XCTAssertEqual(v, nil) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [100, 50, 70, 10, 20, 60, 65]) - + let v1 = h.removeAt(5) XCTAssertEqual(v1, 60) XCTAssertTrue(verifyMaxHeap(h)) @@ -314,7 +314,7 @@ class HeapTests: XCTestCase { h.replace(index: 5, value: 13) XCTAssertTrue(verifyMaxHeap(h)) XCTAssertEqual(h.elements, [16, 14, 13, 8, 7, 10, 3, 2, 4, 1]) - + //test index out of bounds h.replace(index: 20, value: 2) XCTAssertTrue(verifyMaxHeap(h)) diff --git a/Huffman Coding/Huffman.swift b/Huffman Coding/Huffman.swift index 7e2961a2f..cad80327d 100644 --- a/Huffman Coding/Huffman.swift +++ b/Huffman Coding/Huffman.swift @@ -13,7 +13,7 @@ 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 @@ -25,15 +25,15 @@ public class Huffman { 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. */ @@ -41,7 +41,7 @@ public class Huffman { var byte: UInt8 = 0 var count = 0 } - + public init() { } } @@ -59,7 +59,7 @@ extension Huffman { ptr = ptr.successor() } } - + /* Takes a frequency table and rebuilds the tree. This is the first step of decompression. */ fileprivate func restoreTree(fromTable frequencyTable: [Freq]) { @@ -70,7 +70,7 @@ extension Huffman { } buildTree() } - + /* Returns the frequency table. This is the first 256 nodes from the tree but only those that are actually used, without the parent/left/right pointers. You would serialize this along with the compressed file. */ @@ -91,13 +91,13 @@ extension Huffman { 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 @@ -105,15 +105,15 @@ extension Huffman { 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 @@ -125,7 +125,7 @@ extension Huffman { 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) @@ -172,7 +172,7 @@ extension Huffman { } 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 diff --git a/Huffman Coding/NSData+Bits.swift b/Huffman Coding/NSData+Bits.swift index 4ae3c5c6d..1f5333296 100644 --- a/Huffman Coding/NSData+Bits.swift +++ b/Huffman Coding/NSData+Bits.swift @@ -5,7 +5,7 @@ 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) @@ -14,7 +14,7 @@ public class BitWriter { outByte = (outByte << 1) | (bit ? 1 : 0) outCount += 1 } - + public func flush() { if outCount > 0 { if outCount < 8 { @@ -31,11 +31,11 @@ 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 diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift index 3ac29301a..2d327fbac 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.playground/Contents.swift @@ -17,7 +17,7 @@ func ^^ (radix: Int, power: Int) -> Int { 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 { @@ -29,7 +29,7 @@ func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { } product[i + num2Array.count] += carry } - + return Int(product.reversed().map { String($0) }.reduce("", +))! } @@ -37,24 +37,24 @@ func multiply(_ num1: Int, by num2: Int, base: Int = 10) -> Int { func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1Array = String(num1).characters let num2Array = String(num2).characters - + guard num1Array.count > 1 && num2Array.count > 1 else { return multiply(num1, by: num2) } - + let n = max(num1Array.count, num2Array.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 } diff --git a/Karatsuba Multiplication/KaratsubaMultiplication.swift b/Karatsuba Multiplication/KaratsubaMultiplication.swift index fb20a667d..0f0e8ed12 100644 --- a/Karatsuba Multiplication/KaratsubaMultiplication.swift +++ b/Karatsuba Multiplication/KaratsubaMultiplication.swift @@ -22,24 +22,24 @@ func ^^ (radix: Int, power: Int) -> Int { func karatsuba(_ num1: Int, by num2: Int) -> Int { let num1Array = String(num1).characters let num2Array = String(num2).characters - + guard num1Array.count > 1 && num2Array.count > 1 else { return num1 * num2 } - + let n = max(num1Array.count, num2Array.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 } diff --git a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift index 46a88c134..45d9812b7 100644 --- a/Knuth-Morris-Pratt/KnuthMorrisPratt.swift +++ b/Knuth-Morris-Pratt/KnuthMorrisPratt.swift @@ -9,54 +9,54 @@ import Foundation 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 } diff --git a/Linked List/LinkedList.playground/Contents.swift b/Linked List/LinkedList.playground/Contents.swift index 08e14ef70..9ee4cc4c4 100644 --- a/Linked List/LinkedList.playground/Contents.swift +++ b/Linked List/LinkedList.playground/Contents.swift @@ -4,37 +4,37 @@ //: 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 fileprivate var head: Node? - + /// Default initializer public init() {} - + /// Computed property to check if the linked list is empty public var isEmpty: Bool { return head == nil } - + /// Computed property to get the first node in the linked list (if any) public var first: Node? { return head } - + /// Computed property to iterate through the linked list and return the last node in the list (if any) public var last: Node? { if var node = head { @@ -46,7 +46,7 @@ public final class LinkedList { return nil } } - + /// Computed property to iterate through the linked list and return the total number of nodes public var count: Int { if var node = head { @@ -60,7 +60,7 @@ public final class LinkedList { return 0 } } - + /// 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 @@ -77,7 +77,7 @@ public final class LinkedList { } return nil } - + /// Subscript function to return the node at a specific index /// /// - Parameter index: Integer value of the requested value's index @@ -86,7 +86,7 @@ public final class LinkedList { assert(node != nil) return node!.value } - + /// Append a value to the end of the list /// /// - Parameter value: The data value to be appended @@ -94,7 +94,7 @@ public final class LinkedList { let newNode = Node(value: value) self.append(newNode) } - + /// Append a copy of a LinkedListNode to the end of the list. /// /// - Parameter node: The node containing the value to be appended @@ -107,7 +107,7 @@ public final class LinkedList { head = newNode } } - + /// Append a copy of a LinkedList to the end of the list. /// /// - Parameter list: The list to be copied and appended. @@ -118,28 +118,28 @@ public final class LinkedList { nodeToCopy = node.next } } - + /// A private helper funciton to find the nodes before and after a specified index. Crashes if index is out of bounds (0...self.count) /// /// - Parameter index: Integer value of the index between the nodes. /// - Returns: A tuple of 2 nodes before & after the specified index respectively. 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) } - + /// Insert a value at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameters: @@ -149,7 +149,7 @@ public final class LinkedList { let newNode = Node(value: value) self.insert(newNode, atIndex: index) } - + /// Insert a copy of a node at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameters: @@ -162,12 +162,12 @@ public final class LinkedList { newNode.next = next prev?.next = newNode next?.previous = newNode - + if prev == nil { head = newNode } } - + /// Insert a copy of a LinkedList at a specific index. Crashes if index is out of bounds (0...self.count) /// /// - Parameters: @@ -192,12 +192,12 @@ public final class LinkedList { prev?.next = next next?.previous = prev } - + /// Function to remove all nodes/value from the list public func removeAll() { head = nil } - + /// Function to remove a specific node. /// /// - Parameter node: The node to be deleted @@ -205,19 +205,19 @@ public final class LinkedList { @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 } - + /// 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. @@ -225,7 +225,7 @@ public final class LinkedList { 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 @@ -276,7 +276,7 @@ extension LinkedList { } return result } - + public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head @@ -294,7 +294,7 @@ extension LinkedList { extension LinkedList { convenience init(array: Array) { self.init() - + for element in array { self.append(element) } @@ -305,7 +305,7 @@ extension LinkedList { extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() - + for element in elements { self.append(element) } diff --git a/Linked List/LinkedList.swift b/Linked List/LinkedList.swift index 783e650e8..94e978c07 100755 --- a/Linked List/LinkedList.swift +++ b/Linked List/LinkedList.swift @@ -1,29 +1,29 @@ 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 case let next? = node.next { @@ -34,7 +34,7 @@ public final class LinkedList { return nil } } - + public var count: Int { if var node = head { var c = 1 @@ -47,7 +47,7 @@ public final class LinkedList { return 0 } } - + public func node(atIndex index: Int) -> Node? { if index >= 0 { var node = head @@ -60,18 +60,18 @@ public final class LinkedList { } 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 { @@ -81,7 +81,7 @@ public final class LinkedList { head = newNode } } - + public func append(_ list: LinkedList) { var nodeToCopy = list.head while let node = nodeToCopy { @@ -89,29 +89,29 @@ public final class LinkedList { 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) @@ -119,12 +119,12 @@ public final class LinkedList { 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) @@ -144,32 +144,32 @@ public final class LinkedList { 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) @@ -211,7 +211,7 @@ extension LinkedList { } return result } - + public func filter(predicate: (T) -> Bool) -> LinkedList { let result = LinkedList() var node = head @@ -228,7 +228,7 @@ extension LinkedList { extension LinkedList { convenience init(array: Array) { self.init() - + for element in array { self.append(element) } @@ -238,7 +238,7 @@ extension LinkedList { extension LinkedList: ExpressibleByArrayLiteral { public convenience init(arrayLiteral elements: T...) { self.init() - + for element in elements { self.append(element) } diff --git a/Linked List/Tests/LinkedListTests.swift b/Linked List/Tests/LinkedListTests.swift index ea063cacb..7fd31c2c7 100755 --- a/Linked List/Tests/LinkedListTests.swift +++ b/Linked List/Tests/LinkedListTests.swift @@ -165,7 +165,7 @@ class LinkedListTest: XCTestCase { XCTAssertTrue(prev!.next === node) XCTAssertTrue(next!.previous === node) } - + func testInsertListAtIndex() { let list = buildList() let list2 = LinkedList() @@ -190,7 +190,7 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(list.node(atIndex: 1)?.value, 102) XCTAssertEqual(list.node(atIndex: 2)?.value, 8) } - + func testInsertListAtLastIndex() { let list = buildList() let list2 = LinkedList() @@ -202,7 +202,7 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(list.node(atIndex: 6)?.value, 99) XCTAssertEqual(list.node(atIndex: 7)?.value, 102) } - + func testAppendList() { let list = buildList() let list2 = LinkedList() @@ -214,7 +214,7 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(list.node(atIndex: 6)?.value, 99) XCTAssertEqual(list.node(atIndex: 7)?.value, 102) } - + func testAppendListToEmptyList() { let list = LinkedList() let list2 = LinkedList() @@ -225,7 +225,7 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(list.node(atIndex: 0)?.value, 5) XCTAssertEqual(list.node(atIndex: 1)?.value, 10) } - + func testRemoveAtIndexOnListWithOneElement() { let list = LinkedList() list.append(123) @@ -308,10 +308,10 @@ class LinkedListTest: XCTestCase { XCTAssertTrue(last === list.first) XCTAssertEqual(nodeCount, list.count) } - + func testArrayLiteralInitTypeInfer() { let arrayLiteralInitInfer: LinkedList = [1.0, 2.0, 3.0] - + XCTAssertEqual(arrayLiteralInitInfer.count, 3) XCTAssertEqual(arrayLiteralInitInfer.first?.value, 1.0) XCTAssertEqual(arrayLiteralInitInfer.last?.value, 3.0) @@ -319,10 +319,10 @@ class LinkedListTest: XCTestCase { XCTAssertEqual(arrayLiteralInitInfer.removeLast(), 3.0) XCTAssertEqual(arrayLiteralInitInfer.count, 2) } - + func testArrayLiteralInitExplicit() { let arrayLiteralInitExplicit: LinkedList = [1, 2, 3] - + XCTAssertEqual(arrayLiteralInitExplicit.count, 3) XCTAssertEqual(arrayLiteralInitExplicit.first?.value, 1) XCTAssertEqual(arrayLiteralInitExplicit.last?.value, 3) diff --git a/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift index 9dca23996..ee2ace8b9 100644 --- a/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift +++ b/Miller-Rabin Primality Test/MRPrimality.playground/Sources/MRPrimality.swift @@ -23,38 +23,38 @@ import Foundation */ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { guard n > 2 && n % 2 == 1 else { return false } - + var d = n - 1 var s = 0 - + while d % 2 == 0 { d /= 2 s += 1 } - + let range = UInt64.max - UInt64.max % (n - 2) var r: UInt64 = 0 repeat { arc4random_buf(&r, MemoryLayout.size(ofValue: r)) } while r >= range - + r = r % (n - 2) + 2 - + for _ in 1 ... k { var x = powmod64(r, d, n) if x == 1 || x == n - 1 { continue } - + if s == 1 { s = 2 } - + for _ in 1 ... s - 1 { x = powmod64(x, 2, n) if x == 1 { return false } if x == n - 1 { break } } - + if x != n - 1 { return false } } - + return true } @@ -71,17 +71,17 @@ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { */ private func powmod64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { if m == 1 { return 0 } - + var result: UInt64 = 1 var b = base % m var e = exp - + while e > 0 { if e % 2 == 1 { result = mulmod64(result, b, m) } b = mulmod64(b, b, m) e >>= 1 } - + return result } @@ -100,12 +100,12 @@ private func mulmod64(_ first: UInt64, _ second: UInt64, _ m: UInt64) -> UInt64 var result: UInt64 = 0 var a = first var b = second - + while a != 0 { if a % 2 == 1 { result = ((result % m) + (b % m)) % m } // This may overflow if 'm' is a 64bit number && both 'result' and 'b' are very close to but smaller than 'm'. a >>= 1 b = (b << 1) % m } - + return result } diff --git a/Miller-Rabin Primality Test/MRPrimality.swift b/Miller-Rabin Primality Test/MRPrimality.swift index 9dca23996..ee2ace8b9 100644 --- a/Miller-Rabin Primality Test/MRPrimality.swift +++ b/Miller-Rabin Primality Test/MRPrimality.swift @@ -23,38 +23,38 @@ import Foundation */ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { guard n > 2 && n % 2 == 1 else { return false } - + var d = n - 1 var s = 0 - + while d % 2 == 0 { d /= 2 s += 1 } - + let range = UInt64.max - UInt64.max % (n - 2) var r: UInt64 = 0 repeat { arc4random_buf(&r, MemoryLayout.size(ofValue: r)) } while r >= range - + r = r % (n - 2) + 2 - + for _ in 1 ... k { var x = powmod64(r, d, n) if x == 1 || x == n - 1 { continue } - + if s == 1 { s = 2 } - + for _ in 1 ... s - 1 { x = powmod64(x, 2, n) if x == 1 { return false } if x == n - 1 { break } } - + if x != n - 1 { return false } } - + return true } @@ -71,17 +71,17 @@ public func mrPrimalityTest(_ n: UInt64, iteration k: Int = 1) -> Bool { */ private func powmod64(_ base: UInt64, _ exp: UInt64, _ m: UInt64) -> UInt64 { if m == 1 { return 0 } - + var result: UInt64 = 1 var b = base % m var e = exp - + while e > 0 { if e % 2 == 1 { result = mulmod64(result, b, m) } b = mulmod64(b, b, m) e >>= 1 } - + return result } @@ -100,12 +100,12 @@ private func mulmod64(_ first: UInt64, _ second: UInt64, _ m: UInt64) -> UInt64 var result: UInt64 = 0 var a = first var b = second - + while a != 0 { if a % 2 == 1 { result = ((result % m) + (b % m)) % m } // This may overflow if 'm' is a 64bit number && both 'result' and 'b' are very close to but smaller than 'm'. a >>= 1 b = (b << 1) % m } - + return result } diff --git a/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift b/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift index d651ddf2e..238afeb9b 100755 --- a/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift +++ b/Minimum Edit Distance/MinimumEditDistance.playground/Contents.swift @@ -1,21 +1,21 @@ extension String { - + public func minimumEditDistance(other: String) -> Int { let m = self.characters.count let n = other.characters.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.characters.enumerated() { for (j, otherChar) in other.characters.enumerated() { diff --git a/Ordered Array/OrderedArray.playground/Contents.swift b/Ordered Array/OrderedArray.playground/Contents.swift index 1a0320a65..5ca0d7d31 100644 --- a/Ordered Array/OrderedArray.playground/Contents.swift +++ b/Ordered Array/OrderedArray.playground/Contents.swift @@ -49,7 +49,7 @@ public struct OrderedArray { 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 { diff --git a/Palindromes/Palindromes.playground/Contents.swift b/Palindromes/Palindromes.playground/Contents.swift index e8562a367..b9e857dd0 100644 --- a/Palindromes/Palindromes.playground/Contents.swift +++ b/Palindromes/Palindromes.playground/Contents.swift @@ -10,7 +10,7 @@ import Foundation func isPalindrome(_ str: String) -> Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.characters.count - + if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } @@ -28,14 +28,14 @@ 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) } diff --git a/Palindromes/Palindromes.swift b/Palindromes/Palindromes.swift index 2760137ca..9ddd04c80 100644 --- a/Palindromes/Palindromes.swift +++ b/Palindromes/Palindromes.swift @@ -3,7 +3,7 @@ import Foundation func isPalindrome(_ str: String) -> Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.characters.count - + if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } @@ -14,13 +14,13 @@ 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) } diff --git a/Palindromes/Test/Palindromes.swift b/Palindromes/Test/Palindromes.swift index 2760137ca..9ddd04c80 100644 --- a/Palindromes/Test/Palindromes.swift +++ b/Palindromes/Test/Palindromes.swift @@ -3,7 +3,7 @@ import Foundation func isPalindrome(_ str: String) -> Bool { let strippedString = str.replacingOccurrences(of: "\\W", with: "", options: .regularExpression, range: nil) let length = strippedString.characters.count - + if length > 1 { return palindrome(strippedString.lowercased(), left: 0, right: length - 1) } @@ -14,13 +14,13 @@ 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) } diff --git a/Palindromes/Test/Test/Test.swift b/Palindromes/Test/Test/Test.swift index 1dd79ea97..ddf970300 100644 --- a/Palindromes/Test/Test/Test.swift +++ b/Palindromes/Test/Test/Test.swift @@ -9,22 +9,22 @@ 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 { @@ -34,12 +34,12 @@ class PalindromeTests: XCTestCase { _ = 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")) @@ -47,17 +47,17 @@ class PalindromeTests: XCTestCase { 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")) diff --git a/QuadTree/QuadTree.playground/Sources/QuadTree.swift b/QuadTree/QuadTree.playground/Sources/QuadTree.swift index 14d0dbba7..7fd459e97 100644 --- a/QuadTree/QuadTree.playground/Sources/QuadTree.swift +++ b/QuadTree/QuadTree.playground/Sources/QuadTree.swift @@ -1,7 +1,7 @@ public struct Point { let x: Double let y: Double - + public init(_ x: Double, _ y: Double) { self.x = x self.y = y @@ -17,18 +17,18 @@ extension Point: CustomStringConvertible { 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))" } @@ -38,49 +38,49 @@ 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 { @@ -91,7 +91,7 @@ public struct Rect { 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) } @@ -109,37 +109,37 @@ protocol PointsContainer { } 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 @@ -149,26 +149,26 @@ class QuadTreeNode { } } } - + 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" @@ -185,13 +185,13 @@ class QuadTreeNode { } 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 @@ -200,7 +200,7 @@ extension QuadTreeNode: PointsContainer { return true } } - + fatalError("rect.containts evaluted to true, but none of the children added the point") case .leaf: points.append(point) @@ -211,7 +211,7 @@ extension QuadTreeNode: PointsContainer { } return true } - + private func subdivide() { switch type { case .leaf: @@ -220,25 +220,25 @@ extension QuadTreeNode: PointsContainer { 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 @@ -248,7 +248,7 @@ extension QuadTreeNode: PointsContainer { result.append(contentsOf: childNode.points(inRect: rect)) } } - + return result } } @@ -265,18 +265,18 @@ extension QuadTreeNode: CustomStringConvertible { } 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) } diff --git a/QuadTree/Tests/Tests/Tests.swift b/QuadTree/Tests/Tests/Tests.swift index b408c4f7e..9bd8ad28f 100644 --- a/QuadTree/Tests/Tests/Tests.swift +++ b/QuadTree/Tests/Tests/Tests.swift @@ -17,68 +17,68 @@ public func == (lhs: Point, rhs: Point) -> Bool { } 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)]) } diff --git a/Radix Sort/RadixSort.playground/Sources/radixSort.swift b/Radix Sort/RadixSort.playground/Sources/radixSort.swift index 136ede4fd..81c2479e8 100644 --- a/Radix Sort/RadixSort.playground/Sources/radixSort.swift +++ b/Radix Sort/RadixSort.playground/Sources/radixSort.swift @@ -11,18 +11,18 @@ public func radixSort(_ array: inout [Int] ) { 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) @@ -30,9 +30,9 @@ public func radixSort(_ array: inout [Int] ) { done = false } } - + var i = 0 - + for j in 0..: CustomStringConvertible { public var right: RBTNode! public var left: RBTNode! public var parent: RBTNode! - + public var description: String { if self.value == nil { return "null" } else { var nodeValue: String - + // If the value is encapsulated by parentheses it is red // If the value is encapsulated by pipes it is black // If the value is encapsulated by double pipes it is double black (This should not occur in a verified RBTree) @@ -27,33 +27,33 @@ public class RBTNode: CustomStringConvertible { } else { nodeValue = "||\(self.value!)||" } - + return "(\(self.left.description)<-\(nodeValue)->\(self.right.description))" } } - + init(tree: RBTree) { right = tree.nullLeaf left = tree.nullLeaf parent = tree.nullLeaf } - + init() { //This method is here to support the creation of a nullLeaf } - + public var isLeftChild: Bool { return self.parent.left === self } - + public var isRightChild: Bool { return self.parent.right === self } - + public var grandparent: RBTNode { return parent.parent } - + public var sibling: RBTNode { if isLeftChild { return self.parent.right @@ -61,19 +61,19 @@ public class RBTNode: CustomStringConvertible { return self.parent.left } } - + public var uncle: RBTNode { return parent.sibling } - + fileprivate var isRed: Bool { return color == .red } - + fileprivate var isBlack: Bool { return color == .black } - + fileprivate var isDoubleBlack: Bool { return color == .doubleBlack } @@ -82,70 +82,70 @@ public class RBTNode: CustomStringConvertible { public class RBTree: CustomStringConvertible { public var root: RBTNode fileprivate let nullLeaf: RBTNode - + public var description: String { return root.description } - + public init() { nullLeaf = RBTNode() nullLeaf.color = .black root = nullLeaf } - + public convenience init(withValue value: T) { self.init() insert(value) } - + public convenience init(withArray array: [T]) { self.init() insert(array) } - + public func insert(_ value: T) { let newNode = RBTNode(tree: self) newNode.value = value insertNode(n: newNode) } - + public func insert(_ values: [T]) { for value in values { print(value) insert(value) } } - + public func delete(_ value: T) { let nodeToDelete = find(value) if nodeToDelete !== nullLeaf { deleteNode(n: nodeToDelete) } } - + public func find(_ value: T) -> RBTNode { let foundNode = findNode(rootNode: root, value: value) return foundNode } - + public func minimum(n: RBTNode) -> RBTNode { var min = n if n.left !== nullLeaf { min = minimum(n: n.left) } - + return min } - + public func maximum(n: RBTNode) -> RBTNode { var max = n if n.right !== nullLeaf { max = maximum(n: n.right) } - + return max } - + public func verify() { if self.root === nullLeaf { print("The tree is empty") @@ -155,7 +155,7 @@ public class RBTree: CustomStringConvertible { property2(n: self.root) property3() } - + private func findNode(rootNode: RBTNode, value: T) -> RBTNode { var nextNode = rootNode if rootNode !== nullLeaf && value != rootNode.value { @@ -165,15 +165,15 @@ public class RBTree: CustomStringConvertible { nextNode = findNode(rootNode: rootNode.right, value: value) } } - + return nextNode } - + private func insertNode(n: RBTNode) { BSTInsertNode(n: n, parent: root) insertCase1(n: n) } - + private func BSTInsertNode(n: RBTNode, parent: RBTNode) { if parent === nullLeaf { self.root = n @@ -193,7 +193,7 @@ public class RBTree: CustomStringConvertible { } } } - + // if node is root change color to black, else move on private func insertCase1(n: RBTNode) { if n === root { @@ -202,14 +202,14 @@ public class RBTree: CustomStringConvertible { insertCase2(n: n) } } - + // if parent of node is not black, and node is not root move on private func insertCase2(n: RBTNode) { if !n.parent.isBlack { insertCase3(n: n) } } - + // if uncle is red do stuff otherwise move to 4 private func insertCase3(n: RBTNode) { if n.uncle.isRed { // node must have grandparent as children of root have a black parent @@ -224,14 +224,14 @@ public class RBTree: CustomStringConvertible { insertCase4(n: n) } } - + // parent is red, grandparent is black, uncle is black // There are 4 cases left: // - left left // - left right // - right right // - right left - + // the cases "left right" and "right left" can be rotated into the other two // so if either of the two is detected we apply a rotation and then move on to // deal with the final two cases, if neither is detected we move on to those cases anyway @@ -246,28 +246,28 @@ public class RBTree: CustomStringConvertible { insertCase5(n: n) } } - + private func insertCase5(n: RBTNode) { // swap color of parent and grandparent // parent is red grandparent is black n.parent.color = .black n.grandparent.color = .red - + if n.isLeftChild { // left left case rightRotate(n: n.grandparent) } else { // right right case leftRotate(n: n.grandparent) } } - + private func deleteNode(n: RBTNode) { var toDel = n - + if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.parent === nullLeaf { self.root = nullLeaf return } - + if toDel.left === nullLeaf && toDel.right === nullLeaf && toDel.isRed { if toDel.isLeftChild { toDel.parent.left = nullLeaf @@ -276,38 +276,38 @@ public class RBTree: CustomStringConvertible { } return } - + if toDel.left !== nullLeaf && toDel.right !== nullLeaf { let pred = maximum(n: toDel.left) toDel.value = pred.value toDel = pred } - + // from here toDel has at most 1 non nullLeaf child - + var child: RBTNode if toDel.left !== nullLeaf { child = toDel.left } else { child = toDel.right } - + if toDel.isRed || child.isRed { child.color = .black - + if toDel.isLeftChild { toDel.parent.left = child } else { toDel.parent.right = child } - + if child !== nullLeaf { child.parent = toDel.parent } } else { // both toDel and child are black - + var sibling = toDel.sibling - + if toDel.isLeftChild { toDel.parent.left = child } else { @@ -317,10 +317,10 @@ public class RBTree: CustomStringConvertible { child.parent = toDel.parent } child.color = .doubleBlack - + while child.isDoubleBlack || (child.parent !== nullLeaf && child.parent != nil) { if sibling.isBlack { - + var leftRedChild: RBTNode! = nil if sibling.left.isRed { leftRedChild = sibling.left @@ -329,7 +329,7 @@ public class RBTree: CustomStringConvertible { if sibling.right.isRed { rightRedChild = sibling.right } - + if leftRedChild != nil || rightRedChild != nil { // at least one of sibling's children are red child.color = .black if sibling.isLeftChild { @@ -389,7 +389,7 @@ public class RBTree: CustomStringConvertible { } } else { // sibling is red sibling.color = .black - + if sibling.isLeftChild { // left case rightRotate(n: sibling.parent) sibling = sibling.right.left @@ -400,7 +400,7 @@ public class RBTree: CustomStringConvertible { sibling.parent.color = .red } } - + // sibling check is here for when child is a nullLeaf and thus does not have a parent. // child is here as sibling can become nil when child is the root if (sibling.parent === nullLeaf) || (child !== nullLeaf && child.parent === nullLeaf) { @@ -409,14 +409,14 @@ public class RBTree: CustomStringConvertible { } } } - + private func property1() { - + if self.root.isRed { print("Root is not black") } } - + private func property2(n: RBTNode) { if n === nullLeaf { return @@ -431,48 +431,48 @@ public class RBTree: CustomStringConvertible { property2(n: n.left) property2(n: n.right) } - + private func property3() { let bDepth = blackDepth(root: self.root) - + let leaves: [RBTNode] = getLeaves(n: self.root) - + for leaflet in leaves { var leaf = leaflet var i = 0 - + while leaf !== nullLeaf { if leaf.isBlack { i = i + 1 } leaf = leaf.parent } - + if i != bDepth { print("black depth: \(bDepth), is not equal (depth: \(i)) for leaf with value: \(leaflet.value)") } } - + } - + private func getLeaves(n: RBTNode) -> [RBTNode] { var leaves = [RBTNode]() - + if n !== nullLeaf { if n.left === nullLeaf && n.right === nullLeaf { leaves.append(n) } else { let leftLeaves = getLeaves(n: n.left) let rightLeaves = getLeaves(n: n.right) - + leaves.append(contentsOf: leftLeaves) leaves.append(contentsOf: rightLeaves) } } - + return leaves } - + private func blackDepth(root: RBTNode) -> Int { if root === nullLeaf { return 0 @@ -481,7 +481,7 @@ public class RBTree: CustomStringConvertible { return returnValue + (max(blackDepth(root: root.left), blackDepth(root: root.right))) } } - + private func leftRotate(n: RBTNode) { let newRoot = n.right! n.right = newRoot.left! @@ -499,7 +499,7 @@ public class RBTree: CustomStringConvertible { newRoot.left = n n.parent = newRoot } - + private func rightRotate(n: RBTNode) { let newRoot = n.left! n.left = newRoot.right! diff --git a/Run-Length Encoding/RLE.playground/Contents.swift b/Run-Length Encoding/RLE.playground/Contents.swift index 11e177d0d..26f7dca48 100644 --- a/Run-Length Encoding/RLE.playground/Contents.swift +++ b/Run-Length Encoding/RLE.playground/Contents.swift @@ -12,16 +12,16 @@ 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 } @@ -66,10 +66,10 @@ func testBufferWithoutSpans() -> Bool { 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 { for bool in tests { result = result && bool } - + return result } diff --git a/Run-Length Encoding/RLE.playground/Sources/RLE.swift b/Run-Length Encoding/RLE.playground/Sources/RLE.swift index 5707e3d9d..0bb6fa00d 100644 --- a/Run-Length Encoding/RLE.playground/Sources/RLE.swift +++ b/Run-Length Encoding/RLE.playground/Sources/RLE.swift @@ -13,7 +13,7 @@ extension Data { 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 { @@ -21,7 +21,7 @@ extension Data { 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) @@ -33,7 +33,7 @@ extension Data { } return data } - + /* Converts a run-length encoded NSData back to the original. */ @@ -42,20 +42,20 @@ extension 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) diff --git a/Segment Tree/SegmentTree.playground/Contents.swift b/Segment Tree/SegmentTree.playground/Contents.swift index 5bba56cc0..08474aee2 100644 --- a/Segment Tree/SegmentTree.playground/Contents.swift +++ b/Segment Tree/SegmentTree.playground/Contents.swift @@ -1,19 +1,19 @@ //: Playground - noun: a place where people can play 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 { @@ -23,19 +23,19 @@ public class SegmentTree { 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 { @@ -46,7 +46,7 @@ public class SegmentTree { return function(leftResult, rightResult) } } - + public func replaceItem(at index: Int, withItem item: T) { if leftBound == rightBound { value = item @@ -83,7 +83,7 @@ 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 diff --git a/Segment Tree/SegmentTree.swift b/Segment Tree/SegmentTree.swift index a3ec8b1bf..6f4edd306 100644 --- a/Segment Tree/SegmentTree.swift +++ b/Segment Tree/SegmentTree.swift @@ -8,19 +8,19 @@ */ 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 { @@ -30,19 +30,19 @@ public class SegmentTree { 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 { @@ -53,7 +53,7 @@ public class SegmentTree { return function(leftResult, rightResult) } } - + public func replaceItem(at index: Int, withItem item: T) { if leftBound == rightBound { value = item diff --git a/Select Minimum Maximum/MinimumMaximumPairs.swift b/Select Minimum Maximum/MinimumMaximumPairs.swift index b7deb570a..81942b303 100644 --- a/Select Minimum Maximum/MinimumMaximumPairs.swift +++ b/Select Minimum Maximum/MinimumMaximumPairs.swift @@ -35,6 +35,6 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { } } } - + return (minimum, maximum) } diff --git a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift index 182060805..dbf3a7468 100644 --- a/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift +++ b/Select Minimum Maximum/SelectMinimumMaximum.playground/Contents.swift @@ -4,7 +4,7 @@ func minimum(_ array: [T]) -> T? { guard !array.isEmpty else { return nil } - + var minimum = array.removeFirst() for element in array { minimum = element < minimum ? element : minimum @@ -18,7 +18,7 @@ func maximum(_ array: [T]) -> T? { guard !array.isEmpty else { return nil } - + var maximum = array.removeFirst() for element in array { maximum = element > maximum ? element : maximum @@ -32,18 +32,18 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { guard !array.isEmpty else { return nil } - + var minimum = array.first! var maximum = array.first! - + let hasOddNumberOfItems = array.count % 2 != 0 if hasOddNumberOfItems { array.removeFirst() } - + while !array.isEmpty { let pair = (array.removeFirst(), array.removeFirst()) - + if pair.0 > pair.1 { if pair.0 > maximum { maximum = pair.0 @@ -60,7 +60,7 @@ func minimumMaximum(_ array: [T]) -> (minimum: T, maximum: T)? { } } } - + return (minimum, maximum) } diff --git a/Shell Sort/ShellSortExample.swift b/Shell Sort/ShellSortExample.swift index aaf58cf4d..e9cee7543 100644 --- a/Shell Sort/ShellSortExample.swift +++ b/Shell Sort/ShellSortExample.swift @@ -10,18 +10,18 @@ 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 list[index - 1] > list[index] && index - 1 > 0 { swap(&list[index - 1], &list[index]) index -= 1 diff --git a/Shortest Path (Unweighted)/Tests/Graph.swift b/Shortest Path (Unweighted)/Tests/Graph.swift index 8322ba0a9..4d2e59eab 100644 --- a/Shortest Path (Unweighted)/Tests/Graph.swift +++ b/Shortest Path (Unweighted)/Tests/Graph.swift @@ -2,7 +2,7 @@ open class Edge: Equatable { open var neighbor: Node - + public init(neighbor: Node) { self.neighbor = neighbor } @@ -17,28 +17,28 @@ public func == (lhs: Edge, rhs: Edge) -> Bool { 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 }!) } @@ -52,25 +52,25 @@ public func == (lhs: Node, rhs: Node) -> Bool { 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})]" @@ -78,18 +78,18 @@ open class Graph: CustomStringConvertible, Equatable { } 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) @@ -97,7 +97,7 @@ open class Graph: CustomStringConvertible, Equatable { duplicated.addEdge(source, neighbor: neighbour) } } - + return duplicated } } diff --git a/Shunting Yard/ShuntingYard.playground/Contents.swift b/Shunting Yard/ShuntingYard.playground/Contents.swift index fa9f5745b..bd4d15515 100644 --- a/Shunting Yard/ShuntingYard.playground/Contents.swift +++ b/Shunting Yard/ShuntingYard.playground/Contents.swift @@ -12,7 +12,7 @@ public enum OperatorType: CustomStringConvertible { case multiply case percent case exponent - + public var description: String { switch self { case .add: @@ -36,7 +36,7 @@ public enum TokenType: CustomStringConvertible { case closeBracket case Operator(OperatorToken) case operand(Double) - + public var description: String { switch self { case .openBracket: @@ -53,11 +53,11 @@ public enum TokenType: CustomStringConvertible { public struct OperatorToken: CustomStringConvertible { let operatorType: OperatorType - + init(operatorType: OperatorType) { self.operatorType = operatorType } - + var precedence: Int { switch operatorType { case .add, .subtract: @@ -68,7 +68,7 @@ public struct OperatorToken: CustomStringConvertible { return 10 } } - + var associativity: OperatorAssociativity { switch operatorType { case .add, .subtract, .divide, .multiply, .percent: @@ -77,7 +77,7 @@ public struct OperatorToken: CustomStringConvertible { return .rightAssociative } } - + public var description: String { return operatorType.description } @@ -93,19 +93,19 @@ func < (left: OperatorToken, right: OperatorToken) -> Bool { 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: @@ -114,7 +114,7 @@ public struct Token: CustomStringConvertible { return false } } - + var isOperator: Bool { switch tokenType { case .Operator(_): @@ -123,7 +123,7 @@ public struct Token: CustomStringConvertible { return false } } - + var operatorToken: OperatorToken? { switch tokenType { case .Operator(let operatorToken): @@ -132,7 +132,7 @@ public struct Token: CustomStringConvertible { return nil } } - + public var description: String { return tokenType.description } @@ -140,27 +140,27 @@ public struct Token: CustomStringConvertible { 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 @@ -169,29 +169,29 @@ public class InfixExpressionBuilder { // 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 { @@ -204,11 +204,11 @@ public func reversePolishNotation(_ expression: [Token]) -> String { tokenStack.push(token) } } - + while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } - + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } diff --git a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift index 27286fdbd..c54c5a600 100644 --- a/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift +++ b/Shunting Yard/ShuntingYard.playground/Sources/Stack.swift @@ -2,27 +2,27 @@ 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 } diff --git a/Shunting Yard/ShuntingYard.swift b/Shunting Yard/ShuntingYard.swift index 97a72249d..201264650 100644 --- a/Shunting Yard/ShuntingYard.swift +++ b/Shunting Yard/ShuntingYard.swift @@ -18,7 +18,7 @@ public enum OperatorType: CustomStringConvertible { case multiply case percent case exponent - + public var description: String { switch self { case .add: @@ -42,7 +42,7 @@ public enum TokenType: CustomStringConvertible { case closeBracket case Operator(OperatorToken) case operand(Double) - + public var description: String { switch self { case .openBracket: @@ -59,11 +59,11 @@ public enum TokenType: CustomStringConvertible { public struct OperatorToken: CustomStringConvertible { let operatorType: OperatorType - + init(operatorType: OperatorType) { self.operatorType = operatorType } - + var precedence: Int { switch operatorType { case .add, .subtract: @@ -74,7 +74,7 @@ public struct OperatorToken: CustomStringConvertible { return 10 } } - + var associativity: OperatorAssociativity { switch operatorType { case .add, .subtract, .divide, .multiply, .percent: @@ -83,7 +83,7 @@ public struct OperatorToken: CustomStringConvertible { return .rightAssociative } } - + public var description: String { return operatorType.description } @@ -99,19 +99,19 @@ func < (left: OperatorToken, right: OperatorToken) -> Bool { 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: @@ -120,7 +120,7 @@ public struct Token: CustomStringConvertible { return false } } - + var isOperator: Bool { switch tokenType { case .Operator(_): @@ -129,7 +129,7 @@ public struct Token: CustomStringConvertible { return false } } - + var operatorToken: OperatorToken? { switch tokenType { case .Operator(let operatorToken): @@ -138,7 +138,7 @@ public struct Token: CustomStringConvertible { return nil } } - + public var description: String { return tokenType.description } @@ -146,27 +146,27 @@ public struct Token: CustomStringConvertible { 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 @@ -175,29 +175,29 @@ public class InfixExpressionBuilder { // 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 { @@ -210,10 +210,10 @@ public func reversePolishNotation(_ expression: [Token]) -> String { tokenStack.push(token) } } - + while tokenStack.count > 0 { reversePolishNotation.append(tokenStack.pop()!) } - + return reversePolishNotation.map({token in token.description}).joined(separator: " ") } diff --git a/Skip-List/SkipList.swift b/Skip-List/SkipList.swift index e844f9959..cd832eef9 100644 --- a/Skip-List/SkipList.swift +++ b/Skip-List/SkipList.swift @@ -70,29 +70,29 @@ private func coinFlip() -> Bool { public class DataNode { public typealias Node = DataNode - - var data: Payload? + + 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() {} - + } @@ -100,18 +100,18 @@ open class SkipList { // 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 + + currentNode = node.down case .some(let value) where value.key != nil: if value.key == key { @@ -122,14 +122,14 @@ extension SkipList { currentNode = node.down } else { currentNode = node.next - } + } } - + default: continue } - - } else { + + } else { break } } @@ -139,7 +139,7 @@ extension SkipList { } else { return nil } - + } func search(key: Key) -> Payload? { @@ -147,9 +147,9 @@ extension SkipList { return nil } - return node.next!.data - } - + return node.next!.data + } + } @@ -157,12 +157,12 @@ extension SkipList { // 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) + 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() { @@ -174,7 +174,7 @@ extension SkipList { head = newHead currentTopNode = node } - + } @@ -191,13 +191,13 @@ extension SkipList { } else { currentNode = nextNode } - + } else { stack.push(currentNode!) - currentNode = currentNode!.down + currentNode = currentNode!.down } - - } + + } let itemAtLayer = stack.pop() var node = Node(key: key, data: data) @@ -208,24 +208,24 @@ extension SkipList { 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 { + + } else { let nextNode = stack.pop() - + node = Node(key: key, data: data) node.down = currentTopNode node.next = nextNode!.next nextNode!.next = node currentTopNode = node } - } + } } @@ -233,7 +233,7 @@ extension SkipList { if head != nil { if let node = findNode(key: key) { // replace, in case of key already exists. - var currentNode = node.next + var currentNode = node.next while currentNode != nil && currentNode!.key == key { currentNode!.data = data currentNode = currentNode!.down @@ -241,12 +241,12 @@ extension SkipList { } else { insertItem(key: key, data: data) } - + } else { bootstrapBaseLayer(key: key, data: data) } } - + } @@ -257,32 +257,32 @@ extension SkipList { 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) } diff --git a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift index ccfa58b09..324e906ee 100644 --- a/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift +++ b/Strassen Matrix Multiplication/StrassensMatrixMultiplication.playground/Sources/Matrix.swift @@ -9,53 +9,53 @@ 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") @@ -65,7 +65,7 @@ public struct Matrix { grid[(row * columns) + column] = newValue } } - + public subscript(type: Matrix.Index, value: Int) -> [T] { get { switch type { @@ -95,24 +95,24 @@ public struct Matrix { } } } - + // 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) @@ -196,7 +196,7 @@ extension Matrix { 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))))) } @@ -248,7 +248,7 @@ extension Matrix: Addable { 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..(rows: rows, columns: columns) for row in 0.. String { let allowedCharsCount = UInt32(allowedChars.characters.count) var randomString = "" - + for _ in (0..() 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)) @@ -29,20 +29,20 @@ class TernarySearchTreeTests: XCTestCase { } 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() @@ -55,13 +55,13 @@ class TernarySearchTreeTests: XCTestCase { 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) diff --git a/Ternary Search Tree/Utils.swift b/Ternary Search Tree/Utils.swift index cabfe1b68..97f09fdd2 100644 --- a/Ternary Search Tree/Utils.swift +++ b/Ternary Search Tree/Utils.swift @@ -9,22 +9,22 @@ 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.. 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) @@ -155,33 +155,33 @@ extension ThreadedBinaryTree { 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. @@ -191,11 +191,11 @@ extension ThreadedBinaryTree { } 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 { @@ -228,7 +228,7 @@ extension ThreadedBinaryTree { } return nil } - + /* // Recursive version of search // Educational but undesirable due to the overhead cost of recursion @@ -242,11 +242,11 @@ extension ThreadedBinaryTree { } } */ - + public func contains(value: T) -> Bool { return search(value) != nil } - + /* Returns the leftmost descendent. O(h) time. */ @@ -257,7 +257,7 @@ extension ThreadedBinaryTree { } return node } - + /* Returns the rightmost descendent. O(h) time. */ @@ -268,7 +268,7 @@ extension ThreadedBinaryTree { } return node } - + /* Calculates the depth of this node, i.e. the distance to the root. Takes O(h) time. @@ -282,7 +282,7 @@ extension ThreadedBinaryTree { } 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). @@ -294,7 +294,7 @@ extension ThreadedBinaryTree { return 1 + max(left?.height() ?? 0, right?.height() ?? 0) } } - + /* Finds the node whose value precedes our value in sorted order. */ @@ -305,7 +305,7 @@ extension ThreadedBinaryTree { return leftThread } } - + /* Finds the node whose value succeeds our value in sorted order. */ @@ -333,7 +333,7 @@ extension ThreadedBinaryTree { } } } - + public func traverseInOrderBackward(_ visit: (T) -> Void) { var n: ThreadedBinaryTree n = maximum() @@ -346,19 +346,19 @@ extension ThreadedBinaryTree { } } } - + 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. */ @@ -390,7 +390,7 @@ extension ThreadedBinaryTree { 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). @@ -452,7 +452,7 @@ extension ThreadedBinaryTree: CustomDebugStringConvertible { } return s } - + public func toArray() -> [T] { return map { $0 } } diff --git a/Treap/Treap.swift b/Treap/Treap.swift index 6e80abfb2..7038e843e 100644 --- a/Treap/Treap.swift +++ b/Treap/Treap.swift @@ -27,11 +27,11 @@ 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: @@ -46,7 +46,7 @@ public indirect enum Treap { return nil } } - + public func contains(_ key: Key) -> Bool { switch self { case .empty: @@ -61,7 +61,7 @@ public indirect enum Treap { return false } } - + public var depth: Int { switch self { case .empty: @@ -80,12 +80,12 @@ public indirect enum Treap { 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 } } @@ -121,7 +121,7 @@ public extension Treap { 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 @@ -141,14 +141,14 @@ public extension Treap { 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: diff --git a/Treap/Treap/TreapTests/TreapTests.swift b/Treap/Treap/TreapTests/TreapTests.swift index f349e6ab8..d4fc4cfdb 100644 --- a/Treap/Treap/TreapTests/TreapTests.swift +++ b/Treap/Treap/TreapTests/TreapTests.swift @@ -27,17 +27,17 @@ THE SOFTWARE.*/ 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 testSanity() { var treap = Treap.empty treap = treap.set(key: 5, val: "a").set(key: 7, val: "b") @@ -51,7 +51,7 @@ class TreapTests: XCTestCase { XCTAssert(!treap.contains(5)) XCTAssert(treap.contains(7)) } - + func testFairlyBalanced() { var treap = Treap.empty for i in 0..<1000 { @@ -60,7 +60,7 @@ class TreapTests: XCTestCase { let depth = treap.depth XCTAssert(depth < 30, "treap.depth was \(depth)") } - + func testFairlyBalancedCollection() { var treap = Treap() for i in 0..<1000 { @@ -69,5 +69,5 @@ class TreapTests: XCTestCase { let depth = treap.depth XCTAssert(depth > 0 && depth < 30) } - + } diff --git a/Treap/TreapCollectionType.swift b/Treap/TreapCollectionType.swift index 7292c5f0a..eeee065fe 100644 --- a/Treap/TreapCollectionType.swift +++ b/Treap/TreapCollectionType.swift @@ -25,52 +25,52 @@ 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 { @@ -78,28 +78,28 @@ extension Treap: MutableCollection { 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 diff --git a/Treap/TreapMergeSplit.swift b/Treap/TreapMergeSplit.swift index 34cfec3d2..62d18d16f 100644 --- a/Treap/TreapMergeSplit.swift +++ b/Treap/TreapMergeSplit.swift @@ -37,7 +37,7 @@ public extension Treap { } else { fatalError("No values in treap") } - + switch self { case .node: if case let .node(_, _, _, left, right) = current.set(key: key, val: val, p: -1) { @@ -49,7 +49,7 @@ public extension Treap { return (left: .empty, right: .empty) } } - + internal var leastKey: Key? { switch self { case .empty: @@ -60,7 +60,7 @@ public extension Treap { return left.leastKey } } - + internal var mostKey: Key? { switch self { case .empty: @@ -79,7 +79,7 @@ internal func merge(_ left: Treap, right 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)) @@ -96,16 +96,16 @@ 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 "" diff --git a/Trie/Trie/Trie/Trie.swift b/Trie/Trie/Trie/Trie.swift index 4321479c3..7ff9638d7 100644 --- a/Trie/Trie/Trie/Trie.swift +++ b/Trie/Trie/Trie/Trie.swift @@ -18,8 +18,8 @@ class TrieNode { var isLeaf: Bool { return children.count == 0 } - - + + /// Initializes a node. /// /// - Parameters: @@ -29,7 +29,7 @@ class TrieNode { self.value = value self.parentNode = parentNode } - + /// Adds a child node to self. If the child is already present, /// do nothing. /// @@ -92,7 +92,7 @@ class Trie: NSObject, NSCoding { // MARK: - Adds methods: insert, remove, contains extension Trie { - + /// Inserts a word into the trie. If the word is already present, /// there is no change. /// @@ -117,7 +117,7 @@ extension Trie { wordCount += 1 currentNode.isTerminating = true } - + /// Determines whether a word is in the trie. /// /// - Parameter word: the word to check for @@ -168,7 +168,7 @@ extension Trie { 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. @@ -187,7 +187,7 @@ extension Trie { } } } - + /// 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 @@ -210,7 +210,7 @@ extension Trie { } wordCount -= 1 } - + /// Returns an array of words in a subtrie of the trie /// /// - Parameters: diff --git a/Trie/Trie/TrieUITests/TrieUITests.swift b/Trie/Trie/TrieUITests/TrieUITests.swift index f3da2a67f..acb3b1756 100644 --- a/Trie/Trie/TrieUITests/TrieUITests.swift +++ b/Trie/Trie/TrieUITests/TrieUITests.swift @@ -9,12 +9,12 @@ 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. @@ -22,15 +22,15 @@ class TrieUITests: XCTestCase { // 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. } - + } diff --git a/Z-Algorithm/ZAlgorithm.swift b/Z-Algorithm/ZAlgorithm.swift index 9bef69687..969a3599b 100644 --- a/Z-Algorithm/ZAlgorithm.swift +++ b/Z-Algorithm/ZAlgorithm.swift @@ -9,34 +9,34 @@ import Foundation func ZetaAlgorithm(ptrn: String) -> [Int]? { - + let pattern = Array(ptrn.characters) 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 @@ -44,18 +44,18 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { } 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 diff --git a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift index 395122af0..44faf6790 100644 --- a/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift +++ b/Z-Algorithm/ZetaAlgorithm.playground/Contents.swift @@ -2,34 +2,34 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { - + let pattern = Array(ptrn.characters) 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 @@ -37,18 +37,18 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { } 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 @@ -60,28 +60,28 @@ func ZetaAlgorithm(ptrn: String) -> [Int]? { extension String { - + func indexesOf(pattern: String) -> [Int]? { let patternLength = pattern.characters.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 } } diff --git a/Z-Algorithm/ZetaAlgorithm.swift b/Z-Algorithm/ZetaAlgorithm.swift index c35703272..e60c1617f 100644 --- a/Z-Algorithm/ZetaAlgorithm.swift +++ b/Z-Algorithm/ZetaAlgorithm.swift @@ -9,28 +9,28 @@ import Foundation extension String { - + func indexesOf(pattern: String) -> [Int]? { let patternLength = pattern.characters.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 } } From b718f04b4be46ebe9d82cc1d18264d92b12be0a9 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Thu, 4 May 2017 03:53:31 +0500 Subject: [PATCH 0373/1039] Fix violation: unused_optional_binding warning: Unused Optional Binding Violation: Prefer `!= nil` over `let _ =` () --- Graph/Graph/AdjacencyListGraph.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graph/Graph/AdjacencyListGraph.swift b/Graph/Graph/AdjacencyListGraph.swift index 57fd75fed..b58ef6417 100644 --- a/Graph/Graph/AdjacencyListGraph.swift +++ b/Graph/Graph/AdjacencyListGraph.swift @@ -78,7 +78,7 @@ open class AdjacencyListGraph: AbstractGraph where T: Equatable, T: Hashab // works let edge = Edge(from: from, to: to, weight: weight) let edgeList = adjacencyList[from.index] - if let _ = edgeList.edges { + if edgeList.edges != nil { edgeList.addEdge(edge) } else { edgeList.edges = [edge] From 9a363c7082c2acbc6984864b67ac6c20ac911cdb Mon Sep 17 00:00:00 2001 From: Xiangxin Date: Fri, 17 Mar 2017 00:19:36 +0800 Subject: [PATCH 0374/1039] Minimum Spanning Tree (Kruskal's and Prim's) --- Minimum Spanning Tree/Images/kruskal.png | Bin 0 -> 22083 bytes Minimum Spanning Tree/Images/prim.png | Bin 0 -> 19053 bytes Minimum Spanning Tree/Kruskal.swift | 31 +++ .../Contents.swift | 93 +++++++ .../Resources/mst.png | Bin 0 -> 19209 bytes .../Sources/Graph.swift | 55 +++++ .../Sources/Heap.swift | 227 ++++++++++++++++++ .../Sources/PriorityQueue.swift | 58 +++++ .../Sources/UnionFind.swift | 61 +++++ .../contents.xcplayground | 4 + Minimum Spanning Tree/Prim.swift | 45 ++++ Minimum Spanning Tree/README.markdown | 102 ++++++++ README.markdown | 1 + .../contents.xcworkspacedata | 26 ++ 14 files changed, 703 insertions(+) create mode 100644 Minimum Spanning Tree/Images/kruskal.png create mode 100644 Minimum Spanning Tree/Images/prim.png create mode 100644 Minimum Spanning Tree/Kruskal.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/mst.png create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground create mode 100644 Minimum Spanning Tree/Prim.swift create mode 100644 Minimum Spanning Tree/README.markdown diff --git a/Minimum Spanning Tree/Images/kruskal.png b/Minimum Spanning Tree/Images/kruskal.png new file mode 100644 index 0000000000000000000000000000000000000000..5172f180fda8dff8666a4a38f08e675311c515dd GIT binary patch literal 22083 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 literal 0 HcmV?d00001 diff --git a/Minimum Spanning Tree/Kruskal.swift b/Minimum Spanning Tree/Kruskal.swift new file mode 100644 index 000000000..bebd32602 --- /dev/null +++ b/Minimum Spanning Tree/Kruskal.swift @@ -0,0 +1,31 @@ +// +// 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) +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift new file mode 100644 index 000000000..99b5e859f --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift @@ -0,0 +1,93 @@ +/** + 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() + + if graph.vertices.isEmpty { + 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: graph.vertices.first!, 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) diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/mst.png b/Minimum Spanning Tree/MinimumSpanningTree.playground/Resources/mst.png new file mode 100644 index 0000000000000000000000000000000000000000..2138fd535de977e68e4a08878f6e8782eab9ca2e GIT binary patch literal 19209 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 LpB?Rl2?zi?V2Grt literal 0 HcmV?d00001 diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift new file mode 100644 index 000000000..0ae996646 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift @@ -0,0 +1,55 @@ + +// 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) + if adjList[v1] == nil { + adjList[v1] = [(vertex: v2, weight: w)] + } else { + adjList[v1]!.append((vertex: v2, weight: w)) + } + + if adjList[v2] == nil { + adjList[v2] = [(vertex: v1, weight: w)] + } else { + adjList[v2]!.append((vertex: v1, weight: w)) + } + } + + public mutating func addEdge(_ edge: Edge) { + addEdge(vertex1: edge.vertex1, vertex2: edge.vertex2, weight: edge.weight) + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift new file mode 100644 index 000000000..fa30df362 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Heap.swift @@ -0,0 +1,227 @@ +// +// 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 { + swap(&elements[index], &elements[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 } + + swap(&elements[parentIndex], &elements[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 + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift new file mode 100644 index 000000000..92f7b6d3f --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/PriorityQueue.swift @@ -0,0 +1,58 @@ +/* + 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) + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift new file mode 100644 index 000000000..29ea0a373 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/UnionFind.swift @@ -0,0 +1,61 @@ +/* + 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 + } + } +} diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground b/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground new file mode 100644 index 000000000..89da2d470 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Minimum Spanning Tree/Prim.swift b/Minimum Spanning Tree/Prim.swift new file mode 100644 index 000000000..89c26cff0 --- /dev/null +++ b/Minimum Spanning Tree/Prim.swift @@ -0,0 +1,45 @@ +// +// 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() + + if graph.vertices.isEmpty { + 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: graph.vertices.first!, 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) +} diff --git a/Minimum Spanning Tree/README.markdown b/Minimum Spanning Tree/README.markdown new file mode 100644 index 000000000..c47713701 --- /dev/null +++ b/Minimum Spanning Tree/README.markdown @@ -0,0 +1,102 @@ +# Minimum Spanning Tree (Weighted Graph) + +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)) + } + } + } +} +``` diff --git a/README.markdown b/README.markdown index e0983f22e..579ca0b4e 100644 --- a/README.markdown +++ b/README.markdown @@ -178,6 +178,7 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [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/) ## Puzzles diff --git a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata index b2ffce836..c89ac0dfe 100644 --- a/swift-algorithm-club.xcworkspace/contents.xcworkspacedata +++ b/swift-algorithm-club.xcworkspace/contents.xcworkspacedata @@ -1267,6 +1267,32 @@ location = "group:README.markdown"> + + + + + + + + + + + + + + + + From 6bc50e5f9a966738b8331d68de8ed421067d4f4e Mon Sep 17 00:00:00 2001 From: Xiangxin Date: Tue, 25 Apr 2017 15:29:45 +0800 Subject: [PATCH 0375/1039] Address comments and refactor --- .../MinimumSpanningTree.playground/Contents.swift | 4 ++-- .../Sources/Graph.swift | 13 +++++++------ .../playground.xcworkspace/contents.xcworkspacedata | 7 +++++++ Minimum Spanning Tree/Prim.swift | 5 +++-- 4 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift index 99b5e859f..2981d30ea 100644 --- a/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Contents.swift @@ -30,7 +30,7 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) var cost: Int = 0 var tree = Graph() - if graph.vertices.isEmpty { + guard let start = graph.vertices.first else { return (cost: cost, tree: tree) } @@ -38,7 +38,7 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>( sort: { $0.weight < $1.weight }) - priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil)) + priorityQueue.enqueue((vertex: start, weight: 0, parent: nil)) while let head = priorityQueue.dequeue() { let vertex = head.vertex if visited.contains(vertex) { diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift index 0ae996646..a2f243202 100644 --- a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift @@ -36,16 +36,17 @@ public struct Graph: CustomStringConvertible { edgeList.append(Edge(vertex1: v1, vertex2: v2, weight: w)) vertices.insert(v1) vertices.insert(v2) - if adjList[v1] == nil { - adjList[v1] = [(vertex: v2, weight: w)] + + if let _ = adjList[v1] { + adjList[v1]?.append((vertex: v2, weight: w)) } else { - adjList[v1]!.append((vertex: v2, weight: w)) + adjList[v1] = [(vertex: v2, weight: w)] } - if adjList[v2] == nil { - adjList[v2] = [(vertex: v1, weight: w)] + if let _ = adjList[v2] { + adjList[v2]?.append((vertex: v1, weight: w)) } else { - adjList[v2]!.append((vertex: v1, weight: w)) + adjList[v2] = [(vertex: v1, weight: w)] } } diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata b/Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..919434a62 --- /dev/null +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Minimum Spanning Tree/Prim.swift b/Minimum Spanning Tree/Prim.swift index 89c26cff0..d975fc430 100644 --- a/Minimum Spanning Tree/Prim.swift +++ b/Minimum Spanning Tree/Prim.swift @@ -10,7 +10,7 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) var cost: Int = 0 var tree = Graph() - if graph.vertices.isEmpty { + guard let start = graph.vertices.first else { return (cost: cost, tree: tree) } @@ -18,7 +18,7 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) var priorityQueue = PriorityQueue<(vertex: T, weight: Int, parent: T?)>( sort: { $0.weight < $1.weight }) - priorityQueue.enqueue((vertex: graph.vertices.first!, weight: 0, parent: nil)) + priorityQueue.enqueue((vertex: start, weight: 0, parent: nil)) while let head = priorityQueue.dequeue() { let vertex = head.vertex if visited.contains(vertex) { @@ -43,3 +43,4 @@ func minimumSpanningTreePrim(graph: Graph) -> (cost: Int, tree: Graph) return (cost: cost, tree: tree) } + From ea777fb3bc861e4818c414a97eb72fb8b9e3b644 Mon Sep 17 00:00:00 2001 From: Xiangxin Date: Sat, 6 May 2017 13:08:41 +0800 Subject: [PATCH 0376/1039] refactor --- .../Sources/Graph.swift | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift index a2f243202..5e74e14cb 100644 --- a/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift +++ b/Minimum Spanning Tree/MinimumSpanningTree.playground/Sources/Graph.swift @@ -37,17 +37,11 @@ public struct Graph: CustomStringConvertible { vertices.insert(v1) vertices.insert(v2) - if let _ = adjList[v1] { - adjList[v1]?.append((vertex: v2, weight: w)) - } else { - adjList[v1] = [(vertex: v2, weight: w)] - } + adjList[v1] = adjList[v1] ?? [] + adjList[v1]?.append((vertex: v2, weight: w)) - if let _ = adjList[v2] { - adjList[v2]?.append((vertex: v1, weight: w)) - } else { - adjList[v2] = [(vertex: v1, weight: w)] - } + adjList[v2] = adjList[v2] ?? [] + adjList[v2]?.append((vertex: v1, weight: w)) } public mutating func addEdge(_ edge: Edge) { From 12fac48235b369612be3a96b807e4e4ba2ad237c Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Sun, 7 May 2017 04:45:19 -0700 Subject: [PATCH 0377/1039] Fixed spacing, and fixes some English. --- .../UnionFind.playground/Contents.swift | 24 ++--- .../Sources/UnionFindQuickFind.swift | 80 ++++++++-------- .../Sources/UnionFindQuickUnion.swift | 82 ++++++++-------- .../Sources/UnionFindWeightedQuickFind.swift | 94 +++++++++---------- .../Sources/UnionFindWeightedQuickUnion.swift | 92 +++++++++--------- ...indWeightedQuickUnionPathCompression.swift | 86 ++++++++--------- 6 files changed, 229 insertions(+), 229 deletions(-) diff --git a/Union-Find/UnionFind.playground/Contents.swift b/Union-Find/UnionFind.playground/Contents.swift index 9ad5215b3..0a50d1ba6 100644 --- a/Union-Find/UnionFind.playground/Contents.swift +++ b/Union-Find/UnionFind.playground/Contents.swift @@ -3,17 +3,17 @@ var dsu = UnionFindQuickUnion() for i in 1...10 { - dsu.addSetWith(i) + 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) - } + if i % 2 == 0 { + dsu.unionSetsContaining(2, and: i) + } else { + dsu.unionSetsContaining(1, and: i) + } } // check our division @@ -42,12 +42,12 @@ 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) - } + 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")) diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift b/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift index 25d7f5b5d..33e81832d 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindQuickFind.swift @@ -3,48 +3,48 @@ 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 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 } - - 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 - } + } + + 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 } + } } diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift b/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift index 4c848e61d..9bff31616 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindQuickUnion.swift @@ -3,49 +3,49 @@ 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 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] } - - 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 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 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 - } + } + + 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 } + } } diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift index 02bec94a8..c89f2a457 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickFind.swift @@ -3,57 +3,57 @@ 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 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 } - - 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) + } + + 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 - } + } + + 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 } + } } diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift index b3ac7445e..cd33007bc 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnion.swift @@ -1,56 +1,56 @@ 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 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] } - - 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 setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) + } + + /// 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 { - 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] - } - } + 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 - } + } + + 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 } + } } diff --git a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift index 892f46a3c..7eb8fe209 100644 --- a/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift +++ b/Union-Find/UnionFind.playground/Sources/UnionFindWeightedQuickUnionPathCompression.swift @@ -1,53 +1,53 @@ 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) + 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]) } - - /// Path Compression. - private mutating func setByIndex(_ index: Int) -> Int { - if index != parent[index] { - parent[index] = setByIndex(parent[index]) - } - return 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 setOf(_ element: T) -> Int? { - if let indexOfElement = index[element] { - return setByIndex(indexOfElement) + } + + 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 { - 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] - } - } + 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 - } + } + + 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 } + } } From e560f60fc35889fefba95389ea53c6d02a9e22e9 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 8 May 2017 01:09:02 +0500 Subject: [PATCH 0378/1039] Fix a few typos in DiningPhilosophers Readme an -> a dinining -> dining "no needs" -> "no need" --- DiningPhilosophers/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 0bf4f28ce..bc622e559 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -22,12 +22,12 @@ Eating is not limited by the remaining amounts of spaghetti or stomach space; an 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 an dinining table: +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 needs for a central authority to control the locking and serialization of resources. +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). From 297b0d4679fbd8607edb5b59b87d273962354e84 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 8 May 2017 01:26:16 +0500 Subject: [PATCH 0379/1039] Fix minor grammar typo --- Graph/README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Graph/README.markdown b/Graph/README.markdown index bc33b044a..d3c8b89e5 100644 --- a/Graph/README.markdown +++ b/Graph/README.markdown @@ -143,7 +143,7 @@ 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 concept both inherit a common API from `AbstractGraph`, so they can be created in an identical fashion, with different optimized data structures behind the scenes. +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: From 24d5adeba873dc184e2fc28dcaf942b15c60b95e Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Mon, 8 May 2017 01:32:34 +0500 Subject: [PATCH 0380/1039] Fix broken links by replacing spaces with %20 --- Heap/README.markdown | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index 7beea4f34..a3b0038ab 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -1,11 +1,11 @@ # Heap -A heap is a [binary tree](../Binary Tree/) 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. +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 Queue/). -- To support [heap sorts](../Heap Sort/). +- 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. @@ -21,7 +21,7 @@ An example: 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 Queue/)to access the "most important" element quickly. +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. @@ -30,11 +30,11 @@ As a result of this heap property, a max-heap always stores its largest item at A heap is not a replacement for a binary search tree, and there are similarities and differnces between them. Here are some main differences: -**Order of the nodes.** In a [binary search tree (BST)](../Binary Search Tree/), 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. +**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 Tree/) or [red-black tree](../Red-Black Tree/), 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. +**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. @@ -112,7 +112,7 @@ Is this a valid heap? The answer is yes! A sorted array from low-to-high is a va 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 Sort/). +> **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! @@ -162,7 +162,7 @@ All of the above take time **O(log n)** because shifting up or down is expensive - `buildHeap(array)`: Converts an (unsorted) array into a heap by repeatedly calling `insert()`. If you are smart about this, it can be done in **O(n)** time. -- [Heap sort](../Heap Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg n).** +- [Heap sort](../Heap%20Sort/). Since the heap is an array, we can use its unique properties to sort the array from low to high. Time: **O(n lg 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)**. @@ -289,7 +289,7 @@ Here, `elements` is the heap's own array. We walk backwards through this array, 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 Search Tree/), 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. +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: From 1eb61c97a7949a0088834759bd9b1f40d884a9e9 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 8 May 2017 05:16:23 -0700 Subject: [PATCH 0381/1039] Improves the wording for a few sentences. --- Union-Find/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Union-Find/README.markdown b/Union-Find/README.markdown index dfec7dbe6..a268f1d70 100644 --- a/Union-Find/README.markdown +++ b/Union-Find/README.markdown @@ -9,7 +9,7 @@ What do we mean by this? For example, the Union-Find data structure could be kee [ g, d, c ] [ i, j ] -These sets are disjoint because they have no members in common. +These sets are **disjoint** because they have no members in common. Union-Find supports three basic operations: @@ -24,7 +24,7 @@ The most common application of this data structure is keeping track of the conne ## 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: Variety implementation of Union-Find has been included in playground.__ +> __PS: Multiple implementations of Union-Find has been included in playground.__ ```swift public struct UnionFind { @@ -198,7 +198,7 @@ private mutating func setByIndex(_ index: Int) -> Int { ``` Path Compression helps keep trees very flat, thus find operation could take __ALMOST__ in __O(1)__ -## Complexity Summary of Variety Implementation +## Complexity Summary ##### To process N objects | Data Structure | Union | Find | From a087b19f146e32ac731fac5c4c989b1eff3c7401 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Mon, 8 May 2017 05:17:49 -0700 Subject: [PATCH 0382/1039] Fixes spelling. --- DiningPhilosophers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DiningPhilosophers/README.md b/DiningPhilosophers/README.md index 0bf4f28ce..e4db0d7e0 100755 --- a/DiningPhilosophers/README.md +++ b/DiningPhilosophers/README.md @@ -10,7 +10,7 @@ In computer science, the dining philosophers problem is often used in the concur 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 Semaphone on the Swift cross platform. +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 From 988e354fed9122acb0b7b7ec8098b0a29c374070 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 8 May 2017 18:54:43 -0400 Subject: [PATCH 0383/1039] Formatted headers in readme Github seems to require spaces between "#" and headings . --- Radix Sort/ReadMe.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Radix Sort/ReadMe.md b/Radix Sort/ReadMe.md index 5bdb931ca..ceb4459d7 100644 --- a/Radix Sort/ReadMe.md +++ b/Radix Sort/ReadMe.md @@ -2,19 +2,19 @@ Radix sort is a sorting algorithm that takes as input an array of integers and uses a sorting subroutine( that is often another efficient sorting algorith) to sort the integers by their radix, or rather their digit. Counting Sort, and Bucket Sort are often times used as the subroutine for Radix Sort. -##Example +## Example * Input Array: [170, 45, 75, 90, 802, 24, 2, 66] * Output Array (Sorted): [2, 24, 45, 66, 75, 90, 170, 802] -###Step 1: +### Step 1: The first step in this algorithm is to define the digit or rather the "base" or radix that we will use to sort. For this example we will let radix = 10, since the integers we are working with in the example are of base 10. -###Step 2: +### Step 2: The next step is to simply iterate n times (where n is the number of digits in the largest integer in the input array), and upon each iteration perform a sorting subroutine on the current digit in question. -###Algorithm in Action +### Algorithm in Action Let's take a look at our example input array. From 90730ade45d11947529e51acf15e09f1ef622596 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Tue, 16 May 2017 09:56:13 -0700 Subject: [PATCH 0384/1039] Fixes #464. --- Threaded Binary Tree/README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Threaded Binary Tree/README.markdown b/Threaded Binary Tree/README.markdown index 8a1c518f1..f631b86f9 100644 --- a/Threaded Binary Tree/README.markdown +++ b/Threaded Binary Tree/README.markdown @@ -267,9 +267,9 @@ something simple, like removing **7**, which has no children: 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`, +outdated) `rightThread`. Then we can just set **7**'s `parent`, `left`, `right`, `leftThread`, and `rightThread` to `nil`, effectively removing it from -the tree. +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: From cde6f854865d19c4cefb187894a4da09a0be4fee Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Wed, 17 May 2017 05:16:52 +0500 Subject: [PATCH 0385/1039] Fix a few typos in Heap/README --- Heap/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Heap/README.markdown b/Heap/README.markdown index a3b0038ab..bb7a785a5 100644 --- a/Heap/README.markdown +++ b/Heap/README.markdown @@ -21,7 +21,7 @@ An example: 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. +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. @@ -124,7 +124,7 @@ This heap has height 3, so it has 4 levels: ![Large heap](Images/LargeHeap.png) -A heap with *n* nodes has height *h = floor(log_2(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(log_2(15)) = floor(3.91) = 3`. +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`. @@ -303,7 +303,7 @@ Let's say we want to see if the heap contains the value `8` (it doesn't). We sta Despite this small optimization, searching is still an **O(n)** operation. -> **Note:** There is away 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. +> **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 From c014bd9a0823d6206fa18e915f6e4f01d5852beb Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 17 May 2017 03:19:47 +0300 Subject: [PATCH 0386/1039] remove "countingSort" func throws if you received empty array, just return empty array --- Counting Sort/CountingSort.swift | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Counting Sort/CountingSort.swift b/Counting Sort/CountingSort.swift index abece0213..725a634a4 100644 --- a/Counting Sort/CountingSort.swift +++ b/Counting Sort/CountingSort.swift @@ -6,14 +6,8 @@ // Copyright © 2016 Ali Hafizji. All rights reserved. // -enum CountingSortError: Error { - case arrayEmpty -} - -func countingSort(_ array: [Int]) throws -> [Int] { - guard array.count > 0 else { - throw CountingSortError.arrayEmpty - } +func countingSort(_ array: [Int])-> [Int] { + guard array.count > 0 else {return []} // Step 1 // Create an array to store the count of each element From d705414bbcf2eb62232d5c456befc193e397b208 Mon Sep 17 00:00:00 2001 From: Jawwad Ahmad Date: Wed, 17 May 2017 05:20:54 +0500 Subject: [PATCH 0387/1039] Update displayed code to use 2 space indentation --- Heap Sort/README.markdown | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Heap Sort/README.markdown b/Heap Sort/README.markdown index 7fdd8d2ca..a45dad6f9 100644 --- a/Heap Sort/README.markdown +++ b/Heap Sort/README.markdown @@ -48,13 +48,13 @@ 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 + 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 + } } ``` @@ -71,9 +71,9 @@ 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() + let reverseOrder = { i1, i2 in sort(i2, i1) } + var h = Heap(array: a, sort: reverseOrder) + return h.sort() } ``` From e311ee9b88a16d9dfaeacc7f2e7ea7825169fe8b Mon Sep 17 00:00:00 2001 From: Tobias Helmrich Date: Thu, 18 May 2017 21:52:38 +0900 Subject: [PATCH 0388/1039] Fix typos and markdown formatting --- Linear Regression/README.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Linear Regression/README.markdown b/Linear Regression/README.markdown index 1a1a1eb8b..29ac2e321 100644 --- a/Linear Regression/README.markdown +++ b/Linear Regression/README.markdown @@ -75,7 +75,7 @@ for n in 1...numberOfIterations { The program loops through each data point (each car age and car price). For each data point it adjusts the intercept and the slope to bring them closer to the correct values. The equations used in the code to adjust the intercept and the slope are based on moving in the direction of the maximal reduction of these variables. This is a *gradient descent*. -We want to minimse the square of the distance between the line and the points. We define a function `J` which represents this distance - for simplicity we consider only one point here. This function `J` is proprotional to `((slope.carAge + intercept) - carPrice)) ^ 2`. +We want to minimise the square of the distance between the line and the points. We define a function `J` which represents this distance - for simplicity we consider only one point here. This function `J` is proportional to `((slope.carAge + intercept) - carPrice)) ^ 2`. In order to move in the direction of maximal reduction, we take the partial derivative of this function with respect to the slope, and similarly for the intercept. We multiply these derivatives by our factor alpha and then use them to adjust the values of slope and intercept on each iteration. @@ -98,7 +98,7 @@ Here is the same data shown as a graph. Each of the blue lines on the graph repr After 18,000 iterations it looks as if the line is getting closer to what we would expect (just by looking) to be the correct line of best fit. Also, each additional 2,000 iterations has less and less effect on the final result - the values of the intercept and the slope are converging on the correct values. -##A closed form solution +## A closed form solution There is another way we can calculate the line of best fit, without having to do multiple iterations. We can solve the equations describing the least squares minimisation and just work out the intercept and slope directly. @@ -139,7 +139,7 @@ This function takes as arguments two arrays of Doubles, and returns a function w Using this line, we would predict a price for our 4 year old car of £6952. -##Summary +## 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. From d2f02efd49d2367382c7a6fffc5fa1e3b74c8eff Mon Sep 17 00:00:00 2001 From: Barbara Martina Rodeker Date: Sun, 21 May 2017 21:46:01 +0200 Subject: [PATCH 0389/1039] Initial Docs template and text --- Splay Tree/readme.md | 61 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md index 2282502fa..aa6bdd4db 100644 --- a/Splay Tree/readme.md +++ b/Splay Tree/readme.md @@ -1 +1,60 @@ -In progress +# Splay Tree +Splay tree is a data structure, structurally identitical to a Balanced Binary Search Tree. Every operation performed on a Splay Tree causes a readjustment in order to provide fast access to recently operated values. On every access, the tree is rearranged and the node accessed is moved to the root of the tree using a set of specific rotations, which together are referred to as **Splaying**. + + +## Rotations + +### Zig-Zig + +Given a node *a* if *a* is not the root, and *a* has a child *b*, and both *a* and *b* are left children or right children, a **Zig-Zig** is performed. + +### Zig-Zag + +Given a node *a* if *a* is not the root, and *a* has a child *b*, and *b* is the left child of *a* being the right child (or the opporsite), a **Zig-Zag** is performed. + +### Zig + +A **Zig** is performed when the node *a* to be rotated has the root as parent. + +## Splaying + +## Operations + +### Insertion + +### Deletion + +### Search + +## Examples + +### Example 1 + +### Example 2 + +### Example 3 + +## Advantages + +Splay trees provide an efficient way to quickly access elements that are frequently requested. This characteristic makes then a good choice to implement, for exmaple, caches or garbage collection algorithms, or in any other problem involving frequent access to a certain numbers of elements from a data set. + +## Disadvantages + +Splay tree are not perfectly balanced always, so in case of accessing all the elements in the tree in an increasing order, the height of the tree becomes *n*. + +## Time complexity + +| Case | Performance | +| ------------- |:-------------:| +| Average | O(log n) | +| Worst | n | + +With *n* being the number of items in the tree. + + +## See also + +[Splay Tree on Wikipedia](https://en.wikipedia.org/wiki/Splay_tree) +[Splay Tree by University of California in Berkeley - CS 61B Lecture 34](https://www.youtube.com/watch?v=G5QIXywcJlY) + +*Written for Swift Algorithm Club by Mike Taghavi and Matthijs Hollemans* From 7f751918b92881d93aabce634a891b95f46a90f0 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 21 May 2017 22:03:23 +0200 Subject: [PATCH 0390/1039] images for documentation --- Splay Tree/Images /zig.png | Bin 0 -> 7793 bytes Splay Tree/Images /zigzag1.png | Bin 0 -> 13964 bytes Splay Tree/Images /zigzag2.png | Bin 0 -> 13877 bytes Splay Tree/Images /zigzig1.png | Bin 0 -> 13855 bytes Splay Tree/Images /zigzig2.png | Bin 0 -> 15179 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Splay Tree/Images /zig.png create mode 100644 Splay Tree/Images /zigzag1.png create mode 100644 Splay Tree/Images /zigzag2.png create mode 100644 Splay Tree/Images /zigzig1.png create mode 100644 Splay Tree/Images /zigzig2.png diff --git a/Splay Tree/Images /zig.png b/Splay Tree/Images /zig.png new file mode 100644 index 0000000000000000000000000000000000000000..e21522b6fe55f9529b2f818a4e108cd47964908b GIT binary patch literal 7793 zcmY*;1yGcK)b8%Gz=Cu)OE-&j2}>y*QY+ovAdRpfQj&s%v~+_Y2q+;E(kVzwNS7cD z_x1mMcjn%md3WBO{pE@0ob#L*ZOte6xHPyR5C~sIS@9_d1cm_bl`t&eJDw+{8w6qy zS5cJH^EcZ!#ZDquB0XSH#saG_bLK08<-${R3fGw{;BwGZ7G)w<6#@!sMI@8;`QguTmsJ+;M24I zjDSwsKZ%5dWb21{D0yBSC4&8$->h9cM>-(oWMlA2z@JU>WtDr=B4y&h%}jggwimfA zbOb#QiTW*z-h2)|n>K8GaT|DC{uqo-kj_CDE-zb7z+|_d)mhsI+iaNvDJ3?<^9uQRZO$7D271gxvIm3 zPo$u1QVvb+NL+GGmTv{TiMgo)3+^kiQ%!z9)Zm5scx3!bM7YhWwR@)g#sx$ z3%Ezr;lShlu>uToUX=FD#Abi8LIibWUUwRgA(Uw4ujP25($CR!4ysHHJZN%2(P>PB z?chWw8spLBZmj9hYigk_;D>5JPfq1;K#+k9*z~JgOdib= ziTiuFtflsr*VEtT?Ca;7lR>@rkMRTl42w+@_Od8%0Q>3rzBRU*a2jutgvP7JF`=C)iYP|w@P{9_e0zxV*^N_RY zjC!05OKQBRO2gU`5;oP0fb2ZafA=MTfkxzB#Qpsebk1+vpM<`<{LP3hKBO@FZ);P6 z#}0(DU^?vfU?qn%r6Yv@TD+Lz7}=X8K&slDjQ)5twdTujM&ui2A)^W}MG+<~+6L(h zi4Xz-B2EkL)}99*SEr5%vn(WCx>~ZgjkRE%*k^Q$p63z*z zd*7f>+X{0~WSY&5P|)_fV(9&CbNTN}CVPoaBs_DupEs4yShPANR@tm@0&J=pmV;p?cg{^w^TeBK4%TAhQ1_#VFcrezN+rP#tk9yt2Hom8k ze!J+$9lao?(tMgn# zaS?-c^E+}LgR!4Y&W@KS8})6J zHF);v2>Q?Akm2m`(auK4Nryk1!z6)!o=`sDnPM_&`f~9r?haMAS!n}Lg6HQx3W`m! z$xiE&7P247RskO3XGxh0|I8aoO~$Dm2Kc^$Aa06kMgm8xxZgoG=VsvFy=PiOVlx~A zNDJL=<=^q&6$Qc`D)pgfs*U3WonXpVUg>~6iC!l9m<+z)alFzxFP+lp5yZ^?YlrfVsl0 zKZ!{+=)~L`%E-j+dAc=zXWVYbV+XI}N&-+br^29G)wI>8e(uf9rtJOAhuQMZ<_@#Z zfiF?83#l!6#?YIG`}56-GFMwHrX}n10Rlv`WVdRF&x)S|&kA4R)BfC3ar?9U;#xy| zKOc|U3a;%B_50iMaWWFXM@7aL7fh}TEjsC3m%a?ZrIgIS1P2(^S%8_69&^Zx6tDFq zVw>FnxE)JLAVtZlIgS<|tS5NdB8!a$dDqaNj$mBHedxZ_E*g|F-|qaQ=H(5HQvgy* zpWU~%w#Ef$#0$G&oc4qS?sA=O{z7HuL4vUC-33e65707jVoqSdK(F$GFbM#R%$}Ux z%g)mkX)Phwf5qP|D!VVW`MFy%W(eBG9t8&PH~lD6dBgrox<(hbX=l2U>yh11h7O3rm%rJ4xdez5ae=YwJK~*4i#N@Zhp;0xC)9eqv*TDk_+Q{@upf2v zp7zS3m4Z+`EM7oao+OYN#@6A(tFAA9=W*=O zX&c=A8I|RjN)blNaeOV6u4$Ph#XxI(SyNJ&Hoy6`qa1p7S?XWDqMJXc*}0<2IVwMk zcl2w`h@vl|sPXyk42To%fYbI82#LG>fm*{cfC0CN&vZ&+eEmk#`4L??>LJ09w1e07 zGDpfU))Znz;i1q?_6Sg2;qPY+6m%gDIp~H$!dmkVeqWr6&OD5^54hyqsJsk9V?jV5 zR|N`DJn}5dijrujruX0CDoGwG$YD`n%VbLXi zBSEktNm@^cgM+h4qj*VnqRjj)c(L{Q9M3rPkP4=7ge95_*$M_C zQTMA(vTVS$Q-oPUu1=xv(=?CoQr@zErkxV%f5S0~!T)UnTXlkIVwmL|OsQ`P*Dkl8 zD$$_r{wyk^zA6z$mq;t>k`KVTzhE|^0&!?$1G`7ypD{e8 z6f#b}6M_~E@m#p^8}(5IsGoj~NoE3_1ao(BHAL>|(n?v33~>T}+jl^p7|5eVzvYj_j-l!5>J0eZga04$){hjaz0g#c!daRrwVB zl54uozaO;=dA6f^*Iqgl{E-Zo6BKUdrh z29Mm8p)LIjm>*+uZKROoK5P(L%}6FwPx%|4de#qeO`VU3-vNBm>c<&yA6$1;EJ%72 z-a!>89EX&>MVj6T8GkbQz4yV6hMl^;t2SXga4Up+CU zIA=k*fji|k-fBO^TtLcya!+94WJmpq-;i+qsu`(>B&Q!WeB5_eX-T%QnSdg;$#@T} zC)~nCI_WCOVekdiD^H?G2P{H{>>+$wgxHA$O*0nZqf;XN3cZ*HyJ2o_FP8VBNHBqM ziy07lx%A(KY-erEZZ@ckL@_fn>)Lbh=#_=9YTGSB$?VX@%dzzy(-rzmi&NmT{tro0 zi6HBOZ2ER1{BS=Wyn>7SU}1sciV^AcK4a*j8;-n6U{5r0s;H~cDrntSp2mNHYQ?Ts zb%mDp0ezCpM@QJ>@ZnCx%M}JF1v#IQ-Y%PUbGQYoBKuV)6^t%LrrUg#{?!MQDpF)E zkef_Z=<{gtk~579&|H18gJ7T|DsXv3Ufb1S^>KHxhoc^3YkijIqN>sy36H9-Ud9vN~tzO_WYP6AZSk2`C7kSj^+Z+@#N!lqad*ai z-qT>cl2aV&BB$s>dz|4G?#vcMt=hsOm`r^BTU42W*m1hjkV8C>3QDQdE-mnM0590n zLSo=mCpps$mbRJ`Rq)Mm-#2m!U!+<7<9M2wN=<*-t7PCpNs?y%dh0lEI~a95>Wsc# z_B%uE3xHAz^Ncj?7(dw)1Va!lJSSw7;oaf?H-SuzUWLV@`2nI{`z4YXRds!Sc!)D7 zVuhWAN9OlqRT_&!Gn>;($iHitMkm+<65d?E7=uO@OabYZbMhlB<8|eivrrJYVRHqu zJ5ygQoX-NNj|wYDnR$nM2v%l6@G#@5gLQj^HWnoE=jG8?!Ut_gVXpTjnmOFQgh&2D zs#!eQh1)fj3yL`PKnPbNSA9(n-op&NIgZ+{UkE(j?(vj)1;z!# z4PgAWWg`)k2oog>o{%S#SQ1$E52yqz!ZwEFm5skRPO@8ajA#DKLW$Q1G0OhUMfccp z-3`AJ`=-_sbnXUJD6Ar`KlO?#pJpBs4hSVvJUHm;&xt|>ge5ON+=sk}JjC25Ar8hS zWFWgEdclkZ8JIArCx6_HBfdq2;A~$3;a^oe z-L>3DMk@SO*DVe!coMHG$7}2PkFF2eTVO&;Q`9d8}JiB(MnWtwwlBo_kX5*CSwwsdr)3bJ0 zN}F&hy#JlT>RKx?rfl@F*sWUv^=wDmi-j)6LilC<4@3_Vt}oo+o7?$wc!QRB<|CT|`pBTvTb!*R-7w zk&8b~8X7kx-MjSlj#RO*|+CYgOCy ze0Pe8d*NF317Bzzxj)x^p}w3T5o#s-;CzMR?Rp?7{jGons8^r)7r#}G2{vTm2Rkb( zRC*1d4><2!gDDYaCVH>C{^FtGucES#-Tiw9s-BXnth5I8DrI$yg!+9I5=yx%*2*&@ zBcE2f*Bclmha=fgEd7|{uF5o-CzxVpKEb8Xs3IiTJb)}hICx`sy0SFZa2?Y;z&6gW z%$mbWq`e}PTWJMGbaQuo$jq=9ovUD}z4lEh#J}w&^INRCz1ez}XQw80SEmMjf8wVTPl0zk&uNYm1Cm|5S{a`{rcufBKimOjzkh zBvJeQ-8J)XhLico!G+zPUnvRbOE@Kc7>bF;Cq?x7`w~;|5ZqWCvzSw1qiL3?vRCF=f0%l5C5$5*{@t&dvXQNzm zYT$4JddcWm(Tn2YWR@sh?`G+d|A$Oqy7pX?96TwsYAndy{fU~Eg?)d^r-p$| zAbhsFv)(=QI?_CuTF7n;je*VJZ}J42Qph>>n|-&0$G3_*3BD(T$S_JwhZW{&MTCz}z!`Vq{)kkDnqSp!o@uVq{1ORKJ~!cOL9=pa${4OXdeD%z+P};@ zw{nx#F{J+JyhzThz9!VIpT`NFA>#a&Gw_qm0EyUUrH^{*QFuJYbd30T^iu=l9XiWp z52V6=Bx<^YM#L#PI7U-f4+$a?_uWIO|MpU7oZGGKIBY$3E!HQWALvRAPc-KsEQ?i|Sw=ijBHg7Z})NAx4AF8^sCy zFJs5J6IaZ`jQn9)R$fuS+9O-$D0o<(0ie4_+q|r5uB!pjW1Eo=D8KKdTt6HD&&ZPG z)@p8}%{RgaFT!b@{sTsfL!6i$X)-CifI{WqjPQ>YXKLG%!m8B7eO zBjV%>()mrFJ|a864<)F(yDh~9Mrp&te!v@A;Wp{pGT21gX|ka&h%E<--U4SKJTYv# z!^DKFgI~^9ClvHJ=?nNAwmj-jFuG<|grBFezIK8=4|g4&v` zx5gwQhVW=O$lF1Bm#Kv6l>VS@~#a|igeLZEo$qHHn5?oVNh>$gsl@V2Yvmzxjx zaHm8O&wZg zraD>x!h((8_~UDXY9m`$Q5m=CLZt^g0G5fkFD>+$)HVAQMOfc{=vBzPq7-wUsp`=! z)g%_|5mf2}&+66Dda&I3_y|p(Z_j<5-)Qh3GsKSaii-P)P~Oh#UB7GMrT zhA@NF7$tqmqIYb7Ya|MuA!^jp`D1_+6!V+5D$0_6<4Y1EA~uBGM!qMlpe)sRXK-A$ z*>-=imguB6QFw4_ogc;MO{`Q>t8Q;f+mI)}+UVGr#&aXgv39@6quyg_`DnJs3H71{WFdtA5 zL8yJ0U8n(>(9imQZC%Kh!$_9VNVi}d@p3V@{+^D|lH6i^y;0X4VbLrQwi1Wc>(I=Z!vd$6u>IO;G9N{Wn1KFZXWFNFac;G z1``6TT6B9dh>%q8d*l6&Y}qaf1rU#1HWrHr1kVoww8Lbh8E!1`^m?r$*=bQD1(1S> z^UTdZLc!CGpL1b$HmfUcC&zDz_=kFH8dD`8`NEN#N&TAMcAqtKRruCon;1aB@q+LG z=7eG;(R9dr^wDq0AlqZDd3vxo-d7Evq~r8ESYRfQZ(fU2SM)V~Z;};uAQk?}`**D3 z7x9X45VVfcW%*0a3h_4kz?7`3D|D9s*G;r35^%Gox``69)*+#+ceopyv#ql*JcgnL zVk*&afV+r(&utRKV_2gOP%uS+Ww#AT0>}TkL}Q`$HYo{Cm*XKV0Gk)4uW=J#%rr1I z6#4$G>-i@U7$(&JIJu9MI0d+9(U*|x2>=BZWpF_e?^t#38&6r3)z!&f;FtNnN%c@1 z1INTm47B$>*DY9}GZvE#PZb3pVYP(=)E7*YoZkd>ksy82&*Ijg@tO}%$}0l;tmul4 zUh4j{=>P|a;G;I_MwfD3dQq2*GRf+;JEjj}B;hN4%9N#|nOA-FSfW!#CAH1*j{dD& zeKaV_JoVePErne#c;>jdXvyk!2|$UM1_MTau+kL~15jzDKH zLg*xYqEYu%$66(KF?dRVfsy(Bbz6=zvW}9fPRfMU6SmA*H1vUII<_u3jPIdDJ$-$; zF(hn|CEanY!BD=WN}}!znUL0d3Piv+08fPU{^7}NgY5&2OhKiEG{MX@kS|7^PsdUB zgH4(vT_%anE6UGa{WBd%(}>gU$;q?bA2^pAncdzXG)KV6dciv}cfm@a0Rcc5%YR6> zB7hc9XCa%sX}mdSUC0%4nMDFFe75|HygCCIWc}YDfJ>G)Zgyjv%D2WHMH`w0L;__w zv*5JAz$$1rFF>YZ>>oUP<4z}?A1=GUcq|h_Vp$d~qfi~lE&(8%(C8ELD@qVV9b?Wv z*#+#_l@ab8_Gop=5o_1nW~pN0UzBKf{lC0Kk|*T=pOD>9KX1wqAeeqU{o>GpFwo@6 z=|n*!x^d(DV3CyCHFN484%6QTfnWmo>rh1kQ1e>#bXiuDSy!UVTtf_=h`JLXjB|LX z{_ekM=S@5T*T|KAR^9VxN{ZwuTuv!ZCPZ4;*`?Ag`AkPXGRzTvKtmnjz43iR z!!agrEi zlWOv3u=TkK$8KI=c?JZcZVgcEKtzz#@nD_7$&V`J21uINv*JLz5Fm9?vZVpUlnQ!+ z$(*D5X3&n1dr=Rl>sz1ivbQ-OjIsj(#zjy-{ZCmK=oV-hMEM>pP`{DF*n{rOR1d=Q zHJ4q^hpz13MaoG<)4*O^Lv9Xq2sP75HhgC>zQR>a6KTZ~5;1(KwzZAvNKyCeg7YLq z7Pvs!NrWK$F1s4rSNW2s8z6NbXj^~H_bckZ;xIILi|)+8N?|?SnN|~L42WN;0(fTW zzobW5D=9zohLWm^Fl(23p*H;J|T2TBuv^ zOqC1!A6d{mw1O5)RP#gENK~DHZeff<%yZ({@PN9zXVw)yaDkGC!51Dnm@ouG#m82q z{^M7sonc@M@efJH@*b8ZfX`;s-~nPK19koX6)D&ds7Svt0zDigfx2gy0vU$Ew}lfJ9;pJ&5uD3H7F;6Z8*QWx(30ggZEakB{_cl+GGLhJ)aSB( YUzYE4d4Gxltz?jjlBQyfyhZr`0hMWjJpcdz literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /zigzag1.png b/Splay Tree/Images /zigzag1.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd40624802f9bbafa93472c6d3b8ec37711d0bc GIT binary patch literal 13964 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 W8y_a@5`1NbBL7lJrbNov@BaW;q?*+L literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /zigzag2.png b/Splay Tree/Images /zigzag2.png new file mode 100644 index 0000000000000000000000000000000000000000..5f8e4c63f9763560028d3088396d3e24b5787b4a GIT binary patch literal 13877 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 literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /zigzig1.png b/Splay Tree/Images /zigzig1.png new file mode 100644 index 0000000000000000000000000000000000000000..11ec330f2a33a56b5cb2aa983f05d7b9ed7b97c1 GIT binary patch literal 13855 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 LH5H2GUikfg>;GAg literal 0 HcmV?d00001 From 6c1c12651247ed73e3e727c0e7dc28e2a0b1e518 Mon Sep 17 00:00:00 2001 From: barbara Date: Sun, 21 May 2017 22:17:44 +0200 Subject: [PATCH 0391/1039] Images for examples documentation --- Splay Tree/Images /example1-1.png | Bin 0 -> 13964 bytes Splay Tree/Images /example1-2.png | Bin 0 -> 15451 bytes Splay Tree/Images /example1-3.png | Bin 0 -> 14778 bytes Splay Tree/Images /examplezig.svg | 2 ++ Splay Tree/Images /examplezig1.png | Bin 0 -> 6583 bytes Splay Tree/Images /examplezig2.png | Bin 0 -> 9317 bytes Splay Tree/Images /examplezigzig.svg | 2 ++ Splay Tree/Images /examplezigzig1.png | Bin 0 -> 13855 bytes Splay Tree/Images /examplezigzig2.png | Bin 0 -> 15247 bytes Splay Tree/Images /examplezigzig3.png | Bin 0 -> 18128 bytes 10 files changed, 4 insertions(+) create mode 100644 Splay Tree/Images /example1-1.png create mode 100644 Splay Tree/Images /example1-2.png create mode 100644 Splay Tree/Images /example1-3.png create mode 100644 Splay Tree/Images /examplezig.svg create mode 100644 Splay Tree/Images /examplezig1.png create mode 100644 Splay Tree/Images /examplezig2.png create mode 100644 Splay Tree/Images /examplezigzig.svg create mode 100644 Splay Tree/Images /examplezigzig1.png create mode 100644 Splay Tree/Images /examplezigzig2.png create mode 100644 Splay Tree/Images /examplezigzig3.png diff --git a/Splay Tree/Images /example1-1.png b/Splay Tree/Images /example1-1.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd40624802f9bbafa93472c6d3b8ec37711d0bc GIT binary patch literal 13964 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 W8y_a@5`1NbBL7lJrbNov@BaW;q?*+L literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /example1-2.png b/Splay Tree/Images /example1-2.png new file mode 100644 index 0000000000000000000000000000000000000000..46dd35bcd131dc43f7edb45a9efe7c6c585950f0 GIT binary patch literal 15451 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 TFbIB=iK8U1CRZY38t{JrK7T3H literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /examplezig.svg b/Splay Tree/Images /examplezig.svg new file mode 100644 index 000000000..800ef1886 --- /dev/null +++ b/Splay Tree/Images /examplezig.svg @@ -0,0 +1,2 @@ + +
2
2
6
6
10
10
2
2
6
6
10
10
\ No newline at end of file diff --git a/Splay Tree/Images /examplezig1.png b/Splay Tree/Images /examplezig1.png new file mode 100644 index 0000000000000000000000000000000000000000..dda9d6de91d4dcd011fcc9356ee305a8c0eb68e1 GIT binary patch literal 6583 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 U21jw=A2I}Y(05T)YIYI-53Dwf-2eap literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /examplezig2.png b/Splay Tree/Images /examplezig2.png new file mode 100644 index 0000000000000000000000000000000000000000..ba8a48867103c53ac775bd74046d239deaf747eb GIT binary patch literal 9317 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 literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /examplezigzig.svg b/Splay Tree/Images /examplezigzig.svg new file mode 100644 index 000000000..7bd4dcf6f --- /dev/null +++ b/Splay Tree/Images /examplezigzig.svg @@ -0,0 +1,2 @@ + +
4
4
3
3
9
9
2
2
7
7
20
20
2 - ZIG
2 - ZIG
1 - ZIG
1 - ZIG
9
9
7
7
20
20
4
4
2
2
3
3
9
9
7
7
20
20
4
4
2
2
3
3
\ No newline at end of file diff --git a/Splay Tree/Images /examplezigzig1.png b/Splay Tree/Images /examplezigzig1.png new file mode 100644 index 0000000000000000000000000000000000000000..11ec330f2a33a56b5cb2aa983f05d7b9ed7b97c1 GIT binary patch literal 13855 zcmY*=WmHvNyS9`xlG4)M4N@ZAUDAzoC`fmAcb9ZG2&nW1r9n~}B&3`DO`hj{&pF=@ zhhuEko^$QF=De@CuN9%9B#n+jg!1g!Gjv%Q3AJa>VA#PwLZs*56HFZs^k>h=pUFyy zX?!v~%t4*kR=*t7mc;5nW27!cE%9JXRGCOZBcjAYXDpYJm2rn^6n^02=CMg;O@8}c zAxM^}ggx4vF(cCD&sW@}Qu>FyALDF2SBE~UtL@NBfu81EtK2!KaS1O=}c{I6F1j;CC+GIhFIPn(F_8gudSPt*=CY=3g^`qne({f_8XNt$6| ze-!@cWQqJ%RpWS~=f!?T&rGFun!2*ECZkrB^$^NrU>7;Z5SrRz$Hz+V+r6>|-v>|K zM$4Eg{r1Uw`^n-6ZrfP})}DJ8ft_sEb%e+-_T!ZK@GpZ3pjSOm7G>d!WJm_rV7zM7 zOO|4fvu&3NN&I2wLDHR0MCik@-`2&PQJQ4b%i*sfsOWpm@28|3I`(MGRf|H8FPmW` z$(iAkd%wQr^>@p7|8NrLmuxYbI?U3#M9H`EsfgQdp4~q+%3-~_btQ43(P}iBkgM2v zW5DI^ur(_qBa_mY7*@`>B_=%lev8d7LA6L~m~YjaYPsWM(s+)b)gcR=axOCttwMZ* z#i-ozO7|9D&yC{jiX>ST(x&tqWC&#*If1D4Px6H}=c4nRb{wg7R8rCL6`GYJ z@f6|;e~lEehIqjw3$Ft5a$h*dyb^vFib2XK>~-0+S&iWrQ*Smn(i;F*qFrkkIy8+N zU5i(E_Lln9d>km?Qu`p zkMpED0*5a1jmJ_ndT5P7CyH}}QqJrC!;1?a9Djdooz&;`%6THRdA1|T3@%6QJC=Ja z_oA0M?kfqgq=K0SBMDT}w~i`$D)9Q``S9DYRr#zmG=Zd2up45V&IlKVhKm$&(ddY7 zjI!M->hOhc-ykzH7W;XQ^UUc}ZH=a-m8+LY-EaOSbN^G_Is!&Cf4sl>Evk^0j}#t` ztrP6<%tNz6W0<;(b|!qwexX59mbo0xPPZqymy!rGHAb4mS%T8a@P@*iw#9K(#6U@E zQ?LD=fTj*fD$oBRjLerF^(Axo+Iu&lLhx+W8Z8yk4;DE{B79J3>f*yvH6o^MPLGbe6X0Q z(1d9vfo|_lms5QUd!eoR{rW`-kFW|X>L>b4UV9r{T03kiw6>_+tc?S@5j^=+=98t+ zmCs1URN!dki{`WT9sKFOT0yOwG3WVsxnPy0n{IPJXRF^hLrhcmEP?Ja#L}CW=K$_N ziC&Qd&Mc$4zD{LrtX(Rl7naCHF3-TJ58-r1+X!LW)Fn&ccQB55eNmn^}idR0XF+|nk}p9~zx`}{OFwv_sb>&QX}vp2Qb&6b}9 zBTNzS`etxpM3LwNZp4nuyadkXTkQ3cJZiVmU^vgL#xhH+sB`*CwDAJLDnF~?0Ec(s zi%%yjnSt>z=jnGG z@{I_%2Uw>FwGz3EywfGFM2ozwePqF>H-JdLpqOJAp zO(>p~O`;_nW9O0VMFl6;P({8Iv0rmqD@n&n}k(TWaxMvEmf3yZP)P0;o4>t3+F zwv6Z(N6UiQh}3N}VBck+NSO^p%Q~?&+nP}3bFt^`x_E!~xx1XK&}7PE*;+X~+a61L zKUKO{U${hk+v`~czl|f;bd;djqI;J6ZOe6MJOz==TO|^o?Wl3EZ#mXdWhv4p zF;Hz#ZQfsLl&kfB@3qr3e7Ib63^DcqOP6Dg;qAWrlOjFLhA9FRCdiJ{F9Nv5Myoh|ufyhskAJkp7^p1p z7&X{SRz}j;jvMFtmU1Hlgl~6?wwW2Y`af(8!X(-*cQh|ZYO2GZg2S^tMQ67fQtb6- zu9lD5SPzZa2R|`KEwzn75PWBAgsGPML@+hgCi0Eg(>^|r;@=FQaQ9iXZ_TiI!;5e- zb=GU>b;yHLW`^uBtty=nlQ2;vZELTX_n2|Mn9}PVTW7iMg~;wlDOiSZZ|7D@hEcsA;DK02F3j#miYkvX zyO8c)mE>6lju%yBWYv+_dBsqs2(ftRj&{#&%3atW(g?88nEeYh6uqy=Z)d*GEu?!v zl0JojFBDa1Ml1ypNN7^##Iz3zzjvn(KwvL?hd(JCE;bu74KBP-asd~!?Mc^$PwVX#8elEO^lW$sIEoQaU&1eU zwOA2?vj>BYH29IVZ4FkPOs(1)UL{MX-ZW(Tvnmzt=kyq{L=sug`;$S%iIieO%J|Q* zb#T5AjzQ{buh_dH_-%p;2);{I`2JFkp!>MDbF3kU$EmpqBKF7mx){QhBxMnXsWRoX zDAo@8ronnUQhulW^W#;cSm8?@?H?2-tpGT`G6dgC#Zqw1SdL{P7c2bUT<&zw+R0x_ z;2dvnu-pEn&jm`T^gW)mSkG4Jo-VFF&eBg64q-JF z?7ScpJ^v}5TM{{2t>-R-o1{xc6Em@U!w$p6+itFy$1|L%}Gi9)zaL)Fgv8Qw~6rH#ju&LASEXQ|67cU8h z2#M5SQ3>9sN<+Rn*)(?{)oGYs_Hzo_cs*RqZ8eOtChg>Uje8%65pmH}Fx}uqne$41 zWU_RHdyd9lo33P>M61Y&V6HYQZE5RK*AI-56Too}rf6D71pb5Z;JWo3TtD zbZ5Y3`9`G4E~^G#c`4-j-o9@{B}&GVG~UfHaPG%DJsoAs8dMd>U6tXh*<0!E)aB)L zRi^7ZZ(+#4@5eVn^68zA*i>MU*WE`1dz`26S1cM4w+zzwc&@PE&P3bE0C5Q9jzTE z74=^+83-j4cAS>Nn6{XLg?Zkm5eow6*x%{8H*WvbvSAXXwhxl|dFKkT=Z5TVtUg}0 zieLSV0|Ft_ua<*7tBV=tIM9@-Q|i0O(8e$x74Nrk{kT`c#p-2BT5eex==F4|ZO)BP z8o?4VaZ|J5#C3){oUCu?YHw=r{`Jn}f)FDbRvVdsi#a@!mlwQX;S16Gy5T&vC^~Sy zv0{i9uk2!!b6)cl(pesJ*d1~SrgNA{T^fG7v?CRp{_Y-A1vbhF!ap@I8EI^* z7L$%IZ_%*2VeEJPjSTV}t_*&9Jq$2~U^6KfrbI#brX+qGv+e!?1ZToTtqo&A_ap8A z7tW=m&+o9pIR2i+${G9qbag(4KCD7B%qZ-Z8?%Flu4k0r8t3WKSe=uzrp9FRQRnUT zA(DLvP`PBapQ%WB!VpXS>GcpW4g7}WOJ3w~^WCI35m@um-GPVq{Ej|JjA9r#``G3F z4=whK3IoE@2J4u5l;{EeBGRA!{oWAxo?Ex)1%zVz-i5VT$En7C{d+{cf*Xx&%9+P! zp-ttKwV&K!zqD)g8NlLW5L)<+aRr%Q4o#4>dKy0FR=M9v0$gJYBs`L~i;Y_cn#m_X z8=H#~zg#Ybaobv+WL(LmrQZE`CGh3!^~naRqFVQ#nob4F8ysaJEY6X~tT~HfKeWb) zKy01x&&pZ6W0?5VDZ~7N0-opAgs(q*o?(3XSuS7XSEV+av=#9}o&ONOpLOFN=j8ST z!~Jq{?^_~1>c9v%tQ|_KaeILkic8xjBYG?qZYf2h4mfCtFX{-y!*VAa1wIx zI|!;%e=ALn!+w4{a;)$%kdg}d;PgWk78OH&N{v9C_HlhH0xF6nN6Iv)?n*|L~ znJq}H?-fc$ng9M8B30N14y7eBvBn-3oBY0i7_FIWM>GT};Uhjc_CnO~)vCti$4qEu z;{F+g(jRqF3v4AbpZlq9nd3K__D8DK=nEu$c}6JaS?n7B@e5!YCiqyS?%c&Pu4`rcmT>L%Z0M1+wjIf&+4rcs~;E!P9uvfLnB8Zb;zmZI^@Hv@TW83H^#mo%mKO z{^ce@gqUSKQAE>jgLb8sqRmW&Mc_%cQS=CBNs7e9s}N!7w1kCMFz!FJVO_(t3$zCr zoVoH@y=+Q9e>YS{f9|brLny0ei#dAcZ={?x`gAy+vGzrWS&$$$Z8&|P^=G}a2`thi zxwpK@eEn{#vd`af*228kKXg7DT)8%I_}Ar`!R4~V?Qgf$7=$H%Rw}sX+~2p8d%Xik zRf*gXHz>(A8ao44##tFVb4W@WhCdL#pR&e%V3ji#8HijHke5zmue!zMagMR4rSYp{b@N z=(-|mztDnpMVRZ0vR{=v`&m-8V)}=bb#%zKrhNdHPOA|I(Au;OQ?FM^qenWf?J*u7 zvJrCl9CI0)-)+!@^~lU3D{u|7T*ihQDJpYHpnZaUg)b1Wr~3u|lVZ5R&&Fbkz^vX< zDhhT@b(#E~;AtAoGbH5sU|wRzfbv|;x81ax4&}M;hMv)VzEMF^z>~z;q|n`uB!l^0 zd}EXvO8znqJ-Jt7O8BMOtEjYdO8;~TXjH$k#R&}@6?=6>QopLgZc%fE`ddWaUWXf6 z_G(*#HEV12Fp7BDXB@+iWk>OZFh=mDDJ5KRRod6$J{uRDtT&S`LJ)P?l$m-F+mg>35ZZ}?Yw2e#&>h@k0XJdRUU(L-FnEezoU^pLoI^ot=NWSjEm(| z6f?wIWRd0tN#Cb3#t`vvYPJY|+}}Ls?PfKGpN39DBVEcVk)!?H06r>0D8|dN4SN{W zn8PEw?~XcYovL24!0!9)`(+5#$iQ|2RUebh8qlxL!^=$nx6b?KR6m5=_CX7Z(`Zuq zsNIJ8QqDNrUcc2L2Le#u7Q=2d$g%50O5hB_Wib>_(bA>1zAFB3yhEV{b(J+X7drbR zz4kb*uB>=Jm{=Z^=X+a@yvv0;bsLxQ^Ax%|13fkU{J4|YJ9I_)zRv1L?qfFx1xqxk z;4F2kO`^#)T*ae1|G>TDrR-h!F`PsZ5cZSwtOw&L#p5w)$$%%|LK3moQTw<>K^ zpF_4Qwd?ta*HQbR%#nY_J9h9O1qM|gYM;Rh{;6t=o|O0&ik?H2QKbFlVpcEEv_F%_ z)&)0Ut+N^orhd`m4L^|42mmw_;>BZy6rUk#JIgFgwTD(iS*r$heNlM3Dh7dIyUf>_ zH2B=P8HjZJr7At4%l%Y{M!??NZ{Yb}3{2R5g?iD$4Qsp7)&4A;*7~(OwHsvwKI^-t zp&La{i-4yq+|iz{VA8BeUhsj?bhBNtCS75if1OAF)#+ZlTI%xXdm(zon*Vr(6VMF= zHe$zzy~5$jBOe(V#%%8Qi4$n*XQ9vDx$gU|)Tu*p7bcLK6MXXoc=JDN6LnR_F4i?UyrG$E39UY?glYFrSGNv>T0@#iV0fL`F4|rIL zB}`ym{t9RWZs+ZO<%=fARl|49He0XyNP5gxx;!}Te{l#deV*=n~GuG->Ji?JS{cw8w28 zXO?<~3~tA&C31K;aE)V7nYi}zN%sJ>AqGsrypE4^ik+2W})d zgvw8j^9!NB{>}u{zVUUxe>!GxT2whv`erB#Y~kJj2c!B^9{(43v-d^NWv6fGlZBF~ zja~ge*NFsNit8AA+3eY$Mx~KU=6}PQ#1fR~5)DK_ru*xSXf8-krhscH8tH2dty)8S z#^6QcyQ^b-m-Nr;)!XPW1CvtFpx)OXcFDE%okRBKm)cz|z6K+o?pM~zovinFf8<^3 ze0nw!NM#YQp}cL|P7Wx4)N(Q!!!)exhk={%+@H5wt!kxT>s~6Ffa0ktYa4n=t~!g-~EYNgSjjY zoL-w#0kXyXdepw(%j36~yA$HP4omcLK&R%Og${+!ufOR)-OTH?TMp?0eDBHZ53S?1 z|7AWMY4qtgf&ldX?7{tY{!1|77#vmUG=LJ1(_y+ZG#+``$ivf7>!A0qVxg*aJTDG_ zyYNzj^BSu^{+ia_kcoVVD&pEWmT~<(UFE$=S-XC_%cCH%6Y9Pn z@F>#c_jI|9{$^xdFc-U{%|JC`zII-P6Bu}F7X3vi_zdice-1$Tt8{lnHDTK0`H~|I zVfJH!3g|;|L~UgHQH~5A$FiB$Jn6pQQN0FKFg$}{zaVq-h*XAW`2Tz^53m(wV&6!$D1X=_}MMjI9(HWaJ&cA9@t`fucfP_50)aDI2&B6vJJ~0 zcW@c7p6V4R2m9mkT3^ssmgAR+^%ji#@I9}E1`Bjcn?CYz3f_!+C3sY6 zal=jr>Hljwh!>zB0Sw!DQvt<$V|>pP`%xvQ6IgZQ6OekQgf>e=Bm??pV=NWuXmr`F zkzq6j3&qWxwZjE)6{412{+6bGfk7s+G^AIF5aoYsWGOTQjU;D(RG%tU978)O&2kut zwv06hpvCR+2QKb#eXjJJ!9~y4dM&6RNtO^7`y zjVO-=%ofJ%&Vv(X_S6xO~-r{Y6Mg=Wan2^s~+w2htmnB5T+h}7_?4qYF zTBGTBFTM8@%c(0PK!>s=&!$@9$Eo?c`38%qZLg3Q&41`NBcV^A@OEYHeOV4|S)Ol) zW;4CPi+4kOZIpGm5vn@85nLRWhJtPfDyJw5d-vQgB50POh8|mZ4622}`5!Kp-B*$K zasID&$(syH)EeTz_oY9Xy=tSfP2c#lQi6L$V7$hC3r|W$rS5#Pw#*YB;v&zjeGiw~ zxqcX9el3`H0CnEtXsP}3g$BIiZbYwIfX_5ssX_+!A6!&5n%8az*3&fH#$*A52ZDxG+vhn2^?kvyEmKO4*OBP)=}o){@bIf75_(uRsk8> z0N{d9)VGVad?2n9quV+0;ke^ZO%lG5x2jw!Gs6$zt85DP=pIl-V^2OKT$IGa)nU)r8ZU2RI_xW00mMyh~v@gxce%z z=lihBGAtFlzl7v7Y1r#8K6meEB8Ni1g=0|_1N9WzrlCpcQIjVD{R2$?1!gloPK!$I zTHYl1@WWWaqxj024#vx%;ca+gu6Z`!6V$;6qFIoPdf~~u9GdNADSOp6Ex%LTP3#xy}|8Wat?kqK5{vw;x-PXD*(eH2dSVQ4^1hH z+Vcm%zAe|l%$)&8O?)nC;V)>IVl@37$6yYgt>U#*Ugktc~S-@ZnI zm&zPE_Pr9MTIh#bm1jEy7hb!eW)7Da;Ufo>h{hXG5x4<>ZuqdLrjFHR*zLK^mN9T( zs#T?{`Hshw z3`Qfbm3t{z6U&ROH;>Pr;r)8b0x(8ere#vDAp{iO$Mp)x6UiLRo5eM+K(8r8fswbl zm1e}Nrs5l2C<57MKmU7usW#v)i-Ii`OSHp-+JJBPsV_Uv^5b`SDhmeKAY9NgFy$gN zp?SW7Nw_LHkeEn>>kSRjokeEG8EUi~<8%@6gWj#asQ*yvb>71S>x*UV@hxmrZ5#Ac z(g3B`JnDh^{=vx=D7pu}>nK3NJ!IIxYoMT#q+fY_hvXuy@8qF#EEx9(pWru)_DsZg zl;%^P;0DxlZ`oOSMjuA8ePREx!H>7KW{>j@PgLL26U)`L!K2QcoayWVHKmT zdaVT@Do6==1g9Ce>FU(3bsBJ9XDly)7E;YG)4hTE*GRn4q@wkP>1J z0o?42z69dTRW*32rKmsQwFzi>4)OF{BNCVdq@93Gj-4hRYVt^uqruZEW||M7u8)vu zC=9Wb4Ub!vKlm*M zX24kx+cJm1nR(p_l6y*gEIy8}le8l7iXd1TMY2QaCwL@|>|4XN@yE?{k?jN{Qf=EcHf_@Vp)>5_Qv^ zz~DBp7hfNi8I~cDg!(7Z6yeOPs95kmFW_)BzOf8)UdtkX-L56uJdZ^HC-z9dRe!(O zC`(FxsQnkI&4BZ@2i&>{CSmzA$WTL0+z`e-^zo`k;?GilVy_deVy)Au>>kez*55|+ z50Tq#&Kr=)L}r)p1JI5A;AxvbhXt|HJ_&jug4AS?MHIyn08?11J-;b;*(0waFGVLz zgO#;FP#6`j(_-3^ZS$Kz*<`p>>DKg&r=FJGf94z|Yk4%+9o1}jx7eN9gOk`y8-r5( zC%K&2x2Wa2;(;hLWn=!JQf-MF+3$aJRhbEM$OFH>;No?0r(~<7J02LAUbevB0ZOmHN+6LdArBwG!JcWDAaQlR zQf3Dhx{G6BJDz|;UnaW5B0V%1osrdIBpLaPL-)NP2mEtSa48;H!+t>vnB6~6iBKZc ziCp5PR{gti$%cq{3DqAGSOiK%dw5DBIp&6D8;KLhljdVMyMyU59y2S92f9rW)R^WO z-0~y=9B;r_+IWX~N4dTTDs+xkL7Tb$sbPL#w1d4na?m>H)e&KrZ_-bpeS5Hm)5dMJzbt`=b4WO@?R z2nt8^h-Kh$DLHV-%eYbh0Qm{&xxwFsfE7F!pJG~HOY~Uf&;}1s3Z+>yJenO@VxUx0 zHMHx6fMx57XJyj1nX{r276Db^9$x)l`Lo0h^AEgQ(?--kl`G%_e7W~fIo&8Gx}{5a z7*bu~2YTOohCCcq%1d3DNt~dEqal-qqrH{qtC&}Z31?i8tuBe8 z_{%~D?S@3A$`AVJK}5Z)yeu7zkz_0&YmAl+Hulb!4s$dI1xyuc5vlCxYl0KDXdzBF zc81qk@T0o0W`AXB*T@fn#7JUKtv?E4CHzMCCC$ip0h4erfgGTFDzeL*oi$CLOJ;8( zyT9`>xT1(qtm#Jgotlk3&~Fh~{19E(BGb{k;~q9Zrc(eDNas92WA0HR@m%il>q(|p zeJhv7%Ca?*!bLM#j$#PnTk5a60db$q7YnlPVjEC)4&*A?h!fZ*=oiR$W<_x|HP`s2 z6zRBw7J!BNX|E*B9H6V^-cUmHe}i0nlV9L@DVSuUU_!r>bIG7f%45ve81<~+S{qA; z^(4zX&Q@h$MUA?V_WIwiYI8+4vRw-;AG~yJ>LahGzIH1_M(ZCf%k`84b=Yj^Gawd| zT^_FLxL0i(v1gmidwi-WIqMy}%q;qCKjRGn7lCMf1XhxFD_Poe+?`!%IS$cq4`AbE zyzIw8(pdpKy);=9V6ylX=l-$tuG>H~;ghna3P_Y7T*Zx#blqkBI1h(=))h}3*-H;X zQYf(C=l_$}l0G&O6;80T;>;UOWw8z3>l(>7uZEKp(s7RU)xbRq0p-GsB1b zi>^l=BSlz_cNIsmr6$$$T9n!t|`l5vr65x$UI=cPU1gjS&!Qmd~QH2zpjO0du9F3STxb>>W z_?Y~^X|1~crzL*NaTV%ehjfr>Tf=d?3i@{!v+7aDZz+;0xXyNd{J7O)9G`d*V0uJ) zrUN_;{c<&$r0h%$s=be38Fgtm`UO0X)gTWh4#EK(%_8gJRM-M%BcdN5-!Bgr(^9sI z*AI@xPhDC~j}V%>u5=WQ;dxZ!^nt?*%^fHXNoCQK13g(P^aG~x3BfSaS7_U_*aVBi zaU!>$yFe#3;>q7-g}nn?BJq{5r$nM@0l##R>+LnucAtp@O+dns_LFFwqX+h`k}MPS zW3f&?Pw2c+`fyF8D>r{xT&?LV=4~x(0=!_*P{kjm)~qc~fr|W}+}7~7U#i*tc4#3n zuCM<_deo)sNgHQF-vOsLp=9`@`15ea5tHm3jcmWm8g^%;E0cbqPmpR#cBPdwRLM0F z3@hSqv^wKT*gvgazATOmSX!`>VOb{MfQeEB#Y=W!({vj57Mg>c^whLFrG2Uj+A{i_+`2^ zYGC=rwk{p}i1>fQUKW=%|7-YuVq7TY7j%Cm%3mfb$?<~htO{oyl(v|GIluz4uXv?v zyFfA^+KnK+ou_|6z|_}C$uH9MmB`bOjAlhAc#_LfAdKTd^N~)qDxb1VPdz(_Y8&z2 z`!mbcgx%2B0X0u?yE~H$eh8AsW1CvZl^EH`Wj9rO8t8ia5b434Zk5st0t>W2&dhBU zMb%q+xUNUgjrhaBk*t>R3x@9h3^Dw7TJ&vQnmV9zP-7E|D`t+u#+FGBB(T}^o2(Ny zi1DljRY*I2qK@w=t3rzUgeu{+Dl`}x@6v-|Nsq!t7fE+R>g8M9j|~UW>BnOWUVkXS z&z{OFOqUMwm_?u7kWXTm$aTi?adwtnMn3+s)!KCFFfiN!Acs8vy20J80-igcRf`l5 zih!y%mw4kmj-*Wm3!T z7K{M1Ki%ciuxQm@o8I=*U4C0B+UEDyCu#+65#EDXlRgMMtVmM_3r;}FVyXSOGOGE- zG4lK#+i{t+ARm6Go5dzPg-_hiESyIDQZXX#Sf;Q#UjKPNnRhHA96GuVss1@)|z^8*&6>YHWOQrD93m zf8oJ361m-_`uzY}$CSV=cxj_fS?C0UR_!A!kljzO*qoxk53f?l;M~Tae`$qq42Ou3 zzVMQ0kM#8icJW>ZGQIupJa!x_J0Rbd;MnuPyTP;&?)sSac+`0e&(UX<>oHJ4*bdh4 z&Kz#r$oHls+xv9bGPGZga%=G(GmS}mJiAPCJF{?t%=>RZeCxn(*A?Nc?U!d&SOmQs z{Vb}561*p`4;Fym!(NOM50H%$HVWJVcd=#EAxK*faTP|o(>CJmoL^b;rNkWuAif%! z&XM_N&lo|TLoz%P#senhhZAYW;z*&8L~OD=U}y^g+txBA;TGmM6j9f!Z`8QGAMCAx z$p9k+y_mTD2)bPM+AvySb%!hngRfHUsMacGeb@DRlm&py?eJv#Z3I!atKbDk^Iz&& z7SlxC(8oK)=1Re%Hh?QXa)nDVm>zu}Z+60N7-N6A1sTmEK|+nn6|6bMy$|XKqqEOI zs&4GV;&azCCJVvwmhmqHR($-6yl@*ne^-4UZihi*fiioHI{XJDXRHwz4DY~Nei4V4 z5<(k3wHqv6HqGUMZKP0&&x=;;kx&+WI4>yYmLt@VE1cH5Io+~fV{7bEe2W%cg4Sso zh0n$dW3dQ9AKyE62y$%fc!IZ+#iz6p^MpFD`;k5loSCH*QrH;oW|iGv=hk$qm|na2 z@?mHn`|kISr@WS{ai$TR1{qR#={f?hx4DCxjoo*F5Q+=d1%$h~o<|EeN_#GF^m;nc z(`x~vp}%UV^c^6y8Ujfa<45;NS-N3hcWtKi+?RBLPi6eYCP^l#8w>HB0DY4`2UH=(;+s?w$koxvSwI0Dft9=-= zmC$O@X$&gj;H1>U$C}<4Y}JZQCVDzVRZW2L&#yo4N_Y2jc9l|gj(z@59i1=%>pg{Y zw}QA3BNw<%0@m`W!abFv(oET>PnA;szfYy`HJc|N-gv2^Xl57n{R1ig6j=?vr3Z4a z2^;PI@6#ris5`MsH5Tdrna>#1?WtcLM~DmZ-EaE^i2hq9wUDD(Z7xiA;10`7oBliF zw?Uylps`ow_~k|_YVkFJZE76gz&tziOPT8jBpm+-SO_R>c5xGKYJlrba`6=P6WG|E z#kJZAzxnqbuhXq^dUq+M+2Wn0erZ)3!}GHZVQk*toC%8;^IL_oBK>n8VNvaP@RyVF zY=qqo82J@=(a(k}L3BC|SW`<}5&#}|1OEl(wkH(*P!Dprmd`_j8{ZkitJoV``mbdh zsb`}~v&;NDT39;|{J?3rE&-*jjR#i#8bTvm>VmJLGb>3Sx${3*_iB37iu_9J}%{a?1%NKc$%M9ARN?+~e9yo%Y*7F>K-r^+uk#sBx;esH;c!HSEu2`f8 zd%B*Y@rQ(t0FAWV*B@=zgSQwx2^>NBrM!H z6zN|gc38qAhLvZbo50wByu*gQgFg_six|-6O^pd@M<12#U$~Rr+EVIYLbc(bs?#ve z!+8XKy@-#I2<6zMf^OXV*s9MDaypR3Ec+K2-u3C1rFRZ;XmQnPT+N3{wVVDYw3Ry7 zY^zw25C3@~q#)b=gUIGe zjYf9&@9iDdejzT;dOG%wAz8oYUK;~3ldX}?Brp_X9@7G{{H!Ac||k+!%y^eW?b zX#HKr5FAP4a@GbfseEtH9HU(%Y)=LZEcEE(w7tah@Z|7;7~(AS=b}WH1wC~?5b4K7 zV9uR7O>^;^B(QZVqLQ0Uk@>8~Nfv-uZL*$to5|E{)0{e+3 zGzMR&-9myy^_-*DNgmkgw-Gs%xdTc%@dO3$Jy{I9bW&LjY#0OQDz$&yR~vSBEc93D z)E6c*X)6H@Y(IoFx%l*A(^9+oljnRu2}G+Qh~83x$T_!P7T^p(cW`l4vzIs)LM6I{ zRh=(Gv+_D!2+y)9>h3WDX9-{?0jn4RzizYfhe#3-;Dil{Kxx#-*>L-?CWyavuE$M_g>Ha{O)_jXd#pc@o4ZcFfa&Jl;w3WFfcj6|4A@x z@CoOjCl>|=6NZYsjGmAAPcvLseTAvtvRaQ48^S{%qqt0QLfd+_Y1T{8qWJ@Q7^GTI z#aq2r78ICP(kvgNxt2mgo`f}r)T-x^Ct1@|*t)UZl~!bpht?SNri%7ndY+5il1=vB z4LoW8*0j69&GYMeW@kFEeK%|8!t>@3a+;>IDOORT840}r}vMv1z~ zB61{o*FNXGY-@Wk`1$k8$w{M9quPAEas!Q}rKJMr*%qCSpg_m5f*3)UIn$}er{&*E zCh5gty@{yp&OZD1vI}oNOQvYN79RZZ*K51!#;0TTj=GMc`4Q*SxiU9O4Xd-q%kx2mzqha!$&%hC*I?OPd` zq>%?0dcux`p>LF43}p&Ew*7s66zkC9z00SfqB8c*-M-ZHU0s9Xkk4l8ZhK1Q!zR^7 zkBV$Ef2`I<$@gH8^J{FZf+kcM;WyPcVE+F4>f&H2j(;cupUU=h zZ}Fb(Kw`;r_rYZLI)_n~Qj>kn%(Kka-u`1a zF8R298Xs0pn){DWN#WtpSCWA(cm;3QLoo(bh{bPB<0p>IymPnv5Kn#2@6h3CKRoy< z;MG05*m!zzgCq*ILsBNV!aTO(F-EHkt73fO>8Z~VSJbTVEWX#pUd+ps6xPzx(wW(~ zx-Mmews1&Hb@0(wL;VL_yu2D%S-%ZPDj0>IWH9jw`RrMCc+O{BC8Od63K?!tO9i!w zRo6fHe$Vks(Q}3@^Pj>%iu0l!*I@jaa|{bJh9KUNlBA_$ikeR`Y#)$uHs@|3d1j871zG5O$t%n3?oo zAQ@D#-#RUDVJezxcwGK0t>|X&Fd|D#AuKjGR0Tl_o$fVU)U66QJ5a33h@HmgDd91! z+9T(eO;AV1l8kV)V|VTLL=mg``L)FK@VKc<_#GyGcusp?nE^8{1;v6<7gOEo77Fgr zPy)SpJS^y818LX_y_iR0606cdMyUP>oum>H2{TPBUktI^nyAFeR11>iTNsZNeS}e2 z^4|aCAh$@Dgm;`3Zj2H0!Zc3$;`pasX9#Bd1IvwcUeZg8cgVu+nRj0*IldzVz@T{G zK7=h)&48n)9x9LE7nsusIrX;sFu);$gRGVsPi}5PjD(nBJ5jAj^Jxt4eG z#%~|p^FMxqHxY5e8rM?=!FR*S$=$5QLtFKR7;fK2n9vTHY?tN7blw(^!RVkwRQ%mH zP0vDxFbp)nHT*hOkaT`;_c7h+NL~YZ60eLz606xfl&!#}nI0X#oS-+YK<#aOoJ{dg zXMw+qDoo;K4%BV+`nj_G{jFlc=f7mWmT1d){haEn*X0XUMIv#Pbzi>{ewsPvU{Yfl zS}N!9)bx$wbDb&8&Up3!^uuD~;DJBTjQ_kyc_r&uPb7O7`H z_^!w+X+j2J<2+X=g|V@-;|4wX6!~~orN$=e)D*n>N2&pJ^61+VuR~g*l@~Tuc%Ru= zrr;C7d(Q1Cv-SYEPPO2%1RJM~2JKvD?pHyNbuETA4-8f!TR!tPBS*sjtu$?{jd#Y|%pr$c1LOBx<{tP{ zo*fFo5>e|U>?|QXJU4KNQnMxe$(Ucmo=n!r7*rT_mERF|TvJ{Jv01l)QNQ6J&jv`Wo0mBik@|SwzbJ)cg`#j znJ=xz#m=tankgYHEDRY455h9=@Z20vilgF>49d_GU%z!%3w z`fbgw?n z6ci33AK>mk2I}lSuJjN~r7{Mc%2ej>wEaR*224btFfyx79qmW%iOC}mQW{t$4b2P@ zM$aD{jq7q7Sr{?+EMQg+#PD!>)1|Gf5G8zQ$bb9^7s>Xu-0POGkuep@bIk5*xa2-6MO+FeIYnHQ=3DGAXD{iO zP!ot(Z<&615&iK4=A8r;WyH>cgDFqj!?l?Lu%TBRzIkXPq)K(f$N*=3a_T zvJ#wYKMJ!`+_%AZEbRk$^t$U^thueG`YY;bE-T!L)s{{2Bbx(LbmV3vAF*+s+{IT{ z`_yhdKMppG_mflnGq8%-e^kD8aRQqc)PsW(pCDh!?q8XRh=5K1&`?S|+*pRI^RxPE zVGTah=FZ;Cn*kU(9{S}5l$IaJBq40Ydjf(j5ukLIT|5>|`b!7gc*Ca0-}oFSYnbzp zn3%~a_)M8|(5gD7t=&XsId#Ue<$Ye`I{6x195b$)-Xwny*J$OFsd^PK6ZJx0+Zj>g z@Y{dR=ACWvygx<70vAozWg9)-Z*B3|$TvWM;{0p>cH4%SU||h%s?IJ>gdgTm&Q=^k zGq+Q-KN$A)OV=};p9Vr#XOI5MEY&BM3^bmR1MeF{`iG|QN!_*KEW5+?(GM@aZejpA zQmvyaFkwq6u=P0!RbfMU%1KNonoDNHAQ@oP8sIg0mxzL&R>b*^xc5#f&>c!|@D)2! zR&48iXBlV4OLbQVl344UXT?rvPmJRN&kspaupCfsKl|;x*hxlRT5(qT#eDq|f_X!4 z=x6Rt+hAibv6~3h`aA=#9j)neXG-rKlO|{0k$|uXpAkI4ZXj!T{7-h$3@S~qo}QA@ z@(*%ZYrQ^VxoroAUdwBHGS6%X$)6Nyt{X)}Z@V&(bPtqSehbReMioS;H|82fJfoC3 zR{xhTU$R7&-e!Wjr6seMno5y#G!s0_4nO<+$mFOQ=#jAPPEa_%m06g3U{5U!h_*R> z<>t?{f87V}#wdHYVlL1~VV~)HbJcmH1@x;-jfGw2o@|md&{7Smh^L%Z%ZX;-8dE}} zG)!fz`oc9Z2J#j<+0|^pw-vDMZRQWQ-+sok)t~cOChX#5P{#BAt7d4=zsrfl8&^j4 zG<6G17|C+4;O<59Q9t6YQcwX_91`MZT{w&bHZLSNMBxlnRK;R3OmIDdbl!(QwrsFP z`R+Q5Fcsd@x^*cTcwR4tdo}gAdhq?pTzRoJ!6xP4Ad`(E^0u$9?^wP9zUN|tVYT_U zHky8dT+77t^dBFeWr|wDpG@8@6x6zG?woe%sN|F0o$s*VHmJCzGH~OBFIjg%eP=i% z$7cz*RIfC-?Ql$uT{!yIU(uwjY?6}ZiP^2@@BMb#CVLEA4V`D2-ID*2L4^!80p}aV zt7C;~bsif!#Qr@+Du_eOX;_6(t!xq*?6zK)S=&4JwV`>N5RR|v2 zJk&r)y0hBd@92nHS@FhKEV+hZ zEOST>3;Al3nD)oweUsZO4Oj0GEeq)&q!H9=4Qz1wn(Xwotduu^gb+rkL^GTt#sBWz zyRg~DKcarzK&?1?!$pJfo7-qbAr}K%ILG!Hy-jL8FHbA-A7B=aO$`C#A?a9KBv_B zuUj>CGE-W!78g~Jc*IgRPQOqIB1J23fwksj6w1c%kw&)bG0ccj_#^r8aJ(WC89D9Q z;3M*hor&;iq&N9b+VmA$#<%4{KIM`Gdk}-PGNNNb1hVeMs}>1O2^O4AtTw!(nr%3k zy0FdlkoA~18F@)VU3)jwe|2c_$s+M05~GuMa!bz!L) z61}ms`_$sFyZ+CG>Xi|N3%zZRC+MOz;c`r=qFIAi_LKt2y12>$HkJA(i|zgz6+lzRTzi3 zwQ9tY2ggN@S+5F0fkZBoWkpX;kwl~}cv2{G`ZMbV?A~)G5!x~4eU`FmSk%1vXxu~* z*c+Ue6zlPb9I?vL=GQc~N=K}*+Gwkgg4+zmIiAeg&s0c@2Q-d4+}DN&K{xO;R1--? zN}~I7s^M#wsxJP$Buk;_akV>s%pv3YMypGbMWtA{>Y7<%c5%57O@xu^OMZ*F0qXMR zH#S(Ft3#AWG5z^Cki(9#pCk@Q*}eU}#h&Es?5e0@#ayaC4Tl9`veH6YfC3k6Hq!GLCgF4#bz0IL{Hf#%F^!xXhbl6Wn5gjbSw~opvBsRlkE~SBp7% zs(B+gUpPnh%wk~x*LyXA4$cC)n7B;$&4VQ{|0)9!ZhL;X0a}35ppok!0k_-N_!RI( zHoix^(5|ho<@T4v%;OjxSLcr@(VfWIhHM_?RmYd>s=m9a*I2PA*KAyzImH(Y^zFse zW8If$zrJ>Y zuxp&Anp|>}s@AR_J#2hZYM`klVChDMd2ZqGK_xrOCG86PG z$#0B6zv7t+IbQ)grdHtHwQxE9R;w% zn|o-6F$`D5tULpxqfDLp*N?yOZ$lP|UxVFx{@%^i&T^qMbnLCY=Gtwn`X7;mw6=Y* zlx;&~k-s;Bhr4(VrECUqrxp?+UyWJmsFLObercff1n3%u-wByj;XZd$zO~FBcOUAp zFZJXJQ&N9FWAGi%tqFaTM+dL{aN}cQ+=MNu9#f*Pk%E!2+8WWq zZEoJ?qm6Zi?kKv{Noi@f@_l% z6AaIU;OmR|uq)8>sGKn(*A{gy$u%G3^_?~TeNkn4r7WD9+2aSdWMpJQ31|eBCC^sK zOD#Iu&jZFBSHpkKhY*K&gSL|;b44XyhNs^wi%t06Gx)J(Dr*dnkk-upGQ9Zft8>zrr2K2`FZk>NxR zef~^^8kO;~ylD?xUkEl5SX92D2S>L%Lf;pHm+$WaE(DPZSj+NG-3`3{eF9NXy__GN zNa6o`wC9I2xIB22t6WcJy~_)a&VH?7QTv?i&R6#}1!-4!^l6Itr%y1>?mc_px%h+R zfKu{g#-01uaL)Cmy-+y1L0d(dws@4zcz!d}j-oyVCoA^Jw2wDF4OZ8&;JR#abwGuF z9H0+}Gb&yEe@D_fN4Mza-Y|tnxL})I5?c_Hb0ShZe*bg{YYl=$+vvytmG9E=+aTNb z$E)&{@Kf@F%s2GKLP4tqJtDzwRQ=nBdp*SEw=kS5sBZS&sL3w_V|UttM`dF9i7SA_ zbFZU&k|SX2XVbjFesOo0nRPF!CSP`a`6GXaUY)GiY2Lm7C%u=N?7P!in|?i4ou&+O z?=4wlzQYc1Ud7@7_e{ zp3&G*Xg&D2mOy<@Ou8q&e1bllI=Irt?nvc4N54Rx9>SaHHZ>X75s`S;@V)2S?dy4h=5xf#NyhlfDuh%2W)vFxO98({NiZYD~I-*Ao7X9$OR7N#4a{ z{N@+TWk0iE8o(X#*cel&M4caPQPGr!NYp<1i>B)nmM8RoRFiH_d;?9AZ`PocI4IeC z4cD~zAAjbKm+;(~F;+>dyOe_bTKoJGXvcdK6qr%c+c8((yd!pJ7P$ksj;^_jgj{0| zTWm@TP2g3~qLUBn%M$lilvq|A7^d07_`Pew8VQO{5_#?`z-{T^NO@4O?L%6lM8ZLV zEg_&AI3FUThOP&9EYJ;ILzEC9*yY8TH?T`mr)78t+G|0rZg8@WxdTQ~`@01w)S&2l zXD7bF&lDf=BQgn9yg#PP9BiyY^F^kIb!@rt+89*9WO5X#YQ#W5?B#wMk6}W6u;S0a zk&hcdL&Vd;b+CyU=o*5czx%+bUQrn#yIq6a+C$Vv@i3I?>e*~fnX$D~0?m729S z;*GsBA-R(i&Cp-*x^+UCt=Jk7$HeZO#Q(7I)3<&CS5wQ8Tp3ln zkS-U-yI($=6~s z5@uc}q3A@py?&8+%(Vx$idhkDMD_N{O6gnN5O`~;xjO&5M@!y#-F+9utgmqbPD(8y zc9!y!!)py}ioj=GiEzU~^!* zV6{H&PoPhciy|5X&&St!K;BipRhfOoi#g!nqyE_WX#1RzLrlFy?1B;SYo!PS3dk#C zV`JpysTWq4jxm4bIS&Yf{~k>n@*Fn8M;^sI*!R>HRiqRm4%|1 zw9>Cb6Q$LeZmXxZoP)!~tkO@&VEF&|^lI}LvG-Ya@RhI3kC=|@-@8NFM$s6gr&s_D zL)#X!yyvtFJU;R^4FFrIeC!R?&Fym;ZYs><)}0m}$ooZ}=nyG@GkhJ2&04*>Yu>=r}t@^g`KZl|T*7*)#92pAO2>=bxfNw*tM%g7jexZFu75Wkl0@BVo0LR1W& zV24bxN+atmSwx=A-ZVG-!J5LUnf}cp*evkJtpD!&MdAK)dFhAX$L%sclv{c?&xMe$ z87VLqiiYjok?%x0dp*Re%Ciny=WC~byWJwM$be zRDgW{3G2;gS|lk^F% zgD!qHZQduY>oii3xq2A^JH^FZ9vs{S*Oi5fD`MfZh^3$ftRAAj&zw}Q(*b#peUiRP zgo%|v@>lM|go0c!8pN<$Du^QN)*iPK0LjZfw_RVIbU0CdZFXD!=O)4-ib=X8VY7>V zy`WE8eYcja3q4wY^CEJZZi^iAGs)dBRM^dJqHnZ`hvenAZ8?KB3SV|VO*o1P;e?%L zqQbz_(a#!mx`;y=B^zl~ksow1Jst% z;E+Ld2tMpI0d;HJt823_^K?z>x>WKP=$`nQ0&lY9-hi|-7k68p0D<~OFy2R~$Ls_c zx`sKvz(mq3F9GcG-36pk5&DEBR|5RN(=Yi}k_l=(&GH0XH*d0#Xh8E3h@7DFQaVvr z>AJc)sMvSlN+bfHUjCR0AiOYY2@VcLZvC=?!?(--IK!J_iYXi#1-`$2i~)G%U_IbX zj>)os2_fYy{w#T+F8p+gO|&7N_h*sDYt^`$yyF%HOOfMBl_m`or1}*`+Q5~jfQOby z8v%9%p;X?!2dp~fW1w8GSj72sI6+(RJco^lzHdk#DE;#7?wD@ofr>}eq0xz7M&Bse z{go+H7xde&foyZ`eXE$wmp_K^>Tvq;g731s*#m-^#o4YSVwU1#+Tw3Y#bbZ37tE$t#$x**8vK< zFqTnKC+12j_dXoOTWc#ENaPsX3*=hIr-cH1pVm?!%7qVM2VBD zi`^F{7Wrq^2#QhpoL#T55TJ-Vl@8MMF)(OV(OCdtFJClUd}I<}u%WYOjC+;{oZ-T^ z&!zoH@Hk_cjJ|&oXi-Ek75;&hwt$dNlUde0Rc>tMG!(B(a1NDU@Xt{1SzZK z*&9tt26`pQ)k~&|7qgN9OQ0`;Rk>t%EhLghDD1A;n6Q%Egfm;vEU7p;I&!aXH-%aL zuCeNYx^WfgANViIFM8wGT`Q2fsw0;BUl^{X0n*FybgF)zx6J=|J4xmlcIj*zAlLH= z&&VTOH2M=>hJ~;qyZ_4vUrTIrg<_quP=f(JIq!MUyl@UK}qzlC#Q zpoPSZ!NfnnCh&_3f}&l3Qrw9g^Wh5Ax(rAXF(XGOnQa0pi{H{(sN3pCvI+PwBM#0_ zBdZ@@iXi*+W+-dIT9B);6FEMp+ov~#=`qz-!ZSWB_C&EuNX&XXs7k0-dcnXg7n2}^ zL{Nmf^+*#7vcavW92UDH>TLRnSi|NGDxWj?{=xMo^!FF!t-gi@4DZ5HRS=>gUs^mL zho(m6yucR~B1@o_=5gAcdv8KFz9OIZO@48_+UPS4#4ed!un>pf*22dd=@XHR=UmWh z!zxoQU`Y`Cu8Gog%^!K3zc(`eIHd3iJ3J$ zM{Mpj1B=iV*&yyq#eExTk{M#})i!MWfBa%D8YgVj?V#EkBJzlDS09eA8AHL2)8ksD z}L=}g2#^OTvNAr(K-aWW1}7-D7SniLcM-JG+EK-5<$9{x|)c_KyJ8+E(l zJBFsOgtpNxZjJ{nrUC*0t>pXm!+R;i*ew~gk0&a)KqYO|<~e)=uEj?05|^J7@8Z1` zVH1hgN@{8<+i5M95N#Ft-P%7sbjoJo#GNgP2 z1jTXEp;La%Jo$txd1wacwkV`m$9kV|J45t!9->X^qKCL}=FR???pI&iGH#=e!W(8} znI3@&18blp>~QAJF^TlKr>)Z~5tr=uv4sx^3)K)5!?_;*`K}ZA6G(7O&>q+Pi|&X_ z6UslN6@HRP$z#y$m1g%TLxB6}Cb;aKV$nSeNs$qwFy-4ZTJ5{^uOCrvi6jirUpNB_Ct3P@2 z1ao*Z1m?jF^l+J`_l#TA=EUaLa&%hfppVL;g8oX*MwBvjaF^x7BK{cLjUpa zlX?8`IkeqYDT@gX=RBG6G&~ApVnZ~F+MI`B0^5zHlrvdniH{b#EL(Hz03Y}g-@ ze|t_;*lnw_$=qyo(;6RKq1gw@l^};!WSI6|%opJN#KgssM^`W2i9_`LWDI{TzlMc4 ztp^~gb@gY`c!cGn2t=_xkT}D|Lo)@~ZCuu2FLgrfRyM>B zVa2r3sE(tLi=yrM8Pn~nY4n8`S`xlNqQVayE?HX{xy7VRij=TpFnVmcOGmc#YZ(vS7rxo!N=0H$P zP_-1uLDZ|y%DBzKwLL{Q|7KJNvSDpf!?544Jzv#mhw zC7;tOFxI51=QgIj+|DSaqIn-S`bc7feVG&fGXb-52Gm&|dF(C7@XxJn3Fl=!N4xf{ z+M?R22}m~1Smnvg-DZZ+t%1_J$KybKQA_v<3S3Z!0tERHU=xYwLX5YY{60TVlr`T*`NCSHXF$^3$(MjhcJ)z|=@jmq}l8oaQp95GMs{Iyrx)}T)CSqIF$fK9R#%ZAD7 zsF53L83{1It$g{?Zx%_0pm1g$^zu;X6oyjlBxbPDTMs;4zH7ne&Srk}!z- ztapc$f?#ZHEWlTby!NeCPb60%CVc|Fs3#qC5Uwq%@Z!irf$0viJJD9iK+ZfMP5sq5WlYk~j5HG*RQ;F>3TJ43#X z0SF57{Ev;S&qE%sgeNQ~b1QR$ybgzYMsAuVeb~vL6s3Y{k^xn8ffZa^p6qG+M;@pt zdvP~HHVT&G0~;q|lzdQ@xf0C@2#NB~-bGzL9a%SX>Q7Fspy;#ot%2bpM{?8M39E;R zxy-klW!>$6egNRj=UV9&Cgt}F;og9k=-13W{>$Yv&gvc(>NXvu-$`4kQx|-TzAk3r ztrJMSB;J|$=r}GY znDBQSMXxEWfRUjB`kX=#nH?)oA*Y;-{6Q8M2o=?y?2i{>iIN^4$Jf4lQNgvYqT0j?d6DOheIEA5Z$zU>NK00|IXH};BrG}*b!h-r~X{wYLv zeLm=-vcjx&BB0zgTs{PrnjNU1^n@W`PbLkk?*)~IXKzX%3q*`{;dL6hbeqRU@>JTh z*iKzdiNgC;+q9%i5G$4i9%Q#sZ8=U@w}Rn1buEBAmK>0FR?dt?blMC=?#eLWI);CL z&H!m=tDR&hFr*itZsfx{?Su_Fi z&hjRUH1v~9=Qo~W+52c0iCcUZ=+IBK1WK|{NJ0qdN_eY}mS~9i7hoZgx~3pc z_81`_lD}w5{Vv#9I9eZ-D=f8UhRAnXz;3A_?)Dg31Qxj2aY;1=Z)y}KeBWFQL#1EGMpCFnV@aVg))2!ke|a^(`leL&h*)N|nX;+t(dX;K&+ zylZ%b8Ak?W%EHA~Fg*i^9tJ}p;5zU<2adcE$9E@T&~%ig*JdKl^cmdmJt<5O-X*B@ zd8XC|2kddId(0Ptrbm|UV2_bsaND0Cjr02n%X%UR#F&E$Q1yOvQig>D3c!`r!&hP} zGOpeUqnaS$5o;7Dwi1LiJO1hc{?>Pgfc^lO)#c(o|{(d>ab9M_stOzIT==gcs4pjb<_k}aGh#% ziBkRYbQTs8vS=2G*;!fTNKKH)y2Gt+nrKtq z>*5KxE4ZP+mp4$ZZaauoCI9+g%*1)^zk>AKykAo^B})zT&<}mMA|P#kz`a}rdN~!J zif;e}E9`)*$s^rg$1QQ@15fk}-C{)A_VyD` zC`OKc3q^ndi-tbH^*YkhOj!{ylF%*Ey9p?1RlpO{sP8`-SRZ}U&~OF@-EJtA>z>!P z(NMj^V|K4QnXp@Oh{-@X^OpZlc>c?*<+g=9DPVWzfk*n3nyPAQx-#}1l+djxLfWFb zE@@JLVM#Da=Tpe})~!W|xFKjVQmJvW{r$~KSncbV$;nI8ZZ*sDoxIQh4TR{;kStN? zt69Ocq>;P7bhMrUP-dB#HR%0l5)iD(44$7R?a;LB>L-d7nxISz3AX$;la^Rti` z*l8?^VBc~Dw|=j zWN#pA6cgwMZLkewmfaPZ7VweXm}m`$FZl8@z_hcpe<1_2K0mP~_TC+Ywyi`5GuT6x zV-7f9rw1X04~aq-u7}ci>_CXqS!mEJI%ERopowVa@m?7qWtSj3gp|Hid``2^XFfvD z%(VP16P3#sqE8;S5Y)`G*6?|Ok0ET?NJ9Is&d2rNgX&2~GSNvC?liG-eEF#mt@|NU z9K;TaG`{WpV=xCb1WD{`LC0je2R?VlG90ek|F8`%qvH34lU=SPBkBKv8u&O4B3ny* z%oGHTPrffbdix{}<`5B*z5-3dtjGjwK#D1i#5{}s6^zfS=x%S00e=oRA{T6YQ+oE3 zW5B#VA`OUMYX1X>S!3x9$W#*fmOicvC~Is=bsMD%t!FI; z?<&{xA}suyqV&3!o6rAni<>N#H0bZ&+mU_4MdrJD>8!re_Y8@7j}W*OUr0tk{wAsl z$dFBW(KsQft91ZKFtxec6Y@!}vO?=w{yS6>y60&4_L0V`2flUBO#)KE1RY}V2So_b zR(bY!CD1Rq0|_$0v#-Lka0C5qJWB2ovlgZep@=Qk5&!P0SwPZyp2h+oZ2)tSLyS1l zhH*<({01hDKU*v*^ax@|QCJ;1Vq!7tsiQNLnKb22KJO`gr^M``kYY zUN6}xDn^P;VZ2%Z)0GOCozRJj*a8nOtpWK@T%4RrFZpU20T4x>Apq6`fE+Z4DQanH z;!>iJH_NAWzVsMwQUQUb?1! zcSJ&-jly&EwR=c1Cs2})laY9QkWrt-(~RDFM0(s$2*#3guF~BZ0X7Nrk2m8&gjeMC zA!`U(u$inaYDeFnad+en8`%772WWIjxZ}Jw*f8Fo08+ywiCn1nr#K%ed+N$(P2{v5!C zEpy`+xJ40AThlE#6T<3vCrhWB-QGOZsH11erG%Iye?b>rpo7(Gj3dhz7FGc`Ed*YI z37kS)4mu+%t%mGg_$Tt7*k=deDyX8jyIMg9O+v$Bc?U9;OfG3$<0s~`ms`6aPHzNg z;&>TuPCGb1J!n1XPA19qI6?J&%6-+?F9a5O6avG9Xduw5^T5o+qhdOH z@Li#2SgY;HOmi(*b@Z$3iL2mwmp56cGE=S)95bX;w;0c(HEI0bI#zO*C@IJ%9OlY( z?c-oz{v5;=?%Z?)E0?%ey|nOk8mdj-=~QMKMN5;A>|wzdhw1BbrGMd?EX(kWz+9#q zE4OD`4bl3be$l-RQ=yY;1v)Lw<^G42SL&qu{}dT{y!j`PkT{tF%t$QE`9yMpdmsc# zNvEl)NgNwkfF|yLvIy?E@)+n+G_nYs=5qB`^m4Gdun}w!W{j;cX&5@KMTW@dilVhU z0fzUk)3+*K7}@K8rx0E_StjtX0R@k4b;Vr&ZgoLUBcYdKEbuI35M4X*r1o=vhqpcg zweR?S7RluYGg$}0ecj=cA1fH$@}1vS^lq_5#dd*}C;@?=F#55u326%Suy0)weJMAd zg+T)}5j7A1_PdyPdH;HeBSb0=XlI5F&4L>yYmgybI6mx_45AYgM@T9D7BiT306`6E zjspw1(E0?0q62f)DyAA0U8Y9HGa&Kx9LQ$+UWct+62f@-`8EHqRQUf`>gg0A z@0${RCSYO91PNs?UTO>naf6NjSD*UNveEyw7!~h{oO=vfjCqrsN;T6^zu6`(J_8GF OF;o-~@>Q~yVgCoGitcv+ literal 0 HcmV?d00001 diff --git a/Splay Tree/Images /examplezigzig3.png b/Splay Tree/Images /examplezigzig3.png new file mode 100644 index 0000000000000000000000000000000000000000..dbc40a3ba39fe01e44846dba5b16bd6cfed5a351 GIT binary patch literal 18128 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≻M%oM94;*+% zs-#srY}8qlCdTmMuu~$m?z*-&DSe>R`a6nmM!c4&<})trz~NJPh?j*%z!^v}X$~0W zDy3fgkzxE*fqo8(Awf-A1QXyKa(ZoiTx9(5)=nHA5*L6lh3*2b@F=Ll@679{@8Y!2 zX&>KK34&lT#vrqZ5k80k#nRSL>azz-l8{*j<9HAstR`f8zinjK(If5cyB&(9>D(YU9A0bcDCuSkc|IF4C3{LKCz`sXA8I_x?_@t*9ACN-f4z`G@uyClnqzYDC zFCB`i$_S3CWDL}U%SdDTjSmNUySh|4nT`j3MS*WZkx=qMyp9LHJK~g~nN%g|ADV`s zhoS@tB!Kb;3J-_L1T^Z3faX2yVo{!KVij<7&tayPRHN%~tPTJ+oT9tD$pe z2xMk9mP`%@Xo2`$+lrPLe@EUASf9m6+58!-O<5;Cq1AiH4UNYPjzf~-*OEQ z8WpdD4KDkMs=ZG}SR3^3snk4Pg+7UkdR;#3tx3)TJR;xS0lA%V+mg?qs#zRv&E7Ka zif-z_saNC%VmSv8OMs;sCr9VYUs}7>&h#3Ei)x33E@5X`K=mJw?R*@|4bKdRrN+m{ zzqt!-+WHC}b$Zh@q*MqP3PIhr{1Oc~kL^S!7KHpg2C-ZvGht}jZmQ6PqmW5

~t9TomnK zsmVR6O4QK&fW4Jf8*JhLtEUbaDFG#f#^pak$o>WWhx%-AP^g_=e*pL$l6lYMM}vom z^dA`n_Ex5vNtyjt<_1)n0UfqG-spd!N^7-igVUtl2quTdKDy>=$(G$9?T-l9HwEE& z;Bs|S$PJU}XZ{sB&K4&jv~T=w8ZvR9P0?&c6Iy5K7li0=Cy^DxMWDYR|^P ztT@r1KYw0fX;6+FaHCYLdGVb39B`k3w~B=X@EVraZ~qlDT&E<}uUP#_2@K>`y%)Rj z$=w=^-~ByL`h@PXHs!2(Viju2J7TX~QBssoS||%-WMn#F8$DGRP zV(fqvz6PxzMNLYr4&_FPIDa*NiKA=|rXo^2z8B8UsZ){lD`G5r)7TgLG8b7>Ug8F; zRDuf9^F|@g?&n+%(`!21qQ5i<(~3u{c$fYS6}Pb}NZy0!hN}U~VwhVu{*>Y)4cY%> ziX)B`=v5)(VF(`zA{vo+0vZ}Zf*S$)6;?4jo}h1q?yr7vtY2hs>U4K~M- zZ&WA;;=2_JZPtNNLr9PW#RVzh;NbgX-wUvj{FxRv z53m{%0t8Ltlali6(6yd!*r7%d8=UHD5buqNk0Y0G z_Cbh~jE>H+4&i4h`NccUyM_4t1y6%&?~iv6lCzpdHw*?Y2J`c4e-B;0#tFXE8-@v`k01P z3oWt>S)EA)-}@%#>k`0{9I@-7oAs`@`AP0xrZ2Bjv^JtaFOr zN3ccEtxxPAuP0ACaK`-TVt0B8jQ1p>upvQS3|FX{YDjzc(W>62B&_f9zY z$}o@}aGRFc*>Xq$vzzaUv74&*(}^#GAVF`W@E!xWZ3g~lnlo1%ySx9&5QxF8nEx|F zki`ma;Q!1J>@vMh_^%8>2KM>*uMEL4S-H?#5tyaXYOU`-2erUNQ!jb+lS6yR+MrizmH|0_pu`G0Z* z4+sd2&=5aF|3ggw=$|}sP^#9u2{<-KApCTq%;L&GbO0Z;f&%3eWcF z5Ha(yj5%4pi5%1~wZL_lAqA+(_Lm(;)|2iyX6!U8>BZQ_-;}%!(S0!xh)3|o_hi4j zy}$v4h?nG^x&fIy3k0!#zoVX{UupJ;4WNToTto3c1tDTc;}9$xxd**oBjhXwGDdkh z#wSEr^c^UyDF<>YS`2A9DI~|b&zzj z_#ck@CnCH}K+O)!FhFhv55cTTQ3M5NXv4fQptpAq+2(R}mg?e&N)_mbO*M>%JGd@D z(m2HHze2#m5l1x$s5B3H>5|>ae5k*dmlqo`x@BMB&uAtH{-RHdM_~k5fL}pPfco1@ z;h1zqZj{Xy1CMw#t*%WJMMBno}WAgIpn?|~^R-wC?v&D;mcj9{K| z!Qi&5pNd`h6-Y-oLVKo4LWW&bRFCCB((8m^LFB~WuhLKq0r81n*(XT}&@WhwPvJ)V z{}S4D^^>s+#|CS1ATp!&!7)!k-fabXN8h=^e&RcI5Oe(hP7$0$rt`qq1Leciq^9W! zNyX!U;Kb?a={fkx+hcjWvY_dobgm)t_U+pi0D6(q(eVJRw{kmXHbnaPib Date: Sun, 21 May 2017 22:20:42 +0200 Subject: [PATCH 0392/1039] delete blank images space --- Splay Tree/{Images => Images}/example1-1.png | Bin Splay Tree/{Images => Images}/example1-2.png | Bin Splay Tree/{Images => Images}/example1-3.png | Bin Splay Tree/{Images => Images}/examplezig.svg | 0 Splay Tree/{Images => Images}/examplezig1.png | Bin Splay Tree/{Images => Images}/examplezig2.png | Bin Splay Tree/{Images => Images}/examplezigzig.svg | 0 Splay Tree/{Images => Images}/examplezigzig1.png | Bin Splay Tree/{Images => Images}/examplezigzig2.png | Bin Splay Tree/{Images => Images}/examplezigzig3.png | Bin Splay Tree/{Images => Images}/zig.png | Bin Splay Tree/{Images => Images}/zigzag1.png | Bin Splay Tree/{Images => Images}/zigzag2.png | Bin Splay Tree/{Images => Images}/zigzig1.png | Bin Splay Tree/{Images => Images}/zigzig2.png | Bin 15 files changed, 0 insertions(+), 0 deletions(-) rename Splay Tree/{Images => Images}/example1-1.png (100%) rename Splay Tree/{Images => Images}/example1-2.png (100%) rename Splay Tree/{Images => Images}/example1-3.png (100%) rename Splay Tree/{Images => Images}/examplezig.svg (100%) rename Splay Tree/{Images => Images}/examplezig1.png (100%) rename Splay Tree/{Images => Images}/examplezig2.png (100%) rename Splay Tree/{Images => Images}/examplezigzig.svg (100%) rename Splay Tree/{Images => Images}/examplezigzig1.png (100%) rename Splay Tree/{Images => Images}/examplezigzig2.png (100%) rename Splay Tree/{Images => Images}/examplezigzig3.png (100%) rename Splay Tree/{Images => Images}/zig.png (100%) rename Splay Tree/{Images => Images}/zigzag1.png (100%) rename Splay Tree/{Images => Images}/zigzag2.png (100%) rename Splay Tree/{Images => Images}/zigzig1.png (100%) rename Splay Tree/{Images => Images}/zigzig2.png (100%) diff --git a/Splay Tree/Images /example1-1.png b/Splay Tree/Images/example1-1.png similarity index 100% rename from Splay Tree/Images /example1-1.png rename to Splay Tree/Images/example1-1.png diff --git a/Splay Tree/Images /example1-2.png b/Splay Tree/Images/example1-2.png similarity index 100% rename from Splay Tree/Images /example1-2.png rename to Splay Tree/Images/example1-2.png diff --git a/Splay Tree/Images /example1-3.png b/Splay Tree/Images/example1-3.png similarity index 100% rename from Splay Tree/Images /example1-3.png rename to Splay Tree/Images/example1-3.png diff --git a/Splay Tree/Images /examplezig.svg b/Splay Tree/Images/examplezig.svg similarity index 100% rename from Splay Tree/Images /examplezig.svg rename to Splay Tree/Images/examplezig.svg diff --git a/Splay Tree/Images /examplezig1.png b/Splay Tree/Images/examplezig1.png similarity index 100% rename from Splay Tree/Images /examplezig1.png rename to Splay Tree/Images/examplezig1.png diff --git a/Splay Tree/Images /examplezig2.png b/Splay Tree/Images/examplezig2.png similarity index 100% rename from Splay Tree/Images /examplezig2.png rename to Splay Tree/Images/examplezig2.png diff --git a/Splay Tree/Images /examplezigzig.svg b/Splay Tree/Images/examplezigzig.svg similarity index 100% rename from Splay Tree/Images /examplezigzig.svg rename to Splay Tree/Images/examplezigzig.svg diff --git a/Splay Tree/Images /examplezigzig1.png b/Splay Tree/Images/examplezigzig1.png similarity index 100% rename from Splay Tree/Images /examplezigzig1.png rename to Splay Tree/Images/examplezigzig1.png diff --git a/Splay Tree/Images /examplezigzig2.png b/Splay Tree/Images/examplezigzig2.png similarity index 100% rename from Splay Tree/Images /examplezigzig2.png rename to Splay Tree/Images/examplezigzig2.png diff --git a/Splay Tree/Images /examplezigzig3.png b/Splay Tree/Images/examplezigzig3.png similarity index 100% rename from Splay Tree/Images /examplezigzig3.png rename to Splay Tree/Images/examplezigzig3.png diff --git a/Splay Tree/Images /zig.png b/Splay Tree/Images/zig.png similarity index 100% rename from Splay Tree/Images /zig.png rename to Splay Tree/Images/zig.png diff --git a/Splay Tree/Images /zigzag1.png b/Splay Tree/Images/zigzag1.png similarity index 100% rename from Splay Tree/Images /zigzag1.png rename to Splay Tree/Images/zigzag1.png diff --git a/Splay Tree/Images /zigzag2.png b/Splay Tree/Images/zigzag2.png similarity index 100% rename from Splay Tree/Images /zigzag2.png rename to Splay Tree/Images/zigzag2.png diff --git a/Splay Tree/Images /zigzig1.png b/Splay Tree/Images/zigzig1.png similarity index 100% rename from Splay Tree/Images /zigzig1.png rename to Splay Tree/Images/zigzig1.png diff --git a/Splay Tree/Images /zigzig2.png b/Splay Tree/Images/zigzig2.png similarity index 100% rename from Splay Tree/Images /zigzig2.png rename to Splay Tree/Images/zigzig2.png From 5d15f553817310785fc0d5539c01508c86892250 Mon Sep 17 00:00:00 2001 From: Barbara Martina Rodeker Date: Sun, 21 May 2017 22:27:24 +0200 Subject: [PATCH 0393/1039] Adding images for examples and rotation cases --- Splay Tree/readme.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md index aa6bdd4db..89444b2cc 100644 --- a/Splay Tree/readme.md +++ b/Splay Tree/readme.md @@ -8,14 +8,25 @@ Splay tree is a data structure, structurally identitical to a Balanced Binary Se Given a node *a* if *a* is not the root, and *a* has a child *b*, and both *a* and *b* are left children or right children, a **Zig-Zig** is performed. +![ZigZigCase1](Images/zigzig1.png) + +![ZigZigCase2](Images/zigzig2.png) + ### Zig-Zag Given a node *a* if *a* is not the root, and *a* has a child *b*, and *b* is the left child of *a* being the right child (or the opporsite), a **Zig-Zag** is performed. +![ZigZagCase1](Images/zigzag1.png) + +![ZigZagCase2](Images/zigzag2.png) + ### Zig A **Zig** is performed when the node *a* to be rotated has the root as parent. +![ZigCase](Images/zig.png) + + ## Splaying ## Operations @@ -30,9 +41,20 @@ A **Zig** is performed when the node *a* to be rotated has the root as parent. ### Example 1 +![ZigEx1](Images/examplezigzig1.png) + +![ZigEx2](Images/examplezigzig2.png) + +![ZigEx3](Images/examplezigzig3.png) + + ### Example 2 -### Example 3 +![ZigEx21](Images/example1-1.png) + +![ZigEx22](Images/example1-2.png) + +![ZigEx23](Images/example1-3.png) ## Advantages @@ -57,4 +79,4 @@ With *n* being the number of items in the tree. [Splay Tree on Wikipedia](https://en.wikipedia.org/wiki/Splay_tree) [Splay Tree by University of California in Berkeley - CS 61B Lecture 34](https://www.youtube.com/watch?v=G5QIXywcJlY) -*Written for Swift Algorithm Club by Mike Taghavi and Matthijs Hollemans* +*Written for Swift Algorithm Club by Barbara Martina Rodeker* From c4268801a9340b1776c6b4e0c452fe8a6388031b Mon Sep 17 00:00:00 2001 From: Barbara Martina Rodeker Date: Tue, 23 May 2017 22:08:14 +0200 Subject: [PATCH 0394/1039] Update readme.md --- Splay Tree/readme.md | 64 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/Splay Tree/readme.md b/Splay Tree/readme.md index 89444b2cc..29f9dede5 100644 --- a/Splay Tree/readme.md +++ b/Splay Tree/readme.md @@ -4,22 +4,36 @@ Splay tree is a data structure, structurally identitical to a Balanced Binary Se ## Rotations +There are 3 types of rotations that can form an **Splaying**: + +- ZigZig +- ZigZag +- Zig + ### Zig-Zig Given a node *a* if *a* is not the root, and *a* has a child *b*, and both *a* and *b* are left children or right children, a **Zig-Zig** is performed. +### Case both nodes right children ![ZigZigCase1](Images/zigzig1.png) +### Case both nodes left children ![ZigZigCase2](Images/zigzig2.png) +**IMPORTANT** is to note that a *ZigZig* performs first the rotation of the middle node with its parent (call it the grandparent) and later the rotation of the remaining node (grandchild). Doing that helps to keep the trees balanced even if it was first created by inserted a sequence of increasing values (see below worst case scenario). + ### Zig-Zag Given a node *a* if *a* is not the root, and *a* has a child *b*, and *b* is the left child of *a* being the right child (or the opporsite), a **Zig-Zag** is performed. +### Case right - left ![ZigZagCase1](Images/zigzag1.png) +### Case left - right ![ZigZagCase2](Images/zigzag2.png) +**IMPORTANT** A *ZigZag* performs first the rotation of the grandchild node and later the same node with its new parent again. + ### Zig A **Zig** is performed when the node *a* to be rotated has the root as parent. @@ -29,7 +43,53 @@ A **Zig** is performed when the node *a* to be rotated has the root as parent. ## Splaying -## Operations +A splaying consists in making so many rotations as needed until the node affected by the operation is at the top and becomes the root of the tree. + +``` +while (node.parent != nil) { + operation(forNode: node).apply(onNode: node) +} +``` + +Where operation returns the required rotation to be applied. + +``` + public static func operation(forNode node: Node) -> SplayOperation { + + if let parent = node.parent, let _ = parent.parent { + if (node.isLeftChild && parent.isRightChild) || (node.isRightChild && parent.isLeftChild) { + return .zigZag + } + return .zigZig + } + return .zig + } +``` + +During the applying phase, the algorithms determines which nodes are involved depending on the rotation to be applied and proceeding to re-arrange the node with its parent. + +``` + public func apply(onNode node: Node) { + switch self { + case .zigZag: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node, parent: node.parent!) + rotate(child: node, parent: node.parent!) + + case .zigZig: + assert(node.parent != nil && node.parent!.parent != nil, "Should be at least 2 nodes up in the tree") + rotate(child: node.parent!, parent: node.parent!.parent!) + rotate(child: node, parent: node.parent!) + + case .zig: + assert(node.parent != nil && node.parent!.parent == nil, "There should be a parent which is the root") + rotate(child: node, parent: node.parent!) + } + } +``` + + +## Operations on an Splay Tree ### Insertion @@ -73,6 +133,8 @@ Splay tree are not perfectly balanced always, so in case of accessing all the el With *n* being the number of items in the tree. +# An example of the Worst Case Performance + ## See also From 0a813ba0f16865323529e7de03ff9cb69eea378d Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 16:05:34 +0300 Subject: [PATCH 0395/1039] Code improvements --- Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift index f4cd8503a..9c5961c71 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Sources/Dijkstra.swift @@ -13,11 +13,12 @@ public class Dijkstra { 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 { - totalVertices.remove(vertex) + currentVertices.remove(vertex) let filteredNeighbors = vertex.neighbors.filter { totalVertices.contains($0.0) } for neighbor in filteredNeighbors { let neighborVertex = neighbor.0 From 35db21bb212b56ab13a1ecf67b251727ca3718a9 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 17:54:49 +0300 Subject: [PATCH 0396/1039] Updated description --- Dijkstra Algorithm/Images/DirectedGraph.png | Bin 0 -> 68702 bytes Dijkstra Algorithm/Images/Vertices.png | Bin 0 -> 35896 bytes .../Images/WeightedDirectedGraph.png | Bin 0 -> 70820 bytes .../Images/WeightedDirectedGraphFinal.png | Bin 0 -> 76503 bytes .../Images/WeightedUndirectedGraph.png | Bin 0 -> 78079 bytes Dijkstra Algorithm/README.md | 56 +++++++++++++----- 6 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 Dijkstra Algorithm/Images/DirectedGraph.png create mode 100644 Dijkstra Algorithm/Images/Vertices.png create mode 100644 Dijkstra Algorithm/Images/WeightedDirectedGraph.png create mode 100644 Dijkstra Algorithm/Images/WeightedDirectedGraphFinal.png create mode 100644 Dijkstra Algorithm/Images/WeightedUndirectedGraph.png diff --git a/Dijkstra Algorithm/Images/DirectedGraph.png b/Dijkstra Algorithm/Images/DirectedGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..67db4995811de13dbf289b45f4cb0b8125bfe317 GIT binary patch literal 68702 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/Vertices.png b/Dijkstra Algorithm/Images/Vertices.png new file mode 100644 index 0000000000000000000000000000000000000000..09b2ad2c0190c1145627afc85f24157302a4abfb GIT binary patch literal 35896 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/WeightedDirectedGraph.png b/Dijkstra Algorithm/Images/WeightedDirectedGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..542c698e1aa006df61c1dc62bfe950bda1ab1c4c GIT binary patch literal 70820 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 aOX&wc5htqAPn9shkCK9#e7UUov;PC-y<_D7 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/WeightedDirectedGraphFinal.png b/Dijkstra Algorithm/Images/WeightedDirectedGraphFinal.png new file mode 100644 index 0000000000000000000000000000000000000000..b2bb3e8e2b9990ff598b7be178547fa3d0171691 GIT binary patch literal 76503 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/Images/WeightedUndirectedGraph.png b/Dijkstra Algorithm/Images/WeightedUndirectedGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..2f26b74d4dcd457fd32d619744dd5cdbd340a0c0 GIT binary patch literal 78079 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ñx&@q?ReE3{3Qd)#J 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 literal 0 HcmV?d00001 diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index db1726b1f..ddce51525 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,13 +1,50 @@ +#Weighted graph general cocepts + +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 have a direction, i.e. vertex, where it starts and vertex, where it ends. But remember 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 undireceted 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. + # Dijkstra's algorithm +This [algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) was invented in 1956 by Edsger W. Dijkstra. -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. -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 road network. If you wnat 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 best example is road network. If you wnat to find the shortest path from your house to your job, 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 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. -I have created **VisualizedDijkstra.playground** to improve your understanding of the algorithm's flow. Besides, below is step by step algorithm's description. +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. +#Example Let's imagine, 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 graph, that connects your house with all these stores. So, you know what to do :) ## Initialization @@ -38,17 +75,8 @@ To initialize our graph we have to set source vertex path length from source ver | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | -Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. - -But before we will go through all process side by side read this explanation. -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. +Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm, let's start! -Okay, let's start! Let's follow the algorithm's cycle and pick the first vertex, which neighbors we want to check. All our vertices are not visited, but there is only one has the smallest path length from start - A. This vertex is the first one, which neighbors we will check. First of all, set this vertex as visited From e9017365a47a93a977dc0f26c42045d6fccd4b76 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 18:01:53 +0300 Subject: [PATCH 0397/1039] Fix --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index ddce51525..5cf312acc 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,4 +1,4 @@ -#Weighted graph general cocepts +# Weighted graph general cocepts Every weighted graph should contain: 1. Vertices/Nodes (I will use "vertex" in this readme). From b1a50b492373dba7490e603975f9bec8e98c4725 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 18:04:09 +0300 Subject: [PATCH 0398/1039] fix --- Dijkstra Algorithm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 5cf312acc..a9a898d80 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -44,7 +44,7 @@ When all vertices are marked as visited, the algorithm's job is done. Now, you c 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. -#Example +# Example Let's imagine, 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 graph, that connects your house with all these stores. So, you know what to do :) ## Initialization From bb8b2a7d480b6e9f3d5eeee87eaf4a7e01e2ba36 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Wed, 24 May 2017 18:07:47 +0300 Subject: [PATCH 0399/1039] Fixes --- Dijkstra Algorithm/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index a9a898d80..7afc34094 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -44,10 +44,10 @@ When all vertices are marked as visited, the algorithm's job is done. Now, you c 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. -# Example +## Example Let's imagine, 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 graph, that connects your house with all these stores. So, you know what to do :) -## Initialization +### Initialization When the algorithm starts to work initial graph looks like this: @@ -93,7 +93,7 @@ After this step graph has this state: | Path Length From Start | 0 | inf | inf | inf | inf | | Path Vertices From Start | [A] | [ ] | [ ] | [ ] | [ ] | -## Step 1 +### Step 1 Then we check all of its neighbors. If checking vertex path length from start + edge weigth is smaller than neighbor's path length from start, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. @@ -118,7 +118,7 @@ And its state is here: | Path Length From Start | 0 | 3 | inf | 1 | inf | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [ ] | -## Step 2 +### Step 2 From now we repeat all actions again and fill our table with new info! @@ -130,7 +130,7 @@ From now we repeat all actions again and fill our table with new info! | Path Length From Start | 0 | 3 | inf | 1 | 2 | | Path Vertices From Start | [A] | [A, B] | [ ] | [A, D] | [A, D, E] | -## Step 3 +### Step 3 @@ -140,7 +140,7 @@ From now we repeat all actions again and fill our table with new info! | 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 +### Step 4 @@ -150,7 +150,7 @@ From now we repeat all actions again and fill our table with new info! | 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 +### Step 5 @@ -300,16 +300,16 @@ Also there is a **VisualizedDijkstra.playground**. Use it to figure out algorith It is up to you how to implement some specific parts of 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 +# About this repository This repository contains to playgrounds: * To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. * If you need only realization of the algorithm without visualization then run **Dijkstra.playground.** It contains necessary classes and couple functions to create random graph for algorithm testing. -## Demo video +# Demo video Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) -## Credits +# Credits WWDC 2017 Scholarship Project (Rejected) created by [Taras Nikulin](https://github.com/crabman448) From fbd5d6ea149cccd61c93530a772bad148e3a45e1 Mon Sep 17 00:00:00 2001 From: barbara Date: Thu, 25 May 2017 14:04:49 +0200 Subject: [PATCH 0400/1039] Examples for documentation --- .../Images/SplayTreesWorstCaseExamples.svg | 2 ++ Splay Tree/Images/example-zigzig-1.png | Bin 0 -> 32202 bytes Splay Tree/Images/example-zigzig-2.png | Bin 0 -> 34485 bytes Splay Tree/Images/example-zigzig-3.png | Bin 0 -> 29732 bytes Splay Tree/Images/example-zigzig-4.png | Bin 0 -> 28709 bytes Splay Tree/Images/example-zigzig-5.png | Bin 0 -> 25735 bytes Splay Tree/Images/worst-case-1.png | Bin 0 -> 6795 bytes Splay Tree/Images/worst-case-2.png | Bin 0 -> 7076 bytes Splay Tree/Images/worst-case-3.png | Bin 0 -> 9049 bytes Splay Tree/Images/worst-case-4.png | Bin 0 -> 10813 bytes Splay Tree/Images/worst-case-5.png | Bin 0 -> 11827 bytes Splay Tree/Images/worst-case-6.png | Bin 0 -> 35177 bytes Splay Tree/Images/zigzig-wrongrotated.png | Bin 0 -> 38831 bytes 13 files changed, 2 insertions(+) create mode 100644 Splay Tree/Images/SplayTreesWorstCaseExamples.svg create mode 100644 Splay Tree/Images/example-zigzig-1.png create mode 100644 Splay Tree/Images/example-zigzig-2.png create mode 100644 Splay Tree/Images/example-zigzig-3.png create mode 100644 Splay Tree/Images/example-zigzig-4.png create mode 100644 Splay Tree/Images/example-zigzig-5.png create mode 100644 Splay Tree/Images/worst-case-1.png create mode 100644 Splay Tree/Images/worst-case-2.png create mode 100644 Splay Tree/Images/worst-case-3.png create mode 100644 Splay Tree/Images/worst-case-4.png create mode 100644 Splay Tree/Images/worst-case-5.png create mode 100644 Splay Tree/Images/worst-case-6.png create mode 100644 Splay Tree/Images/zigzig-wrongrotated.png diff --git a/Splay Tree/Images/SplayTreesWorstCaseExamples.svg b/Splay Tree/Images/SplayTreesWorstCaseExamples.svg new file mode 100644 index 000000000..c07312af2 --- /dev/null +++ b/Splay Tree/Images/SplayTreesWorstCaseExamples.svg @@ -0,0 +1,2 @@ + +
1
1
2
2
1
1
2
2
1
1
2
2
3
3
1
1
2
2
3
3
1
1
2
2
3
3
4
4
1
1
2
2
3
3
4
4
1
1
2
2
3
3
4
4
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
5
5
6
6
7
7
8
8
5
5
6
6
7
7
8
8
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
\ No newline at end of file diff --git a/Splay Tree/Images/example-zigzig-1.png b/Splay Tree/Images/example-zigzig-1.png new file mode 100644 index 0000000000000000000000000000000000000000..48a08c17cf8cdbbf4de565b1ae4339a533f8b562 GIT binary patch literal 32202 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

^3u@V70z)B9iJxD+Z%NK(r?LStzHVG-% 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 G@c#kXNwKB? literal 0 HcmV?d00001 diff --git a/Splay Tree/Images/example-zigzig-3.png b/Splay Tree/Images/example-zigzig-3.png new file mode 100644 index 0000000000000000000000000000000000000000..905b4d4bd2d9638e902358172764e23e29c03da6 GIT binary patch literal 29732 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

350Y9 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 Date: Wed, 19 Apr 2017 16:44:55 +0300 Subject: [PATCH 0310/1039] Replaced _vertices with vertices --- .../Dijkstra.playground/Contents.swift | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift index cd08e26fb..1c12245bd 100644 --- a/Dijkstra Algorithm/Dijkstra.playground/Contents.swift +++ b/Dijkstra Algorithm/Dijkstra.playground/Contents.swift @@ -1,19 +1,19 @@ //: Playground - noun: a place where people can play import Foundation -var _vertices: Set = Set() +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 + var newSet = vertices newSet.remove(vertex) let offset = Int(arc4random_uniform(UInt32(newSet.count))) let index = newSet.index(newSet.startIndex, offsetBy: offset) @@ -38,9 +38,9 @@ func randomVertex(except vertex: Vertex) -> Vertex { } func randomVertex() -> Vertex { - let offset = Int(arc4random_uniform(UInt32(_vertices.count))) - let index = _vertices.index(_vertices.startIndex, offsetBy: offset) - return _vertices[index] + let offset = Int(arc4random_uniform(UInt32(vertices.count))) + let index = vertices.index(vertices.startIndex, offsetBy: offset) + return vertices[index] } //initialize random graph @@ -48,7 +48,7 @@ createNotConnectedVertices() setupConnections() //initialize Dijkstra algorithm with graph vertices -let dijkstra = Dijkstra(vertices: _vertices) +let dijkstra = Dijkstra(vertices: vertices) //decide which vertex will be the starting one let startVertex = randomVertex() @@ -63,6 +63,7 @@ var pathVerticesFromStartString: [String] = [] for vertex in destinationVertex.pathVerticesFromStart { pathVerticesFromStartString.append(vertex.identifier) } + print(pathVerticesFromStartString.joined(separator: "->")) From 93aad5ea36a1f09d62c8c877675877097e9b29fc Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 03:39:21 -0700 Subject: [PATCH 0311/1039] Added templates for the repository. --- .github/CONTRIBUTING.md | 0 .github/ISSUE_TEMPLATE.md | 19 +++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 0 3 files changed, 19 insertions(+) create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..e69de29bb diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..27a857ef5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,19 @@ +### Category + +- [ ] Bug +- [ ] Feature Request +- [ ] Question + +### Brief Intro + +> Describe this issue below in 1 sentence. + +### More Details + +> If necessary, start off with the code snippet. Put the code in between ``` to format them into code blocks. + +[INSERT CODE HERE] + +> Describe the problem in more detail. + +[INSERT DETAILS HERE] \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..e69de29bb From 5128bfa4dca199beeda930dacf0623d7f6e0e926 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:32:41 -0700 Subject: [PATCH 0312/1039] Updated contribution guidelines. --- .github/CONTRIBUTING.md | 57 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e69de29bb..a1393a2e0 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,57 @@ +# 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** + +The `README` file is the cake, and the sample code is the cherry on top. Readablity is really important for us. A good contribution has succinct explanations supported by diagrams. Code is best introduced in chunks, weaved into the explanations where relevant. + +**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 is most welcomed. + +### 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! \ No newline at end of file From 1e149dc959731e16eb303396293e1e719f86d2ef Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:33:33 -0700 Subject: [PATCH 0313/1039] Fixed broken link. --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a1393a2e0..fe8a23278 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -50,7 +50,7 @@ For the unit tests: - Uncheck **Autocreate schemes** - Check **Shared** -![Screenshot of scheme settings](Images/scheme-settings-for-travis.png) +![Screenshot of scheme settings](../Images/scheme-settings-for-travis.png) ## Want to chat? From 1620a9cb811ecac68528c8f330f45762ec1beb6a Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:34:11 -0700 Subject: [PATCH 0314/1039] Fixes another broken link in the readme. --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index fe8a23278..5b6f5d4dd 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -33,7 +33,7 @@ If what you have in mind is a new addition, please follow this process when subm 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. +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. From d83263cd7e2dcd13e7e2e8ad7c9f624fab337a00 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:43:55 -0700 Subject: [PATCH 0315/1039] Updated issue and pr template. --- .github/ISSUE_TEMPLATE.md | 10 ++-------- .github/PULL_REQUEST_TEMPLATE.md | 11 +++++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 27a857ef5..416641261 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -6,14 +6,8 @@ ### Brief Intro -> Describe this issue below in 1 sentence. + ### More Details -> If necessary, start off with the code snippet. Put the code in between ``` to format them into code blocks. - -[INSERT CODE HERE] - -> Describe the problem in more detail. - -[INSERT DETAILS HERE] \ No newline at end of file + \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e69de29bb..c52564721 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ + + +### 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 + + + From bb6c29fee3cf3549c56cf5fb351bf01b15301177 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:45:44 -0700 Subject: [PATCH 0316/1039] Fixes formatting. --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5b6f5d4dd..2b08e2633 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -14,7 +14,7 @@ A good contribution abides to the [Swift API Guidelines](https://swift.org/docum We follow the following Swift [style guide](https://github.com/raywenderlich/swift-style-guide). -### Contribution Categories +## Contribution Categories ### Refinement From aadae31ed56f8317eae20e94196b2c242994d1fb Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:54:06 -0700 Subject: [PATCH 0317/1039] Updated readme with links to updated/new contributions. --- README.markdown | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/README.markdown b/README.markdown index 29fc9d748..e0983f22e 100644 --- a/README.markdown +++ b/README.markdown @@ -8,9 +8,7 @@ If you're a computer science student who needs to learn this stuff for exams -- 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. -Most code is compatible with **Xcode 8.2** and **Swift 3**. We'll keep this updated with the latest version of Swift. - -This is a work in progress. More algorithms will be added soon. :-) +Most code is compatible with **Xcode 8.3** and **Swift 3**. We'll keep this updated with the latest version of Swift. :heart_eyes: **Suggestions and contributions are welcome!** :heart_eyes: @@ -24,9 +22,7 @@ This is a work in progress. More algorithms will be added soon. :-) [Algorithm design techniques](Algorithm%20Design.markdown). How do you create your own algorithms? -[How to contribute](How%20to%20Contribute.markdown). Report an issue to leave feedback, or submit a pull request. - -[Under construction](Under%20Construction.markdown). Algorithms that are under construction. +[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? @@ -56,7 +52,7 @@ If you're new to algorithms and data structures, here are a few good ones to sta - [Brute-Force String Search](Brute-Force%20String%20Search/). A naive method. - [Boyer-Moore](Boyer-Moore/). 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](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. @@ -103,7 +99,6 @@ Bad sorting algorithms (don't use these!): - [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. -- Statistics - [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. @@ -112,7 +107,7 @@ Bad sorting algorithms (don't use these!): - [k-Means Clustering](K-Means/). Unsupervised classifier that partitions data into *k* clusters. - k-Nearest Neighbors -- [Linear Regression](Linear%20Regression/) +- [Linear Regression](Linear%20Regression/). A technique for creating a model of the relationship between two (or more) variable quantities. - Logistic Regression - Neural Networks - PageRank @@ -153,9 +148,9 @@ Most of the time using just the built-in `Array`, `Dictionary`, and `Set` types - [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 Tree](Red-Black%20Tree/). A self balancing binary search tree. - Splay Tree -- Threaded Binary Tree +- [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. - kd-Tree - [Heap](Heap/). A binary tree stored in an array, so it doesn't use pointers. Makes a great priority queue. @@ -226,7 +221,7 @@ Other algorithm repositories: 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) and [Kelvin Lau](https://github.com/kelvinlauKL). +It is now maintained by [Vincent Ngo](https://www.raywenderlich.com/u/jomoka), [Kelvin Lau](https://github.com/kelvinlauKL) and [Ross O'brien](https://www.raywenderlich.com/u/narrativium). The Swift Algorithm Club is a collaborative effort from the [most algorithmic members](https://github.com/rwenderlich/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](How%20to%20Contribute.markdown)? :] From 2ce23ca2b1059050be7c87cf45df184dd5090008 Mon Sep 17 00:00:00 2001 From: Kelvin Lau Date: Thu, 20 Apr 2017 04:55:50 -0700 Subject: [PATCH 0318/1039] Removed old contribution guidelines. --- How to Contribute.markdown | 55 -------------------------------------- 1 file changed, 55 deletions(-) delete mode 100644 How to Contribute.markdown diff --git a/How to Contribute.markdown b/How to Contribute.markdown deleted file mode 100644 index 1235f07ff..000000000 --- a/How to Contribute.markdown +++ /dev/null @@ -1,55 +0,0 @@ -# How to contribute - -Want to help out with the Swift Algorithm Club? Great! - -## What sort of things can you contribute? - -Take a look at the [list](README.markdown). Any algorithms or data structures that don't have a link yet are up for grabs. - -Algorithms in the [Under construction](Under%20Construction.markdown) area are being worked on. Suggestions and feedback is welcome! - -New algorithms and data structures are always welcome (even if they aren't on the list). - -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. - -Unit tests. Fixes for typos. No contribution is too small. :-) - -## Please follow this process - -To keep this a high quality repo, please follow this process when submitting your contribution: - -1. Create a pull request to "claim" an algorithm or data structure. Just so multiple people don't work 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. -6. Run [SwiftLint](https://github.com/realm/SwiftLint) - - [Install](https://github.com/realm/SwiftLint#installation) - - Open terminal and run the `swiftlint` command: - -``` -cd path/to/swift-algorithm-club -swiftlint -``` - - -Just so you know, I will probably edit your text and code for grammar etc, just to ensure a certain level of polish. - -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! From 37de447879960291131d97aecb3d56c89da77429 Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:07:29 +0300 Subject: [PATCH 0319/1039] Updating --- Dijkstra Algorithm/README.md | 61 +++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/Dijkstra Algorithm/README.md b/Dijkstra Algorithm/README.md index 325bab40f..7ec9d352e 100644 --- a/Dijkstra Algorithm/README.md +++ b/Dijkstra Algorithm/README.md @@ -1,19 +1,59 @@ # Dijkstra-algorithm -## About this repository +This algorithm was invented in 1956 by Edsger W. Dijkstra. + +This algorithm 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 road network. If you wnat to find the shortest path from your house to your job, then it is time for the Dijkstra's algorithm. + +I have a gif example, which will show you how algorithm works. If this is not enough, then you can play with my **VisualizedDijkstra.playground**. +So let's image, that your house is "A" vertex and your job is "B" vertex. And you are lucky, you have graph with all possible routes. +When the algorithm starts to work initial graph looks like this: +[image1.png all are non visited] +Graph's array contains 5 vertices [A, B, C, D, E]. +Let's assume, that edge weight it is path length in kilometers between vertices. +A vertex has neighbors: B(path from A: 5.0), C(path from A: 0.0), D(path from A: 0.0) +And because algorithm has done nothing, then all vertices' path length from source vertex values are infinity (think about infinity as "I don't know, how long will it takes to get this vertex from source one") +Finally we have to set source vertex path length from source vertex to 0. + +Great, now our graph is initialized and we can pass it to the Dijkstra's algorithm. + +| | A | B | C | D | E | +| ------------------------- | --- | --- | --- | --- | --- | +| Visited | F | F | F | F | F | +| Path Length From Start | inf | inf | inf | inf | inf | +| Path Vertices From Start | [ ] | [ ] | [ ] | [ ] | [ ] | + +But before we will go through all process side by side let me explain how algorithm works. +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. + +Okay, let's start! +From now we will keep array which contains non visited vertices. Here they are: +var nonVisitedVertices = [A, B, C, D, E] +Let's follow the algorithm and pick the first vertex, which neighbors we want to check. +Imagine that we have function, that returns vertex with smallest path length from start. +var checkingVertex = nonVisitedVertices.smallestPathLengthFromStartVertex() +Then we set this vertex as visited +checkingVertex.visited = true +[image2.jpg visited first] +Then we check all of its neighbors. +If neighbor's path length from start is bigger than checking vertex path length from start + edge weigth, then we set neighbor's path length from start new value and append to its pathVerticesFromStart array new vertex: checkingVertex. Repeat this action for every vertex. +[image3.jpg visited first with checked neighbors] + + + This repository contains to playgrounds: * To understand how does this algorithm works, I have created **VisualizedDijkstra.playground.** It works in auto and interactive modes. Moreover there are play/pause/stop buttons. * If you need only realization of the algorithm without visualization 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) - -## Screenshots - - ## Dijkstra's algorithm explanation - + [Wikipedia](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)'s explanation: Let the node at which we are starting be called the initial node. Let the distance of node Y be the distance from the initial node to Y. Dijkstra's algorithm will assign some initial distance values and will try to improve them step by step. @@ -37,8 +77,13 @@ Cycle: 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. ## Usage +This algorithm is popular in routing. For example, biggest Russian IT company Yandex uses it in [Яндекс.Карты](https://yandex.ru/company/technologies/routes/) +## Demo video +Click the link: [YouTube](https://youtu.be/PPESI7et0cQ) +## VisualizedDijkstra.playground Screenshots + ## Credits WWDC 2017 Scholarship Project From f24ecc22436be2b71f6c840464d6826ddf9e258c Mon Sep 17 00:00:00 2001 From: Taras Nikulin Date: Thu, 20 Apr 2017 15:30:59 +0300 Subject: [PATCH 0320/1039] Still updating --- Dijkstra Algorithm/Images/image1.png | Bin 0 -> 61926 bytes Dijkstra Algorithm/Images/image2.png | Bin 0 -> 63758 bytes Dijkstra Algorithm/Images/image3.png | Bin 0 -> 65232 bytes Dijkstra Algorithm/Images/image4.png | Bin 0 -> 65286 bytes Dijkstra Algorithm/Images/image5.png | Bin 0 -> 66333 bytes Dijkstra Algorithm/Images/image6.png | Bin 0 -> 67070 bytes Dijkstra Algorithm/Images/image7.png | Bin 0 -> 66716 bytes Dijkstra Algorithm/README.md | 66 +++++++++++++++++++++------ 8 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 Dijkstra Algorithm/Images/image1.png create mode 100644 Dijkstra Algorithm/Images/image2.png create mode 100644 Dijkstra Algorithm/Images/image3.png create mode 100644 Dijkstra Algorithm/Images/image4.png create mode 100644 Dijkstra Algorithm/Images/image5.png create mode 100644 Dijkstra Algorithm/Images/image6.png create mode 100644 Dijkstra Algorithm/Images/image7.png diff --git a/Dijkstra Algorithm/Images/image1.png b/Dijkstra Algorithm/Images/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..aabe0969e2cf86efc9a5e2e3e313d8fa3e02818e GIT binary patch literal 61926 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 y9tz2t8pe1{?q0s@KBMqFG) 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