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 0d94bda..5c67fbf 100644 Binary files a/images/.DS_Store and b/images/.DS_Store differ diff --git a/images/01_introduction_to_algorithms/.DS_Store b/images/01_introduction_to_algorithms/.DS_Store index 44223fc..fe6182d 100644 Binary files a/images/01_introduction_to_algorithms/.DS_Store and b/images/01_introduction_to_algorithms/.DS_Store differ diff --git a/images/02_selection_sort/.DS_Store b/images/02_selection_sort/.DS_Store index 12e6bc1..6857b75 100644 Binary files a/images/02_selection_sort/.DS_Store and b/images/02_selection_sort/.DS_Store differ diff --git a/images/08_greedy_algorithms/.DS_Store b/images/08_greedy_algorithms/.DS_Store index 075d427..ec94de8 100644 Binary files a/images/08_greedy_algorithms/.DS_Store and b/images/08_greedy_algorithms/.DS_Store differ diff --git a/images/11_where_to_go_next/.DS_Store b/images/11_where_to_go_next/.DS_Store index d1ad048..0ad5315 100644 Binary files a/images/11_where_to_go_next/.DS_Store and b/images/11_where_to_go_next/.DS_Store differ