├── .gitignore ├── LICENSE ├── README.md ├── art └── swift.png └── challenges ├── 01_unique.swift ├── 02_palindrome.swift ├── 03_sameCharacters.swift ├── 04_contains.swift ├── 05_charCount.swift ├── 06_removeDuplicates.swift ├── 07_condensedWhiteSpace.swift ├── 08_isRotate.swift ├── 09_isPangram.swift ├── 10_vowelsConsonants.swift └── 11_threeLetterDiff.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dulio Denis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swift Coding Challenges 2 | ![](art/swift.png?raw=true) 3 | 4 | These Swift code challenges cover important concepts for any coding interview. The solutions are all in Swift 3 and Swift 4. 5 | 6 | ## Strings 7 | 8 | | No. | Challenge 9 | | ------------- | ------------- 10 | | 1. | [Are the letters unique?](challenges/01_unique.swift) 11 | | 2. | [Is the string a palindrome?](challenges/02_palindrome.swift) 12 | | 3. | [Do two strings contain the same characters?](challenges/03_sameCharacters.swift) 13 | | 4. | [Does one String contain another String?](challenges/04_contains.swift) 14 | | 5. | [How many times does a character appear in a string?](challenges/05_charCount.swift) 15 | | 6. | [Remove duplicate letters from a string.](challenges/06_removeDuplicates.swift) 16 | | 7. | [Condensed white space.](challenges/07_condensedWhiteSpace.swift) 17 | | 8. | [Is the string rotated?](challenges/08_isRotate.swift) 18 | | 9. | [Is the string a pangram?](challenges/09_isPangram.swift) 19 | | 10. | [Return a tuple of a string's vowels and consonants.](challenges/10_vowelsConsonants.swift) 20 | | 11. | [Are two strings identical with no more than a three letter difference?](challenges/11_threeLetterDiff.swift) 21 | 22 | ### Licensing 23 | My Swift Coding Challenges Solutions are licensed under [the MIT License](LICENSE). 24 | 25 | ### Support or Contact 26 | Visit [ddApps.co](http://ddapps.co) to see more. 27 | -------------------------------------------------------------------------------- /art/swift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duliodenis/swift-coding-challenges/bdb7ba330b70f13d3bb145de330b164615149a4c/art/swift.png -------------------------------------------------------------------------------- /challenges/01_unique.swift: -------------------------------------------------------------------------------- 1 | // Are the letters unique? 2 | // Write a function that accepts a string as its only param and returns 3 | // true if the string has only unique letters taking letter case into account. 4 | func isUnique(_ input: String) -> Bool { 5 | var checkLetter = [Character]() 6 | for letter in input.characters { 7 | if checkLetter.contains(letter) { 8 | return false 9 | } 10 | checkLetter.append(letter) 11 | } 12 | 13 | return true 14 | } 15 | 16 | func isUnique2(_ input: String) -> Bool { 17 | return Set(input.characters).count == input.characters.count 18 | } 19 | 20 | // call function 21 | print(isUnique("AaBbCc")) // true 22 | print(isUnique("Hello, world!")) // false 23 | 24 | print(isUnique2("AaBbCc")) // true 25 | print(isUnique2("Hello, world!")) // false 26 | 27 | // Swift 4 28 | func isUnique3(_ input: String) -> Bool { 29 | return Set(input).count == input.count 30 | } 31 | 32 | 33 | print(isUnique3("AaBbCc")) // true 34 | print(isUnique3("Hello, world!")) // false 35 | -------------------------------------------------------------------------------- /challenges/02_palindrome.swift: -------------------------------------------------------------------------------- 1 | // Is a string a palindrome? 2 | // Write a function that accepts a String as its only parameter, and returns 3 | // true if the string reads the same when reversed, ignoring case. 4 | 5 | func isPalindrome(_ input: String) -> Bool { 6 | let reversedInput = String(input.characters.reversed()) 7 | if input == reversedInput { 8 | return true 9 | } 10 | return false 11 | } 12 | 13 | // the one line of code solution 14 | func isPalindrome2(_ input: String) -> Bool { 15 | return String(input.characters.reversed()) == input 16 | } 17 | 18 | // case insensitive 19 | func isPalindromeCaseInsensitive(_ input: String) -> Bool { 20 | return String(input.lowercased().characters.reversed()) == input.lowercased() 21 | } 22 | 23 | print(isPalindrome("rotator")) // true 24 | print(isPalindrome("palindrome")) // false 25 | 26 | print(isPalindrome2("rotator")) // true 27 | print(isPalindrome2("roTator")) // false - not case sensitive 28 | print(isPalindrome2("palindrome")) // false 29 | 30 | print(isPalindromeCaseInsensitive("rotator")) // true 31 | print(isPalindromeCaseInsensitive("roTator")) // true - case sensitive 32 | print(isPalindromeCaseInsensitive("palindrome")) // false 33 | 34 | // Swift 4 35 | func isPalindrome3(_ word: String) -> Bool { 36 | return word == String(word.reversed()) 37 | } 38 | 39 | func isPalindromeCaseInsensitive2(_ word:String) -> Bool { 40 | return word.lowercased() == String(word.reversed()).lowercased() 41 | } 42 | 43 | 44 | print(isPalindrome3("rotator")) // true 45 | print(isPalindrome3("roTator")) // false - not case sensitive 46 | print(isPalindrome3("palindrome")) // false 47 | 48 | print(isPalindromeCaseInsensitive2("rotator")) // true 49 | print(isPalindromeCaseInsensitive2("roTator")) // true - case sensitive 50 | print(isPalindromeCaseInsensitive2("palindrome")) // false 51 | -------------------------------------------------------------------------------- /challenges/03_sameCharacters.swift: -------------------------------------------------------------------------------- 1 | // Do two strings contain the same characters? 2 | // Write a function that accepts two String parameters, and returns 3 | // true if they contain the same characters in any order. 4 | 5 | func isSameCharacters(_ input1: String, _ input2: String) -> Bool { 6 | let input1Array = Array(input1.characters) 7 | var input2Array = Array(input2.characters) 8 | 9 | // brute force - O(n^2) 10 | for input1char in input1Array { 11 | for input2char in input2Array { 12 | // nested for loops check for matches 13 | if input2char == input1char { 14 | // remove the match 15 | if let index = input2Array.index(of: input2char) { 16 | input2Array.remove(at: index) 17 | } 18 | } 19 | } 20 | // if everything matched the array is empty - return true 21 | if input2Array.count == 0 { 22 | return true 23 | } 24 | } 25 | // otherwise the strings did not match - return false 26 | return false 27 | } 28 | 29 | // tighen up the check and return code 30 | func isSameCharacters2(_ input: String, _ check: String) -> Bool { 31 | let inputArray = Array(input.characters) 32 | var checkArray = Array(check.characters) 33 | 34 | // brute force - O(n^2) 35 | for inputChar in inputArray { 36 | // remove this character if its found in the check array 37 | if let index = checkArray.index(of: inputChar) { 38 | checkArray.remove(at: index) 39 | } 40 | } 41 | return checkArray.count == 0 42 | } 43 | 44 | // sorted arrays - O(n log n) 45 | func isSameCharactersSorted(_ input: String, _ check: String) -> Bool { 46 | let inputArray = Array(input.characters) 47 | let checkArray = Array(check.characters) 48 | 49 | return inputArray.sorted() == checkArray.sorted() 50 | } 51 | 52 | print(isSameCharacters("hello", "world")) // false 53 | print(isSameCharacters("hello", "hello")) // true 54 | 55 | print(isSameCharacters2("hello", "world")) // false 56 | print(isSameCharacters2("hello", "hello")) // true 57 | 58 | print(isSameCharactersSorted("hello", "world")) // false 59 | print(isSameCharactersSorted("hello", "hello")) // true 60 | 61 | // Swift 4 62 | func isSameCharactersSorted2(_ one: String, _ two: String) -> Bool { 63 | return one.sorted() == two.sorted() 64 | } 65 | 66 | 67 | print(isSameCharactersSorted2("hello", "world")) // false 68 | print(isSameCharactersSorted2("hello", "hello")) // true 69 | -------------------------------------------------------------------------------- /challenges/04_contains.swift: -------------------------------------------------------------------------------- 1 | // Does one String contain another String? 2 | // Write your own version of the contains method on String that 3 | // ignores letter case. 4 | // See: https://developer.apple.com/reference/swift/string/1643241-contains 5 | // Returns true iff other is non-empty and contained within self by 6 | // case-sensitive, non-literal search. 7 | 8 | import Foundation 9 | 10 | extension String { 11 | func doesContain(_ substring: String) -> Bool { 12 | return self.lowercased().range(of: substring.lowercased()) != nil 13 | } 14 | 15 | //Swift 4 16 | func doesContain2(_ substring: String) -> Bool { 17 | return lowercased().contains(substring.lowercased()) 18 | } 19 | } 20 | 21 | print("hello".doesContain("world")) // false 22 | print("hello".doesContain("hello")) // true 23 | 24 | 25 | print("hello".doesContain2("world")) // false 26 | print("hello".doesContain2("hello")) // true 27 | -------------------------------------------------------------------------------- /challenges/05_charCount.swift: -------------------------------------------------------------------------------- 1 | // Count the characters 2 | // Write a function that accepts a string, and returns how many times a specific 3 | // character appears. Case sensitive. 4 | 5 | // the classy way with a for-in loop 6 | func charCount(_ input: String, char find: Character) -> Int { 7 | var count = 0 8 | for char in input.characters { 9 | if char == find { 10 | count += 1 11 | } 12 | } 13 | return count 14 | } 15 | 16 | // introduce a constraint of no for-in or while loop 17 | 18 | // a functional approach 19 | func charCountNoFor(_ input: String, char check: Character) -> Int { 20 | return input.characters.reduce(0) { 21 | $1 == check ? $0 + 1 : $0 22 | } 23 | } 24 | 25 | // an arithmetic solution 26 | import Foundation 27 | 28 | func charCountWithRemoval(_ input: String, char check: String) -> Int { 29 | let newInput = input.replacingOccurrences(of: check, with: "") 30 | return input.characters.count - newInput.characters.count 31 | } 32 | 33 | //Swift 4 34 | func charCount2(_ input: String, char check: Character) -> Int { 35 | var count = 0 36 | input.forEach { if $0 == check { count += 1 }} 37 | return count 38 | } 39 | 40 | func charCountNoFor2(_ input: String, char check: Character) -> Int { 41 | return input.reduce(0) { 42 | $1 == check ? $0 + 1 : $0 43 | } 44 | } 45 | 46 | // Test Cases 47 | 48 | charCount("hello", char: "h") // 1 49 | charCount("hello", char: "l") // 2 50 | charCount("hello", char: "q") // 0 51 | charCount("hello", char: "H") // 0 52 | 53 | charCountNoFor("hello", char: "h") // 1 54 | charCountNoFor("hello", char: "l") // 2 55 | charCountNoFor("hello", char: "q") // 0 56 | charCountNoFor("hello", char: "H") // 0 57 | 58 | charCountWithRemoval("hello", char: "h") // 1 59 | charCountWithRemoval("hello", char: "l") // 1 60 | charCountWithRemoval("hello", char: "q") // 1 61 | charCountWithRemoval("hello", char: "H") // 1 62 | 63 | charCount2("hello", char: "h") // 1 64 | charCount2("hello", char: "l") // 2 65 | charCount2("hello", char: "q") // 0 66 | charCount2("hello", char: "H") // 0 67 | 68 | charCountNoFor2("hello", char: "h") // 1 69 | charCountNoFor2("hello", char: "l") // 2 70 | charCountNoFor2("hello", char: "q") // 0 71 | charCountNoFor2("hello", char: "H") // 0 72 | -------------------------------------------------------------------------------- /challenges/06_removeDuplicates.swift: -------------------------------------------------------------------------------- 1 | // Remove duplicate letters from a string. 2 | // Write a function that accepts a string as its input and 3 | // return a string with the duplicate letters removed. 4 | 5 | func removeDuplicatesFrom(_ input: String) -> String { 6 | var returnString = Array(input.characters) 7 | var i = 0 8 | var length = returnString.count 9 | 10 | while i < length - 1 { 11 | if returnString[i] == returnString[i+1] { 12 | returnString.remove(at: i+1) 13 | length -= 1 14 | } 15 | i+=1 16 | } 17 | 18 | return String(returnString) 19 | } 20 | 21 | print(removeDuplicatesFrom("hello")) // helo 22 | print(removeDuplicatesFrom("helo")) // helo 23 | print(removeDuplicatesFrom("Helllo,, worrld!!")) // Hello, world! 24 | 25 | // ---------------------------------------------------------- 26 | // Second approach using a for in and an additive array 27 | 28 | func removeDuplicatesFrom2(_ input: String) -> String { 29 | var usedCharacters = [Character]() 30 | 31 | for letter in input.characters { 32 | if !usedCharacters.contains(letter) { 33 | usedCharacters.append(letter) 34 | } 35 | } 36 | 37 | return String(usedCharacters) 38 | } 39 | 40 | print(removeDuplicatesFrom2("hello")) // helo 41 | print(removeDuplicatesFrom2("helo")) // helo 42 | print(removeDuplicatesFrom2("Helllo,, worrld!!")) // Helo, wrd! 43 | 44 | 45 | // ---------------------------------------------------------- 46 | // A third solution - a functional approach using a dictionary 47 | // (note: this solution has poor performance) 48 | 49 | func removeDuplicatesFrom3(_ input: String) -> String { 50 | var usedCharacters = [Character: Bool]() 51 | 52 | let result = input.characters.filter { 53 | usedCharacters.updateValue(true, forKey: $0) == nil 54 | } 55 | 56 | return String(result) 57 | } 58 | 59 | print(removeDuplicatesFrom3("hello")) // helo 60 | print(removeDuplicatesFrom3("helo")) // helo 61 | print(removeDuplicatesFrom3("Helllo,, worrld!!")) // Helo, wrd! 62 | 63 | 64 | // Swift 4 65 | func removeDuplicatesFrom4(_ str: String) -> String { 66 | var usedChar = String() 67 | str.forEach { if !usedChar.contains($0) { usedChar.append($0) }} 68 | return usedChar 69 | } 70 | 71 | print(removeDuplicatesFrom4("hello")) // helo 72 | print(removeDuplicatesFrom4("helo")) // helo 73 | print(removeDuplicatesFrom4("Helllo,, worrld!!")) // Helo, wrd! 74 | -------------------------------------------------------------------------------- /challenges/07_condensedWhiteSpace.swift: -------------------------------------------------------------------------------- 1 | // Challenge 7: Condensed white space 2 | // Write a function that returns a string with any consecutive spaces 3 | // replaced with a single space. 4 | 5 | func truncateWhiteSpaces(_ input: String) -> String { 6 | var returnedString = Array(input.characters) 7 | 8 | var i = 0 9 | var length = returnedString.count 10 | 11 | while i < length - 1 { 12 | if returnedString[i] == " " && returnedString[i+1] == " " { 13 | returnedString.remove(at: i) 14 | length -= 1 15 | continue 16 | } 17 | i += 1 18 | } 19 | 20 | return String(returnedString) 21 | } 22 | 23 | print(truncateWhiteSpaces("Hello, world!")) // Hello, world! 24 | print(truncateWhiteSpaces(" a")) // [1 space]a 25 | 26 | 27 | // --------------------------------------------------- 28 | // Alternate solution with a for in loop 29 | 30 | func truncateWhiteSpaces2(_ input: String) -> String { 31 | var spaceDetected = false 32 | var returnString = String() 33 | 34 | for letter in input.characters { 35 | if letter == " " { 36 | if spaceDetected { continue } 37 | spaceDetected = true 38 | } else { 39 | spaceDetected = false 40 | } 41 | returnString.append(letter) 42 | } 43 | 44 | return returnString 45 | } 46 | 47 | print("-------------------") 48 | print(truncateWhiteSpaces2("Hello, world!")) // Hello, world! 49 | print(truncateWhiteSpaces2(" a")) // [1 space]a 50 | 51 | 52 | // --------------------------------------------------- 53 | // Alternate solution using a regular expression 54 | // Note: this solution is not performance oriented. 55 | 56 | import Foundation 57 | 58 | func truncateWhiteSpaces3(_ input: String) -> String { 59 | return input.replacingOccurrences(of: " +", with: " ", options: .regularExpression, range: nil) 60 | } 61 | 62 | print("-------------------") 63 | print(truncateWhiteSpaces3("Hello, world!")) // Hello, world! 64 | print(truncateWhiteSpaces3(" a")) // [1 space]a 65 | -------------------------------------------------------------------------------- /challenges/08_isRotate.swift: -------------------------------------------------------------------------------- 1 | // Challenge 8: String is rotated 2 | // Write a function that accepts two strings, and returns true if 3 | // one string is a rotation of the other. 4 | 5 | import Foundation 6 | 7 | // classic brute force solution 8 | 9 | func isRotate(string1: String, string2:String) -> Bool { 10 | let letter = Array(string1.characters)[0] 11 | var string2_index = 0 12 | 13 | // short circuit if the two strings are not of equal length 14 | if string1.characters.count != string2.characters.count { 15 | return false 16 | } 17 | 18 | for match in string2.characters { 19 | if letter == match { 20 | // make a new string out of the slice before the match and compare 21 | let newIndex = string2.index(string2.startIndex, offsetBy: string2_index) 22 | 23 | let prefix = string2.substring(to: newIndex) 24 | let suffix = string2.substring(from: newIndex) 25 | let potential_Rotate = "\(suffix)\(prefix)" 26 | 27 | if string1 == potential_Rotate { 28 | return true 29 | } 30 | } 31 | string2_index += 1 // increment the index to string 2 32 | } 33 | return false 34 | } 35 | 36 | print("-------------------") 37 | print(isRotate(string1: "Swift", string2: "ftSwi")) // true 38 | print(isRotate(string1: "tca", string2: "cat")) // true 39 | print(isRotate(string1: "atc", string2: "cat")) // true 40 | print(isRotate(string1: "dog", string2: "catty")) // false 41 | 42 | 43 | // ------------------------------------------------------------- 44 | // Alternate solution which doubles the second string 45 | // and if the first is in the second and they are the same length 46 | // then its a rotation. 47 | 48 | func isRotateDoubler(_ input: String, _ rotated: String) -> Bool { 49 | guard input.characters.count == rotated.characters.count else { return false } 50 | 51 | let doubledUp = rotated + rotated 52 | return doubledUp.contains(input) 53 | } 54 | 55 | print("-------------------") 56 | print(isRotateDoubler("Swift", "ftSwi")) // true 57 | print(isRotateDoubler("tca", "cat")) // true 58 | print(isRotateDoubler("atc", "cat")) // true 59 | print(isRotateDoubler("dog", "catty")) // false 60 | 61 | //Swift 4 62 | func isRotateDoubler2(_ strOne: String, _ strTwo: String) -> Bool { 63 | guard strOne.count == strTwo.count else { return false } 64 | return (strTwo+strTwo).contains(strOne) 65 | } 66 | 67 | print("-------------------") 68 | print(isRotateDoubler2("Swift", "ftSwi")) // true 69 | print(isRotateDoubler2("tca", "cat")) // true 70 | print(isRotateDoubler2("atc", "cat")) // true 71 | print(isRotateDoubler2("dog", "catty")) // false 72 | -------------------------------------------------------------------------------- /challenges/09_isPangram.swift: -------------------------------------------------------------------------------- 1 | // Challenge 9: Is the string a pangram? 2 | // Write a function that returns true if a given string is an English pangram. 3 | 4 | func isPangram(_ input: String) -> Bool { 5 | var alphabet = Array("abcdefghijklmnopqrstuvwxyz".characters) 6 | 7 | for letter in input.lowercased().characters { 8 | if let index = alphabet.index(of: letter) { 9 | alphabet.remove(at: index) 10 | } 11 | if alphabet.count == 0 { return true } 12 | } 13 | return false 14 | } 15 | 16 | print("---------------") 17 | print(isPangram("The quick brown fox jumps over the lazy dog.")) // true 18 | print(isPangram("The quick brown fox jumped over the lazy dog.")) // false - missing s 19 | 20 | //Swift 4 21 | func isPangram2(_ string: String) -> Bool { 22 | var isPan = true 23 | "abcdefghijklmnopqrstuvwxyz".forEach({ 24 | if !string.lowercased().contains($0) { isPan = false } 25 | }) 26 | return isPan 27 | } 28 | 29 | print("---------------") 30 | print(isPangram2("The quick brown fox jumps over the lazy dog.")) // true 31 | print(isPangram2("The quick brown fox jumped over the lazy dog.")) // false - missing s 32 | -------------------------------------------------------------------------------- /challenges/10_vowelsConsonants.swift: -------------------------------------------------------------------------------- 1 | // Challenge 10: Vowels and Consonants 2 | // Write a function that returns a tuple containing the number of vowels and consonants. 3 | 4 | func vowelConsonants(_ input: String) -> (vowels: Int, consonants: Int) { 5 | let vowels = "aeiou".characters 6 | let consonants = "bcdfghjklmnpqrstvwxyz".characters 7 | var vowelCount = 0 8 | var consonantCount = 0 9 | 10 | for letter in input.lowercased().characters { 11 | if consonants.contains(letter) { 12 | consonantCount += 1 13 | } else { 14 | // check again to weed out punctuations 15 | if vowels.contains(letter) { 16 | vowelCount += 1 17 | } 18 | } 19 | } 20 | return (vowelCount, consonantCount) 21 | } 22 | 23 | print("---------------") 24 | print(vowelConsonants("hello, world")) // (3, 7) 25 | print(vowelConsonants("Mississippi")) // (4, 7) 26 | 27 | 28 | //Swift 4 29 | func vowelConsonants2(_ str: String) -> (vowels: Int, consonants: Int) { 30 | var numOfVow = 0 31 | var numOfCon = 0 32 | str.lowercased().forEach { 33 | if "bcdfghjklmnpqrstvwxyz".contains($0) { numOfCon += 1 } 34 | else if "aeiou".contains($0) { numOfVow += 1 } 35 | } 36 | return (numOfVow, numOfCon) 37 | } 38 | 39 | print("---------------") 40 | print(vowelConsonants2("hello, world")) // (3, 7) 41 | print(vowelConsonants2("Mississippi")) // (4, 7) 42 | -------------------------------------------------------------------------------- /challenges/11_threeLetterDiff.swift: -------------------------------------------------------------------------------- 1 | // Challenge 11: Three Different Letters 2 | // Write a function that accepts two strings, and returns true if they are 3 | // identical in length but have no more than three different letters. 4 | 5 | func threeLetterDiff(_ input1: String, _ input2: String) -> Bool { 6 | if input1.characters.count != input2.characters.count { return false } 7 | var difference = 0 8 | 9 | for letter in input1.characters { 10 | if input2.characters.contains(letter) == false { 11 | difference += 1 12 | } 13 | if difference > 3 { return false } 14 | } 15 | 16 | return true 17 | } 18 | 19 | print("---------------") 20 | print(threeLetterDiff("One", "Three")) // false - different length 21 | print(threeLetterDiff("String", "Threes")) // false - 4 letter difference 22 | print(threeLetterDiff("Hello", "World")) // true - 3 letter difference 23 | print(threeLetterDiff("Clamp", "Cramp")) // true - 1 letter difference 24 | 25 | //Swift 4 26 | func threeLetterDiff2(_ strOne: String, _ strTwo: String) -> Bool { 27 | guard strOne.count == strTwo.count else { return false } 28 | let setOne = Set(strOne) 29 | return setOne.subtracting(strTwo).count <= 3 30 | } 31 | 32 | print("---------------") 33 | print(threeLetterDiff2("One", "Three")) // false - different length 34 | print(threeLetterDiff2("String", "Threes")) // false - 4 letter difference 35 | print(threeLetterDiff2("Hello", "World")) // true - 3 letter difference 36 | print(threeLetterDiff2("Clamp", "Cramp")) // true - 1 letter difference 37 | --------------------------------------------------------------------------------