From 12265a8c61f8142a0601b130dc6400c0f6b2d810 Mon Sep 17 00:00:00 2001 From: Anthony Marchenko Date: Thu, 16 Mar 2017 02:05:38 +0300 Subject: [PATCH] Add examples on Swift 3.0.2 (#11) * 01_binary_search Swift 3.0.2 * 01_binary_search Swift 3.0.2 * add Chapter 2 - 01_selection_sort Swift 3.0.2 example * 01_binary_search cosmetic note updates Swift 3.0.2 * 03_recursion Swift 3.0.2 examples * 04_quicksort Swift 3.0.2 examples * fix typo on quicksort example. Swift 3.0.2 * add 05_hash_tables examples on Swift 3.0.2 * add 01_breadth-first_search Swift 3.0.2 example * 01_breadth-first_search fixing typo Swift 3.0.2 * add 01_dijkstras_algorithm on Swift 3.0.2 * add 08_greedy_algorithms Swift 3.0.2 example * 01_longest_common_subsequence Swift 3.0.2 example --- .../swift/01_binary_search.swift | 31 ++++++ .../swift/01_selection_sort.swift | 38 +++++++ 03_recursion/swift/01_countdown.swift | 16 +++ 03_recursion/swift/02_greet.swift | 18 ++++ 03_recursion/swift/03_factorial.swift | 12 +++ 04_quicksort/swift/01_loop_sum.swift | 11 +++ 04_quicksort/swift/02_recursive_sum.swift | 12 +++ 04_quicksort/swift/03_recursive_count.swift | 12 +++ 04_quicksort/swift/04_recursive_max.swift | 13 +++ 04_quicksort/swift/05_quicksort.swift | 21 ++++ .../swift/01_price_of_groceries.swift | 18 ++++ 05_hash_tables/swift/02_check_voter.swift | 18 ++++ .../swift/01_breadth-first_search.swift | 93 ++++++++++++++++++ .../swift/01_dijkstras_algorithm.swift | 79 +++++++++++++++ .../swift/01_set_covering.swift | 35 +++++++ .../swift/01_longest_common_subsequence.swift | 40 ++++++++ images/.DS_Store | Bin 10244 -> 10244 bytes .../01_introduction_to_algorithms/.DS_Store | Bin 6148 -> 6148 bytes images/02_selection_sort/.DS_Store | Bin 6148 -> 6148 bytes images/08_greedy_algorithms/.DS_Store | Bin 6148 -> 8196 bytes images/11_where_to_go_next/.DS_Store | Bin 8196 -> 8196 bytes 21 files changed, 467 insertions(+) create mode 100644 01_introduction_to_algorithms/swift/01_binary_search.swift create mode 100644 02_selection_sort/swift/01_selection_sort.swift create mode 100644 03_recursion/swift/01_countdown.swift create mode 100644 03_recursion/swift/02_greet.swift create mode 100644 03_recursion/swift/03_factorial.swift create mode 100644 04_quicksort/swift/01_loop_sum.swift create mode 100644 04_quicksort/swift/02_recursive_sum.swift create mode 100644 04_quicksort/swift/03_recursive_count.swift create mode 100644 04_quicksort/swift/04_recursive_max.swift create mode 100644 04_quicksort/swift/05_quicksort.swift create mode 100644 05_hash_tables/swift/01_price_of_groceries.swift create mode 100644 05_hash_tables/swift/02_check_voter.swift create mode 100644 06_breadth-first_search/swift/01_breadth-first_search.swift create mode 100644 07_dijkstras_algorithm/swift/01_dijkstras_algorithm.swift create mode 100644 08_greedy_algorithms/swift/01_set_covering.swift create mode 100644 09_dynamic_programming/swift/01_longest_common_subsequence.swift diff --git a/01_introduction_to_algorithms/swift/01_binary_search.swift b/01_introduction_to_algorithms/swift/01_binary_search.swift new file mode 100644 index 0000000..232c552 --- /dev/null +++ b/01_introduction_to_algorithms/swift/01_binary_search.swift @@ -0,0 +1,31 @@ +import Foundation + +// Note: If you aren’t familiar with Comparable, please check out “Generics” chapter in Swift book +func binarySearch (_ list: [T], item: T) -> Int? { + // low and high keep track of which part of the list you'll search in. + var low = 0 + var high = list.count - 1 + // While you haven't narrowed it down to one element ... + while low <= high { + //... check the middle element + let mid = low + (high - low) / 2 + let guess = list[mid] + // Found the item. + if guess == item { + return mid + } + // The guess was too high. + if guess > item { + high = mid - 1 + } else { + low = mid + 1 + } + } + + return nil +} + +let myList = [1, 3, 5, 7, 9] +print(binarySearch(myList, item: 3) ?? "Not Found") // => 1 +print(binarySearch(myList, item: -1) ?? "Not Found") // => Not Found + diff --git a/02_selection_sort/swift/01_selection_sort.swift b/02_selection_sort/swift/01_selection_sort.swift new file mode 100644 index 0000000..be0a473 --- /dev/null +++ b/02_selection_sort/swift/01_selection_sort.swift @@ -0,0 +1,38 @@ +import Foundation + +// Finds the smallest value in an array +func findSmallestIndex (_ arr: [T]) -> Int { + // Stores the smallest value + var smallest = arr[0] + // We don't need any calculation if the array lenght is 1 + if arr.count == 1 { + return 0 + } + // Stores the index of the smallest value + var smallestIndex = 0 + for i in 1...arr.count-1 { + if arr[i] < smallest { + smallest = arr[i] + smallestIndex = i + } + } + return smallestIndex +} + +// Sort array +func selectionSort (arr: [T]) -> [T] { + var newArr: [T] = [] + // We have to make mutableArray reference copy of original array, because Swift 3 doesn't allow to get var parameter + var mutableArr = arr + for _ in 0...mutableArr.count-1 { + //Finds the smallest element in the array and adds it to the new array + let smallestIndex = findSmallestIndex(mutableArr) + newArr.append(mutableArr[smallestIndex]) + mutableArr.remove(at: smallestIndex) + } + return newArr +} + +print(selectionSort(arr: [5, 3, 6, 2, 10])) // => [2, 3, 5, 6, 10] + + diff --git a/03_recursion/swift/01_countdown.swift b/03_recursion/swift/01_countdown.swift new file mode 100644 index 0000000..2166aa1 --- /dev/null +++ b/03_recursion/swift/01_countdown.swift @@ -0,0 +1,16 @@ +import Foundation + +func countDown(i : Int) { + print(i) + // base case + if i <= 0 { + return + } else { + // recursive case + countDown(i: i-1) + } +} + +countDown(i: 5) + + diff --git a/03_recursion/swift/02_greet.swift b/03_recursion/swift/02_greet.swift new file mode 100644 index 0000000..3facea9 --- /dev/null +++ b/03_recursion/swift/02_greet.swift @@ -0,0 +1,18 @@ +import Foundation + +func greet2(name: String) { + print("how are you, \(name) ?") +} + +func bye() { + print("ok bye!") +} + +func greet(name: String ) { + print("hello, \(name)!") + greet2(name: name) + print("getting ready to say bye...") + bye() +} + +greet(name: "adit") diff --git a/03_recursion/swift/03_factorial.swift b/03_recursion/swift/03_factorial.swift new file mode 100644 index 0000000..a74776d --- /dev/null +++ b/03_recursion/swift/03_factorial.swift @@ -0,0 +1,12 @@ +import Foundation + +func fact(x: Int) -> Int { + if x == 1 { + return 1 + } else { + return x*fact(x: x-1) + } +} + + +print(fact(x: 5)) // => 120 diff --git a/04_quicksort/swift/01_loop_sum.swift b/04_quicksort/swift/01_loop_sum.swift new file mode 100644 index 0000000..a6b58b4 --- /dev/null +++ b/04_quicksort/swift/01_loop_sum.swift @@ -0,0 +1,11 @@ +import Foundation + +func sum (_ arr: [Int]) -> Int { + var total = 0 + for x in arr { + total += x + } + return total +} + +print(sum([1, 2, 3, 4])) // => 10 diff --git a/04_quicksort/swift/02_recursive_sum.swift b/04_quicksort/swift/02_recursive_sum.swift new file mode 100644 index 0000000..d43f461 --- /dev/null +++ b/04_quicksort/swift/02_recursive_sum.swift @@ -0,0 +1,12 @@ +import Foundation + +func sum(list : [Int]) -> Int { + if list.count == 0 { + return 0 + } + var tempArray = list + tempArray.remove(at: 0) + return list[0] + sum(list: tempArray) +} + +print(sum(list: [1, 2, 3, 4])) // => 10 diff --git a/04_quicksort/swift/03_recursive_count.swift b/04_quicksort/swift/03_recursive_count.swift new file mode 100644 index 0000000..6b68f7f --- /dev/null +++ b/04_quicksort/swift/03_recursive_count.swift @@ -0,0 +1,12 @@ +import Foundation + +func count(list : [Int]) -> Int { + if list.count == 0 { + return 0 + } + var tempArray = list + tempArray.remove(at: 0) + return 1 + count(list: tempArray) +} + +print(count(list: [1, 2, 3, 4])) // => 4 diff --git a/04_quicksort/swift/04_recursive_max.swift b/04_quicksort/swift/04_recursive_max.swift new file mode 100644 index 0000000..e3cf8b2 --- /dev/null +++ b/04_quicksort/swift/04_recursive_max.swift @@ -0,0 +1,13 @@ +import Foundation + +func max(list : [Int]) -> Int { + if list.count == 2 { + return (list[0] > list[1]) ? list[0] : list[1] + } + var tempArray = list + tempArray.remove(at: 0) + let subMax = max(list: tempArray) + return (list[0] > subMax) ? list[0] : subMax +} + +print(max(list: [1, 5, 10, 25, 16, 1])) // => 25 diff --git a/04_quicksort/swift/05_quicksort.swift b/04_quicksort/swift/05_quicksort.swift new file mode 100644 index 0000000..e017b4d --- /dev/null +++ b/04_quicksort/swift/05_quicksort.swift @@ -0,0 +1,21 @@ +import Foundation + +//The following implementation of quick sort is little more classic than described in the book, but we have two use this one because of some “slice” feature limitation with array on Swift 3. Main concept is the same +func quicksort (_ array : [T]) -> [T] { + if (array.count < 2) { + // base case, arrays with 0 or 1 element are already "sorted" + return array + } else { + // recursive case + let pivot = array[0] + // sub-array of all the elements less than the pivot + let less = array.filter { $0 < pivot } + // sub-array of all the elements equal to the pivot + let equal = array.filter { $0 == pivot } + // sub-array of all the elements greater than the pivot + let greater = array.filter { $0 > pivot } + return quicksort(less) + equal + quicksort(greater) + } +} + +print(quicksort([1, 5, 10, 25, 16, 1])) // => [1, 1, 5, 10, 16, 25] diff --git a/05_hash_tables/swift/01_price_of_groceries.swift b/05_hash_tables/swift/01_price_of_groceries.swift new file mode 100644 index 0000000..eee11be --- /dev/null +++ b/05_hash_tables/swift/01_price_of_groceries.swift @@ -0,0 +1,18 @@ +import Foundation + +var book = [String: Double]() +// an apple costs 67 cents +book["apple"] = 0.67 +//# milk costs $1.49 +book["milk"] = 1.49 +book["avacado"] = 1.49 +print(book) // => ["avacado": 1.49, "apple": 0.67000000000000004, "milk": 1.49] + +// Qustion: Why is "apple" is 0.67000000000000004 intsted of 0.67? +// Answer: Double cannot store the value 0.67 exactly. Swift uses (like many other languages) binary floating point numbers according to the IEEE 754 standard. +// This topic is not related with Algorithms, but you can play with .description and .debugDescription for making workarrounds +print(book["apple"]?.description ?? "Not exist") // => 0.67 +print(book["apple"]?.debugDescription ?? "Not exist") // => 0.67000000000000004 + + + diff --git a/05_hash_tables/swift/02_check_voter.swift b/05_hash_tables/swift/02_check_voter.swift new file mode 100644 index 0000000..59a156c --- /dev/null +++ b/05_hash_tables/swift/02_check_voter.swift @@ -0,0 +1,18 @@ +import Foundation + +var voter = [String : Bool]() + +func checkVoter(_ name : String) { + if voter[name] != nil { + print("kick them out!") + } else { + voter[name] = true + print("let them vote!") + } +} + +checkVoter("tom") +checkVoter("mike") +checkVoter("mike") + + diff --git a/06_breadth-first_search/swift/01_breadth-first_search.swift b/06_breadth-first_search/swift/01_breadth-first_search.swift new file mode 100644 index 0000000..307ac10 --- /dev/null +++ b/06_breadth-first_search/swift/01_breadth-first_search.swift @@ -0,0 +1,93 @@ +import Foundation + +// As I can see Swift doesn't have Queue default implementation, so we have to use custom on, Degue structure from Swift Algorithm Club +// https://github.com/raywenderlich/swift-algorithm-club/tree/master/Deque +public struct Deque { + private var array = [T]() + + public var isEmpty: Bool { + return array.isEmpty + } + + public var count: Int { + return array.count + } + + public mutating func enqueue(_ element: T) { + array.append(element) + } + + public mutating func enqueueFront(_ element: T) { + array.insert(element, at: 0) + } + + public mutating func dequeue() -> T? { + if isEmpty { + return nil + } else { + return array.removeFirst() + } + } + + public mutating func dequeueBack() -> T? { + if isEmpty { + return nil + } else { + return array.removeLast() + } + } + + public func peekFront() -> T? { + return array.first + } + + public func peekBack() -> T? { + return array.last + } +} + +func persionIsSeller(name: String) -> Bool { + return name.characters.last == "m" +} + +var graph = [String : [String]]() +graph["you"] = ["alice", "bob", "claire"] +graph["bob"] = ["anuj", "peggy"] +graph["alice"] = ["peggy"] +graph["claire"] = ["thom", "jonny"] +graph["anuj"] = [] +graph["peggy"] = [] +graph["thom"] = [] +graph["jonny"] = [] + +func search(name: String) -> Bool { + var searchQueue = Deque() + //Swift Note: Our custom Deque doesn't have possibility to add new element as array so we have to add elements one by one (insted of +=graph["person"] in the book example) + for string in graph[name]! { + searchQueue.enqueue(string) + } + // This array is how you keep track of which people you've searched before. + var searched = [String]() + while !searchQueue.isEmpty { + let person = searchQueue.dequeue() + // Only search this person if you haven't already searched them + if !searched.contains(person!) { + if persionIsSeller(name: person!) { + print("\(person!) is a mango seller!") + return true + } else { + for string in graph[person!]! { + searchQueue.enqueue(string) + } + // Marks this person as searched + searched.append(person!) + } + } + } + + return false +} + +if search(name: "you") == false { + print("Mango seller Not Found!") +} // => thom is a mango seller! diff --git a/07_dijkstras_algorithm/swift/01_dijkstras_algorithm.swift b/07_dijkstras_algorithm/swift/01_dijkstras_algorithm.swift new file mode 100644 index 0000000..e0453e9 --- /dev/null +++ b/07_dijkstras_algorithm/swift/01_dijkstras_algorithm.swift @@ -0,0 +1,79 @@ +import Foundation + +// the graph +var graph = [String : [String: Double]] () +graph["start"] = [String: Double]() +graph["start"]?["a"] = 6 +graph["start"]?["b"] = 2 + +graph["a"] = [String: Double]() +graph["a"]?["fin"] = 1 + +graph["b"] = [String: Double]() +graph["b"]?["a"] = 3 +graph["b"]?["fin"] = 5 + +graph["fin"] = [String: Double]() + +// the costs table +let infinity = Double.infinity +var costs = [String: Double]() +costs["a"] = 6 +costs["b"] = 2 +costs["fin"] = infinity + +// the parents table +var parents = [String: String]() +parents["a"] = "start" +parents["b"] = "start" +parents["fin"] = nil + +var processed = [String]() + +func findLowestCostNode(costs: [String: Double]) -> [String: Double] { + var lowestCost = Double.infinity + var lowestCostNode = [String: Double]() + // Go through each node. + for node in costs { + let cost = node.value + // If it's the lowest cost so far and hasn't been processed yet... + if (cost < lowestCost) && !processed.contains(node.key) { + // ... set it as the new lowest-cost node. + lowestCost = cost + lowestCostNode = [node.key : node.value] + } + + } + return lowestCostNode +} + +// Find the lowest-cost node that you haven't processed yet. +var node = findLowestCostNode(costs: costs) + +// If you've processed all the nodes, this while loop is done. +while !node.isEmpty { + // Swift Note: Unfortunately there are some limits for working with Dictionary inside Dictionary, so we have to use temp "nodeFirstKey" variable as workaround + var nodeFirstKey = node.first?.key + var cost = costs[nodeFirstKey!] + // Go through all the neighbors of this node. + var neighbors = graph[nodeFirstKey!] + for n in (neighbors?.keys)! { + var newCost = cost! + (neighbors?[n])! + // If it's cheaper to get to this neighbor by going through this node... + if costs[n]! > newCost { + // ... update the cost for this node. + costs[n] = newCost + // This node becomes the new parent for this neighbor. + parents[n] = nodeFirstKey + } + } + // Mark the node as processed. + processed.append(nodeFirstKey!) + // Find the next node to process, and loop. + node = findLowestCostNode(costs: costs) +} + + +print("Cost from the start to each node:") +print(costs) // -> ["b": 2.0, "fin": 6.0, "a": 5.0] + diff --git a/08_greedy_algorithms/swift/01_set_covering.swift b/08_greedy_algorithms/swift/01_set_covering.swift new file mode 100644 index 0000000..53edbf4 --- /dev/null +++ b/08_greedy_algorithms/swift/01_set_covering.swift @@ -0,0 +1,35 @@ +import Foundation + +// You pass an array in, and it gets converted to a set. +var statesNeeded : Set = ["mt", "wa", "or", "id", "nv", "ut", "ca", "az"] + +var stations = [String: Set]() +stations["kone"] = ["id", "nv", "ut"] +stations["ktwo"] = ["wa", "id", "mt"] +stations["kthree"] = ["or", "nv", "ca"] +stations["kfour"] = ["nv", "ut"] +stations["kfive"] = ["ca", "az"] + +var finalStations = Set(); + +while !statesNeeded.isEmpty { + var bestStation = String() + var statesCovered = Set() + + for station in stations { + var covered = statesNeeded.intersection(station.value) + if covered.count > statesCovered.count { + bestStation = station.key + statesCovered = covered + } + statesNeeded = statesNeeded.subtracting(statesCovered) + //Swift note: We should avoid adding empty station to Set + if !bestStation.isEmpty { + finalStations.insert(bestStation) + } + } +} + +print(finalStations) // -> ["kone", "kfive", "ktwo", "kthree"] + + diff --git a/09_dynamic_programming/swift/01_longest_common_subsequence.swift b/09_dynamic_programming/swift/01_longest_common_subsequence.swift new file mode 100644 index 0000000..cdee14c --- /dev/null +++ b/09_dynamic_programming/swift/01_longest_common_subsequence.swift @@ -0,0 +1,40 @@ +import Foundation + +if wordA[i] == wordB[j] { + // The letters match + cell[i][j] = cell[i-1][j-1] + 1 +} else { + // The letters don't match. + cell[i][j] = max(cell[i-1][j], cell[i][j-1]) +} + +/* Working example for "play" with + +var wordA = "fish" +var wordB = "hish" +var cell : [[Int]] = Array(repeating: Array(repeating: 0, count: wordA.characters.count), count: wordB.characters.count) +let wordAArray = wordA.characters.map { String($0) } +let wordBArray = wordB.characters.map { String($0) } + +for i in 0...wordA.characters.count-1 { + for j in 0...wordB.characters.count-1 { + // The letters match + if wordAArray[i] == wordBArray[j] { + if i > 0 && j > 0 { + cell[i][j] = cell[i-1][j-1] + 1 + } else { + cell[i][j] = 1 + } + } else { + // The letters don't match. + if i > 0 && j > 0 { + cell[i][j] = max(cell[i-1][j], cell[i][j-1]) + } else { + cell[i][j] = 0 + } + } + } +} + +*/ + diff --git a/images/.DS_Store b/images/.DS_Store index 0d94bdaf73c7952287fc0481e6a14731958e8e1d..5c67fbf06caf66800d77eec5317eccdd06ca20a4 100644 GIT binary patch delta 70 zcmZn(XbISGQ=F-ebMky~9lqRr7nhXMl4J&kE3cQHnH(sg2NX&{6|!M$nCvKJxOu;X J6hB0tCIGZ@8M^=g delta 70 zcmZn(XbISGQ=F-cbMky~9lqRr7nhXMl4J&kOU`8xlLIC6fI=y#LN<&AlO3fDH}98_ J;)m$d1OQp97XbhO diff --git a/images/01_introduction_to_algorithms/.DS_Store b/images/01_introduction_to_algorithms/.DS_Store index 44223fcb9819bb8a45a94beac1b9a2a6ebfe8722..fe6182d2841bcb39c577b9307c49b9a7fa7aa4da 100644 GIT binary patch delta 76 zcmZoMXffDO#KLmr_0m(5*RW_zp2xxk<1AtWi83%umSNSJT*t}*5$|H10Aa|nX~7r@ Kn{(J^2m$~jKOuks delta 76 zcmZoMXffDO#KLk}I>~7A8WxSo^H{iGoJDMxrIR}t7$(cGYE7u_0m(5_p#_r-oU~Il4+9XbqWlYXe0=;(pG#wBlN}p$7Iu zGa68j&MBl(ZnQQi0VSXWlzp=jgsmb42&oG^RdUCoyF~?ulb$~GE9!;?Nk@uhZ){O z(7Xi81Z7CWPq}V()-n6iJ_`6P;UmYXw2uWIo3d0&`?%>$$D?@M2M68`c7^9rhG&A+ zIK$@Uj=-ZzOI7xxU{bY-u@k?=+;gXe8yOFmQsWoKf^QRcTY7X z3(s}q<$f6-1$^v%FL50OTuS>`;IZdnDw>o)B?+wBS=TxKKl}Li|4OpaNh^V>5HPiN zr`^JAU2L73H^Rx+ApQ9d0om{4y8p{P J(4u+-UIE}m9tZ#c delta 128 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{MGqg`E6q~50D9Q+A12Isngdu|=l_8!Xn;~yv zp*kbu|Z3 MY-HFR&ohS^09B+FVgLXD diff --git a/images/11_where_to_go_next/.DS_Store b/images/11_where_to_go_next/.DS_Store index d1ad04877ab512fe6de3541994622b8551dcb49b..0ad5315d36da4df2f3ef5c89279adf8f60ced8f4 100644 GIT binary patch delta 215 zcmZp1XmQvOB*1dz_0ltwYXl@F=LvAZIJ4M5q6`d^9|-92rMRS&mLxMUz=d=sw+LoI zlztM_fiRSWZa^6Sgo0oUkI8d{yC57b5gQ02OXLoO;U($=VayW!0AV~3bK%R)N49PA N1F-K8&MY>d=w1ef$qxkd_)=U_N=uR%7~n!WlUoF{ zfJzq`PW~jQ17Ro$-2gGZPW~qp1Y>wio+I1^?P_0VayW! e0Awt0oBTk`g)cWBVcYVy%@4%V*ho^Y!UzD;gIPQP