├── .gitignore ├── CTA ├── Binary-Tree-Breadth-First-Traversal.playground │ ├── Contents.swift │ └── contents.xcplayground └── README.md ├── PostCTA ├── KVOIntroduction.playground │ ├── Contents.swift │ └── contents.xcplayground └── README.md ├── README.md ├── Unit1 ├── Arrays-Part-1.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Arrays-Part-2.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Classes.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Closures-Part-1.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Control-Flow.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Dictionaries.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Enums-Part-1.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Enums-Part-2.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Functions-Part-1.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Initialization.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Loops-Part-1.playground │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ └── alexpaul.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── Loops-Part-2.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Optionals-Preview.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Optionals.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Questions-Review-10-04-19.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Questions-Review-Closures-Custom-map.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Questions-Review-Enums.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Questions-Review-Optionals-Dictionaries.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Questions-Review-Sets.playground │ ├── Contents.swift │ └── contents.xcplayground ├── README.md ├── ReadLineDemo │ ├── .DS_Store │ ├── ReadLineDemo.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ ├── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcuserdata │ │ │ │ └── alexpaul.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── alexpaul.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── ReadLineDemo │ │ └── main.swift ├── Sets.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Strings-Part-1.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Strings-Part-2.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Structs-and-Classes-Wrapup.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Structs.playground │ ├── Contents.swift │ └── contents.xcplayground ├── TriviaGame.zip ├── TriviaGame │ ├── README.md │ ├── TriviaGame.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── TriviaGame │ │ ├── Game.swift │ │ ├── Question.swift │ │ ├── TriviaData.swift │ │ ├── TriviaType.swift │ │ └── main.swift └── Types-Variables.playground │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ └── alexpaul.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── Unit2 ├── Big-O-Notation.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Protocols.playground │ ├── Contents.swift │ └── contents.xcplayground └── README.md ├── Unit3 ├── JSONParsing.playground │ ├── Contents.swift │ └── contents.xcplayground └── README.md ├── Unit4 ├── Generics-inout-Functions-Stacks.playground │ ├── Contents.swift │ └── contents.xcplayground ├── LinkedList.playground │ ├── Contents.swift │ └── contents.xcplayground └── README.md ├── Unit5 ├── BinarySearch.playground │ ├── Contents.swift │ └── contents.xcplayground ├── BubbleSort.playground │ ├── Contents.swift │ └── contents.xcplayground ├── InsertionSort.playground │ ├── Contents.swift │ └── contents.xcplayground ├── MergeSort.playground │ ├── Contents.swift │ └── contents.xcplayground ├── Queues.playground │ ├── Contents.swift │ └── contents.xcplayground ├── QuickSort.playground │ ├── Contents.swift │ └── contents.xcplayground └── README.md ├── Unit6 ├── Contiguous-Array-LeetCode.playground │ ├── Contents.swift │ └── contents.xcplayground └── README.md └── Unit7 ├── BinarySearchTree.playground ├── Contents.swift └── contents.xcplayground ├── DoublyLinkedList.playground ├── Contents.swift └── contents.xcplayground ├── HashTable.playground ├── Contents.swift └── contents.xcplayground └── README.md /.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 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots/**/*.png 68 | fastlane/test_output 69 | 70 | .DS_Store 71 | -------------------------------------------------------------------------------- /CTA/Binary-Tree-Breadth-First-Traversal.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Binary Tree - Abstract data type 4 | // the components of a tree are the root node, child node 5 | 6 | // a node is referred to as a leaf if it does not have 7 | // any children 8 | 9 | // There are 2 ways to traverse a binary tree 10 | // 1. Breadth-first traversal - uses a queue to keep track of visited nodes 11 | // 2. Depth-first traversal: in-order, post-order, pre-order 12 | 13 | class BinaryTreeNode { 14 | var value: T // T is a generic, can hold any data type, e.g Int, String.... 15 | var leftChild: BinaryTreeNode? 16 | var rightChild: BinaryTreeNode? 17 | init(_ value: T) { 18 | self.value = value 19 | } 20 | } 21 | 22 | // queue - is a FIFO data structure 23 | // FIFO - first in first out 24 | struct Queue { 25 | private var elements = [T]() 26 | 27 | public var isEmpty: Bool { 28 | return elements.isEmpty 29 | } 30 | 31 | public var count: Int { 32 | return elements.count 33 | } 34 | 35 | // looks at the front of the queue (line) 36 | public var peek: T? { 37 | return elements.first 38 | } 39 | 40 | // add an element to the back of the queue 41 | public mutating func enqueue(_ item: T) { 42 | elements.append(item) // O(1) 43 | } 44 | 45 | // removes the first element from the (front) queue 46 | public mutating func dequeue() -> T? { 47 | guard !elements.isEmpty else { return nil } 48 | return elements.removeFirst() // O(n) // we will optimize post CTA 49 | } 50 | } 51 | 52 | 53 | /* 54 | root 55 | 1 56 | / \ 57 | 2 3 58 | / \ 59 | 4 5 60 | */ 61 | 62 | let rootNode = BinaryTreeNode(1) 63 | let twoNode = BinaryTreeNode(2) 64 | let threeNode = BinaryTreeNode(3) 65 | let fourNode = BinaryTreeNode(4) 66 | let fiveNode = BinaryTreeNode(5) 67 | 68 | rootNode.leftChild = twoNode 69 | rootNode.rightChild = threeNode 70 | twoNode.leftChild = fourNode 71 | twoNode.rightChild = fiveNode 72 | 73 | 74 | /* 75 | root 76 | 1 77 | / \ 78 | 2 3 79 | / \ 80 | 4 5 81 | */ 82 | 83 | extension BinaryTreeNode { 84 | func breadthFirstTraversal(visit: (BinaryTreeNode) -> ()) { 85 | // using a queue to keep track of nodes as they are being visited 86 | // enqueues any children of that node to the Queue 87 | var queue = Queue() 88 | visit(self) // self represents the root node 89 | // visit(self) // we are capturing the current node as opposed to printing in this method 90 | queue.enqueue(self) // add the root node to the queue 91 | // we are adding the root node to the queue in order to also visit its children (left, right child) 92 | 93 | while let node = queue.dequeue() { 94 | // check for left child and enqueue as needed 95 | if let leftChild = node.leftChild { // using optional binding 96 | visit(leftChild) 97 | queue.enqueue(leftChild) 98 | } 99 | // check for right child and enqueue as needed 100 | if let rightChild = node.rightChild { 101 | visit(rightChild) 102 | queue.enqueue(rightChild) 103 | } 104 | } 105 | } 106 | } 107 | 108 | 109 | // test out breadth-first traversal 110 | 111 | print("breadth-first traversal") 112 | rootNode.breadthFirstTraversal { (node) in 113 | print(node.value, terminator: " ") // 1 2 3 4 5 114 | } 115 | 116 | print("\n") 117 | 118 | -------------------------------------------------------------------------------- /CTA/Binary-Tree-Breadth-First-Traversal.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CTA/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexpaul/Lecture-Resources/f5f6712fb3caa0d3931a88415d023d24b2b87c5c/CTA/README.md -------------------------------------------------------------------------------- /PostCTA/KVOIntroduction.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // KVO - Key-value observing 4 | 5 | // KVO is part of the observer pattern 6 | // NotifcationCenter is also an observer pattern 7 | // NotificationCenter.postNofication(name: "API ready") 8 | 9 | // KVO is a one-to many pattern relationship as opposed to delegation which is a one-to-one 10 | 11 | // In the delegation pattern 12 | // class ViewController: UIViewController {} 13 | // eg. tableView.dataSource = self 14 | 15 | // KVO is an Objective-C runtime API 16 | // Along with KVO being an objective-c runtime some essentials are required 17 | // 1. The object being observed needs to be a class 18 | // 2. The class needs to inherit from NSObject, NSObject is the top abstract class in Objective-C. The class also needs to be marked @objc 19 | // 3. Any property being marked for observation needs to be prefixed with @objc dynamic. dynamic means that the property is being dynamically dispatched (at runtime the compiler verifies the underlying property) 20 | // In swift types are statically dispatched which means they are checked at compile time vs Objective-C which is dynamiclly dispatched and checked at runtime. 21 | 22 | // Static vs dynamic dispatch 23 | // https://medium.com/flawless-app-stories/static-vs-dynamic-dispatch-in-swift-a-decisive-choice-cece1e872d 24 | 25 | // Dog class (class being observed) - will have a property to be observed 26 | @objc class Dog: NSObject { // Dog is KVO-compliant 27 | var name: String 28 | @objc dynamic var age: Int // age is a observable property 29 | init(name: String, age: Int) { 30 | self.name = name 31 | self.age = age 32 | } 33 | } 34 | 35 | 36 | // Observer class one 37 | class DogWalker { // class ViewController1 38 | let dog: Dog 39 | var birthdayObservation: NSKeyValueObservation? // a handle for the property being observed i.e age property on Dog 40 | // similart to ListenerRegistration in Firebase 41 | // e.g listenerRegistration: ListenerRegistration? 42 | 43 | var nameObservation: NSKeyValueObservation? 44 | 45 | init(dog: Dog) { 46 | self.dog = dog 47 | configureBirthdayObservation() 48 | } 49 | 50 | private func configureNameObservation() {} 51 | 52 | private func configureBirthdayObservation() { 53 | // \.age is keyPath syntax for KVO observing 54 | birthdayObservation = dog.observe(\.age, options: [.old, .new], changeHandler: { (dog, change) in 55 | // update UI accordingly if in a ViewController class 56 | // oldValue e.g 5 (if 5 gets incremented by 1 new value will be 6) 57 | // newValue e.g 6 58 | guard let age = change.newValue else { return } 59 | print("Hey \(dog.name), happy \(age) birthday from the dog walker") 60 | print("dogWalker: oldValue is \(change.oldValue ?? 0)") 61 | print("dogWalker: newValue is \(change.newValue ?? 0)\n") 62 | }) 63 | } 64 | } 65 | 66 | 67 | // Observer class two 68 | class DogGroomer { // class ViewController2 69 | let dog: Dog 70 | var birthdayObservation: NSKeyValueObservation? 71 | 72 | init(dog: Dog) { 73 | self.dog = dog 74 | configureBirthdayObservation() 75 | } 76 | 77 | private func configureBirthdayObservation() { 78 | birthdayObservation = dog.observe(\.age, options: [.old, .new], changeHandler: { (dog, change) in 79 | 80 | // unwrap the newValue property on change as it's optional 81 | guard let age = change.newValue else { return } 82 | print("Hey \(dog.name), happy \(age) birthday from the dog groomer.") 83 | print("groomer oldValue: \(change.oldValue ?? 0)") 84 | print("groomer newValue: \(change.newValue ?? 0)\n") 85 | }) 86 | } 87 | } 88 | 89 | // test out KVO observing on the .age property of Dog 90 | // both classes (DogWalker and DogGroomer should get .age changes) 91 | 92 | let snoopy = Dog(name: "Snoopy", age: 5) 93 | let dogWalker = DogWalker(dog: snoopy) // both dogWalker and dogGroomer have a reference to snoopy 94 | let dogGroomer = DogGroomer(dog: snoopy) 95 | 96 | snoopy.age += 1 // increment from 5 to 6 97 | 98 | -------------------------------------------------------------------------------- /PostCTA/KVOIntroduction.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /PostCTA/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Unit1/Arrays-Part-1.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Arrays - an array is an ordered collection of items 4 | 5 | //=========================================== 6 | // initializing arrays 7 | //=========================================== 8 | 9 | // using Type Annotation we are declaring an 10 | // array of type String 11 | var bucketList: [String] 12 | 13 | bucketList = ["France", "Austrailia", "South Africa", "Aruba", "Cozumel", "Brazil", "Japan"] 14 | 15 | print(bucketList) 16 | 17 | // count the items in the array 18 | print("There are \(bucketList.count) countries on my bucket list") 19 | 20 | var threeDoubles = Array(repeating: 0.0, count: 3) 21 | 22 | print(threeDoubles) // [0.0, 0.0, 0.0] 23 | 24 | 25 | //=========================================== 26 | // accessing values inside an array 27 | //=========================================== 28 | 29 | // tuples 30 | var juan = (name: "Juan", cohort: 6.3, hobby: "gaming") 31 | var shaniya = (name: "Shaniya", cohort: 6.3, hobby: "music yeah") 32 | var fellows = [juan, shaniya] 33 | 34 | 35 | // array of planets 36 | // declaring an array using an array literal 37 | var planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"] 38 | var dwarfPlanets = ["Pluto"] 39 | 40 | // accessing "Earth" planet using subscripting [2] 41 | let thirdRockFromTheSun = planets[2] 42 | print("Our home planet is \(thirdRockFromTheSun)") 43 | 44 | let lastPlanet = planets[planets.count - 1] 45 | print("the last planet in our solar system is \(lastPlanet)") 46 | 47 | // print the second to the last planet 48 | let secondToLastPlanet = planets[planets.count - 2] 49 | print("second to last planet is \(secondToLastPlanet)") 50 | 51 | 52 | // print the middle planet 53 | // declare a variable middlePlanet and print out it's value 54 | let middlePlanet = planets[planets.count / 2] 55 | print("Our middle planet is \(middlePlanet)") 56 | 57 | 58 | //=========================================== 59 | // some properties and methods on arrays 60 | //=========================================== 61 | 62 | // property - a variable on an object e.g planets.count 63 | // method - a function that runs on an instance of an object e.g planets.append(:_) 64 | 65 | // first 66 | // if planets.first is NOT nil assign the value to the firstPlanet constant 67 | // 68 | 69 | // think about planets.first as being a condition of true or false where if first does not exist the condition is false, if first exist then the condition is true 70 | 71 | // however long term we will come to realize that planets.first implies that either we have a valid value of String or not in the case that it's nil i.e planets array is empty 72 | 73 | // here we are using optional binding to unwrap the first? value 74 | 75 | // BOTH WAYS OF DECLARING THE ARRAY BELOW ARE VALID 76 | 77 | // USING TYPE ANNOTATION 78 | //var programmingLanguages: [String] = [] 79 | 80 | // USING TYPE INFERENCE 81 | var programmingLanguages = [String]() 82 | 83 | 84 | // using isEmpty property on an array 85 | // isEmpty is preferable over using .count 86 | if programmingLanguages.isEmpty { 87 | print("we need to start progrmming") 88 | } else { 89 | print("programming is fundamental") 90 | } 91 | 92 | if programmingLanguages.count == 0 { 93 | print("what are you waiting for????") 94 | } 95 | 96 | //=========================================== 97 | // append to an array - add to an array 98 | //=========================================== 99 | 100 | programmingLanguages.append("Swift") 101 | 102 | if let firstProgrammingLanguage = programmingLanguages.first { 103 | // if we have a valid value of String 104 | // we enter this if block {.....} 105 | print("first programming language is \(firstProgrammingLanguage)") 106 | } else { 107 | print("looks like you haven't started using any programming languages") 108 | } 109 | 110 | 111 | 112 | //=========================================== 113 | // remove(at:) - removing items from an array 114 | //=========================================== 115 | 116 | print("there are \(planets.count) planets") 117 | 118 | planets.append("Pluto") 119 | 120 | print("there are \(planets.count) planets") 121 | 122 | print(planets) // 9 planets 123 | 124 | let removedPlanet = planets.remove(at: planets.count - 1) // 9 - 1 = 8 125 | 126 | print("looks like \(removedPlanet) was ditched again 😞") 127 | 128 | print("there are \(planets.count) planets") 129 | 130 | //=========================================== 131 | // remove all elements in an array 132 | // using removeAll() 133 | //=========================================== 134 | //planets.removeAll() // 0 planets 135 | 136 | print("there are \(planets.count) planets in the solar system") 137 | 138 | let randomPlanet = planets.randomElement() ?? "PlanetX" // using nil-coelescing ?? we default to a value of "Earth" 139 | print("random planet is \(randomPlanet)") 140 | 141 | // popLast() 142 | 143 | //planets.removeAll() 144 | 145 | let oopsAnotherPlanetIsGone = planets.popLast() ?? "Ameni's Planet" 146 | 147 | print("another planet was gone \(oopsAnotherPlanetIsGone)") 148 | 149 | 150 | //=========================================== 151 | // modifying arrays 152 | //=========================================== 153 | var classRoom1 = ["Maigrett", "Gregg", "Adam"] 154 | var classRoom2 = ["Aaron", "Jack", "Vic"] 155 | 156 | // adding or concatenating arrays together 157 | // NOTE: when adding arrays together they need to be of the same data type 158 | 159 | 160 | // DOES NOT COMPILE, CANNOT ADD DIFFERENT ARRAY TYPES TOGETHER 161 | //classRoom1 += [56, 56] 162 | 163 | classRoom1 += classRoom2 164 | 165 | print("class room 1 has \(classRoom1.count) of fellows") 166 | 167 | 168 | //=========================================== 169 | // iterating or looping through arrays 170 | //=========================================== 171 | // method 1: interating through array using for-in loop without using an index 172 | 173 | planets.append("Neptune") 174 | 175 | for planet in planets { 176 | print("Planet is \(planet)") 177 | } 178 | 179 | // method 2: interating using enumerated() to gain access to the current index in the for-in loop 180 | for (index, planet) in planets.enumerated() { 181 | print("\(planet) \(index + 1)") 182 | } 183 | 184 | // method 3: using a range 185 | for index in 0.. 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Arrays-Part-2.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | // Arrays Part 2 4 | 5 | //==================================================== 6 | // array review 7 | //==================================================== 8 | 9 | 10 | var musicalArtists = ["Bob Marley", 11 | "Burning Spear", "Steel Pulse", "Mos Def", "The Beatles", 12 | "Norah Jones", "John Mayer", "Lauryn Hill"] 13 | 14 | let artist = musicalArtists[2] 15 | print("currently playing \(artist) on Spotify") 16 | 17 | 18 | //==================================================== 19 | // array slice 20 | //==================================================== 21 | 22 | // array slice 23 | // a view of the array 24 | let reggaeStars = musicalArtists[1...3] 25 | print("Some Reggae superstars are \(reggaeStars)") 26 | 27 | 28 | //==================================================== 29 | // modifying an element 30 | //==================================================== 31 | 32 | 33 | // modify the value of an array using subscripting 34 | musicalArtists[1] += " (The Reggae Legend)" 35 | print(musicalArtists) 36 | 37 | // replace an element using subscript 38 | musicalArtists[musicalArtists.count - 1] = "Prince" 39 | 40 | print(musicalArtists) 41 | 42 | for artist in musicalArtists { 43 | if artist == "John Mayer" { 44 | print("Acoustic genius") 45 | break // ends the loop 46 | } 47 | print("searching for John Mayer......") 48 | } 49 | 50 | // tuple review 51 | let artist1 = (name: "John Mayer", genre: "Pop") 52 | let artist2 = (name: "Beyonce", genre: "Pop, Country, Hip-Hop, Soca, Afro-beat") 53 | let artitsts = [artist1, artist2] 54 | 55 | for artist in artitsts { 56 | print("artist name is \(artist.name)") 57 | } 58 | 59 | //==================================================== 60 | // multi-dimensional arrays 61 | //==================================================== 62 | 63 | let matrix = [[1, 2, 3], 64 | [4, 5, 6], 65 | [7, 8, 9]] 66 | 67 | let exampleArr = ["Brendon", "Eddie"] 68 | 69 | // print out the size of the multi-dimensional array 70 | print("current count is \(matrix.count)") 71 | 72 | // using a for-in loop print out the elements of the matrix 73 | 74 | // matrix is an array - also a multi-dimensional array 75 | for arr in matrix { 76 | 77 | // each element in the matrix is an array 78 | for num in arr { // e.g first time ran => 1, 2, 3 79 | print(num, terminator: " ") 80 | } 81 | print() 82 | } 83 | 84 | // using subscripting on a multi-dimensional array 85 | let firstInnerArray = matrix[0] 86 | print("first element in matrix array is \(firstInnerArray)") 87 | 88 | // print out last element 89 | 90 | // count of matrix is 3 91 | // how to find last index in matrix array 92 | // count - 1 => 2 93 | // matrix[2] // don't hard code!!!! 94 | let lastInnerArray = matrix[matrix.count - 1]// hard coding matrix[2] 95 | print("the last element in matrix array is \(lastInnerArray)") 96 | -------------------------------------------------------------------------------- /Unit1/Arrays-Part-2.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Classes.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // classes: building block that enable us to create complex "objects" in our program. Those objects are created using properties and methods. 4 | 5 | //======================================================= 6 | // class syntax 7 | //======================================================= 8 | 9 | class MyFirstClass { 10 | 11 | } 12 | 13 | // Day not has added functionality to count how many 14 | // cases it has e.g here it is 3 15 | // enum Day conforms (adds more functionality) to CaseIterable 16 | enum Day: CaseIterable { 17 | case monday, tueday, wednesday 18 | } 19 | Day.allCases.count 20 | 21 | //======================================================= 22 | // inheritance - ONLY classes can inherit from other classes 23 | //======================================================= 24 | 25 | class Person { 26 | var name = "Jane Doe" // stored property 27 | var age = 21 28 | 29 | // instance methods 30 | func info() { 31 | print("This person name is \(name) and age is \(age)") 32 | } 33 | } 34 | 35 | // Fellow inherits from Person 36 | // Fellow is a subclass of Person 37 | // Person is the parent or superclass of Fellow 38 | // In Swift we only have single inheritance, meaning you can ONLY 39 | // inherit from one parent 40 | 41 | // Object-oriented programming consists on those concepts: 42 | // - inheritance 43 | // - encapsulation: use private access modifiers on your properties and access them externally through methods 44 | // - polymorphism - changing the form of an object 45 | 46 | // The class Fellow inherits from the Person class above 47 | class Fellow: Person { 48 | // DOES NOT COMPILE BECAUSE PARENT HAS THE SAME METHOD NAME 49 | // SO FELLOW NEEDS TO USE the override keyword 50 | // func info() { 51 | // 52 | // } 53 | override func info() { 54 | print("\(name) is a fellow at Pursuit and is \(age) years old") 55 | } 56 | } 57 | 58 | class Employee: Person { 59 | // properties 60 | var position = "iOS developer" 61 | var salary = 85_000 62 | 63 | // instance methods 64 | override func info() { 65 | print("\(position) is making $\(salary)") 66 | } 67 | } 68 | 69 | // creating an instance of Fellow() 70 | let brendon = Fellow() 71 | brendon.name = "Brendon" 72 | brendon.age = 31 73 | brendon.info() 74 | 75 | // before the Fellow class over rode info() method from the Person class this was the output from the print statement 76 | // "This person name is Brendon and age is 31" 77 | 78 | // after over ridding info() in the Fellow class the print statment comes from the overriden method 79 | // "Brendon is a fellow at Pursuit and is 31 years old" 80 | 81 | 82 | /* DOES NOT COMPILE - STRUCTS CANNOT INHERIT FROM OTHER STRUCTS 83 | struct Artist { } - If Artist is a protocol then code will compile 84 | struct PopStar: Artist { } 85 | */ 86 | 87 | 88 | //======================================================= 89 | // polymorphism - changing form on an object 90 | //======================================================= 91 | 92 | // instance of a Person 93 | let tom = Person() 94 | tom.name = "Tom" 95 | 96 | // instance of an Employee 97 | let john = Employee() 98 | john.name = "John" 99 | 100 | // instance of a Fellow 101 | let bienbenido = Fellow() 102 | bienbenido.name = "Bienbenido" 103 | 104 | // an array of instances from above 105 | let people = [tom, john, bienbenido] 106 | 107 | // if we were to loop over the people array what for example would be the info() message for bienbenido 108 | 109 | for person in people { 110 | person.info() 111 | } 112 | 113 | //======================================================= 114 | // struct are value-types - meaning assigning a new variable 115 | // that new variable gets a copy of 116 | // the original. Changing the copy 117 | // does not change the original 118 | // 119 | // classes are reference types - multiple instances point to 120 | // the same object meaning object b can 121 | // mutate object a 122 | //======================================================= 123 | 124 | // creating an instance of Fellow() named anna 125 | let anna = Fellow() 126 | anna.name = "Anna" 127 | print(anna.name) // Anna 128 | 129 | // assinging luba the anna object 130 | let luba = anna // both anna and luba are pointing to the same object 131 | print(luba.name) // Anna 132 | 133 | luba.name = "Luba" 134 | print(luba.name) // Luba 135 | 136 | // what is anna's name if printed 137 | print(anna.name) // Luba 138 | 139 | //======================================================= 140 | // Swift provides a way to check for object equality of 141 | // identity using === 142 | //======================================================= 143 | if anna === luba { // ONLY available on classes 144 | print("both object are pointing to the same reference") 145 | } 146 | 147 | 148 | //======================================================= 149 | // introduction to initializer in classes 150 | //======================================================= 151 | 152 | struct Dog { 153 | var breed: String 154 | var age: Int 155 | } 156 | // creating an instance of Dog using the memberwise initializer 157 | // of the Dog struct, ONLY structs provide memberwise initialzers 158 | var frenchBulldog = Dog(breed: "French Bulldog", age: 7) 159 | 160 | // compiler error if class does not provide default values 161 | // for ALL properties 162 | class Game { 163 | // properties 164 | var name: String 165 | var noOfPlayers: Int 166 | 167 | // initializers 168 | init(name: String, noOfPlayers: Int) { 169 | self.name = name 170 | // basketball.name = "basketball" 171 | 172 | self.noOfPlayers = noOfPlayers // 5 173 | // basketball.noOfPlayers = 5 174 | } 175 | 176 | // instance method 177 | func info() { 178 | print("\(name) has \(noOfPlayers) players") 179 | } 180 | } 181 | // creating an instance of Game() called basketball 182 | let basketball = Game(name: "Basketball", noOfPlayers: 5) 183 | let football = Game(name: "Football", noOfPlayers: 11) 184 | 185 | basketball.info() 186 | 187 | // accessing properties 188 | basketball.name = "NBA" 189 | 190 | basketball.info() 191 | 192 | 193 | //======================================================= 194 | // creating instances from a dictionary 195 | //======================================================= 196 | 197 | class Playlist { 198 | // properties 199 | var name: String 200 | var trackCount: Int 201 | var description: String 202 | var isTop100: Bool 203 | 204 | // initializer 205 | init(name: String, 206 | trackCount: Int, 207 | description: String, 208 | isTop100: Bool){ 209 | self.name = name 210 | self.trackCount = trackCount 211 | self.description = description 212 | self.isTop100 = isTop100 213 | } 214 | 215 | // instance method 216 | func info() { 217 | print("\(name) contains \(trackCount) tracks. \(description)") 218 | if isTop100 { 219 | print("\(name) is on the top 100 Spotify list") 220 | } 221 | } 222 | } 223 | 224 | let playlistDict: [String: Any] = ["name": "Best Pop Songs 2019", 225 | "trackCount": 128, 226 | "description": "Awesome playlist", 227 | "isTop100": true 228 | ] 229 | 230 | // write a function that takes a dictionary of type [String: Any] and returns an optional Playlist? 231 | func getPlaylist(dict: [String: Any]) -> Playlist { 232 | // accessing the name key in dict["name"] 233 | // used typecasting of Any type to String type using optional downcasting as? 234 | // used nil-coalescing to unwrap optional String? to String 235 | let name = dict["name"] as? String ?? "no name available" 236 | let trackCount = dict["trackCount"] as? Int ?? 0 237 | let description = dict["description"] as? String ?? "no description is availble" 238 | let isTop100 = dict["isTop100"] as? Bool ?? false 239 | let playlist = Playlist(name: name, 240 | trackCount: trackCount, 241 | description: description, 242 | isTop100: isTop100) 243 | return playlist 244 | } 245 | // calling the getPlalist function which return a Playlist 246 | let playlist = getPlaylist(dict: playlistDict) 247 | playlist.info() 248 | 249 | 250 | -------------------------------------------------------------------------------- /Unit1/Classes.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Closures-Part-1.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Closures: is a block of code that can be called in our program similar to a function. In fact a closure is a type of function. We will see and recognize differences as we journey through this course. 4 | 5 | //===================================================== 6 | // function review 7 | //===================================================== 8 | 9 | // returns void 10 | // internal parameter name are used in the function body 11 | // definition 12 | // external parameter name is used by the caller, they will see the external name e.g printGreeting(name: "Bob") 13 | 14 | // default parameter value we will set on age is 21 15 | // in the case the caller of our function does not 16 | // provide age argument we will default to showing 21 17 | // set default value on the data type that we are 18 | // interested in, e.g age: Int = 21 19 | func printGreeting(_ name: String, _ age: Int = 21) { 20 | // code 21 | print("Good morning \(name), welcome to iOS 6.3, your age is \(age)") 22 | } 23 | 24 | // call function 25 | printGreeting("Alex") 26 | 27 | 28 | for index in 0..<4 { 29 | print("Good Friday morning", terminator: "🥳") // default newline character for terminator"\n" 30 | } 31 | 32 | print() 33 | 34 | 35 | 36 | //===================================================== 37 | // closure syntax 38 | //===================================================== 39 | 40 | /* 41 | { (paramerters) -> (return type) in 42 | // code here 43 | } 44 | */ 45 | 46 | // closures: 47 | // - can be passed as function parameters 48 | // - can be assigned into a variable or constant 49 | // - can be returned from a function 50 | 51 | // example closure 1 52 | // greeting is a closure, does not have paramerters, does not return a value, returns Void (nothing) 53 | let greeting = { 54 | print("Welcome to closures.") 55 | } 56 | 57 | greeting() 58 | 59 | // closure that takes parameters and returns a value 60 | let square = { (num: Int) -> (Int) in 61 | return num * num 62 | } 63 | print(square(10)) 64 | 65 | // refactoring square closure above to make use of 66 | // shorthand closure syntax and shorthand argument names 67 | // $0 is the first parameter, here we ONLY have one parameter, if you have e.g two parameters it would be $0 followed by $1 and so on 68 | let squareShorthandSyntax: (Int) -> (Int) = { $0 * $0 } 69 | print(squareShorthandSyntax(25)) // 25 * 25 = 625 70 | 71 | // practice, create add, subtract, multiply and divide using shorthand closure syntax and argument names 72 | 73 | // subtract trailing closure implicity return the value of the subtraction, return keyword is not needed 74 | let subtractSyn: (Int, Int) -> (Int) = { $0 - $1 } 75 | print(subtractSyn(5, 2)) 76 | 77 | 78 | //===================================================== 79 | // closures as function parameters 80 | // closures are "first class citizen" meaning we can pass 81 | // closures into functions as parameters similar as we do with variables in functions, we can also return a closure 82 | //===================================================== 83 | 84 | // the name of the closure could be anyname, here we are simply using the word "closure" but it could be "action", "myClosure".......... 85 | func helloGreeting(closure: (String) -> ()) {// 86 | closure("Heather") // value was captured by the closure 87 | print("Hello iOS 6.3") 88 | } 89 | 90 | // calling a function that takes in a closure using trailing closure synax 91 | helloGreeting { name in 92 | print("Hello, \(name) it's Friday 🚀") 93 | } 94 | 95 | func printClosure(action: () -> ()) { 96 | action() 97 | } 98 | 99 | // defined a closure named printingAction 100 | // no paramerter, no return 101 | let printingAction = { 102 | print("inside printCloser trailing closure") 103 | } 104 | 105 | // called our printClosure 106 | printClosure(action: printingAction) 107 | 108 | 109 | //===================================================== 110 | // use some built-in higher order functions (closures) 111 | // - map {....} - tranforms a value. e.g 4 * 4 = 16 112 | // returns an array of collection 113 | // - filter {....} - filters values based on a condition 114 | // return an array of collection 115 | // - reduce(0, +) - takes an initial value, e.g 0 and a 116 | // closure e.g + (addition) and combines all the values 117 | // and returns the result 118 | // - compactMap {....} - returns non-nil values 119 | // - sorted { > } - you provide a sorting closure and it 120 | // returns the collection sorted accordingly 121 | // - forEach {....} - similar to the for-in loop 122 | //===================================================== 123 | 124 | // given an array of integers return an array where each value is squared 125 | // input: [1, 2, 3, 4, 5, 6] 126 | // output: [1, 4, 9, 16, 25, 36] 127 | let list1 = [1, 2, 3, 4, 5, 6] 128 | func returnSquares(arr: [Int]) -> [Int] { 129 | var squares = [Int]() 130 | for num in arr { 131 | squares.append(num * num) 132 | } 133 | return squares 134 | } 135 | print(returnSquares(arr: list1)) // [1, 4, 9, 16, 25, 36] 136 | 137 | //===================================================== 138 | // using map 139 | //===================================================== 140 | let usingMapResults = list1.map { $0 * $0 } 141 | print(usingMapResults) 142 | 143 | 144 | //===================================================== 145 | // using filter 146 | //===================================================== 147 | // given an array of fellows return only fellows where 148 | // their names begin with "a" case-insensitive 149 | // input = ["George", "Tom", "Ahad", "James", "Ameni"] 150 | // output = ["Ahad", "Ameni"] 151 | let list2 = ["George", "Tom", "Ahad", "James", "Ameni"] 152 | let fiteredResults = list2.filter { $0.lowercased().hasPrefix("a") } 153 | print(fiteredResults) 154 | 155 | 156 | //===================================================== 157 | // using reduce 158 | //===================================================== 159 | // given an array of integers return the sum 160 | // input: [10, -10, 50, 20] 161 | // output: 70 162 | let list3 = [10, -10, 50, 20] 163 | let reducedResults = list3.reduce(0, +) 164 | print(reducedResults) 165 | 166 | 167 | //===================================================== 168 | // using compactMap 169 | //===================================================== 170 | // given an optional array of integers return ONLY valid 171 | // integers 172 | // input: [nil, 56, 12, -89, nil, nil, 0, 6] 173 | // ouput: [56, 12, -89, 0, 6] 174 | let list4 = [nil, 56, 12, -89, nil, nil, 0, 6] 175 | let compactedResults = list4.compactMap { $0 } 176 | print(compactedResults) 177 | -------------------------------------------------------------------------------- /Unit1/Closures-Part-1.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Control-Flow.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Control Flow, Tuples 4 | 5 | // if / else 6 | 7 | // block of code { code in here } 8 | 9 | /* 10 | // example 1 - if statement 11 | if(some condition is true) { 12 | execute code 13 | } 14 | other code runs as normal 15 | 16 | // example 2 - if/else statment 17 | if(some condition is true) { 18 | execute this block of code 19 | } else { 20 | something other statement will get executed 21 | } 22 | other code runs as normal 23 | 24 | // example 3 - if/else if/ else 25 | 26 | */ 27 | 28 | // built-in functions we have seen so far include: 29 | /* 30 | print() 31 | lowercased() 32 | round() - e.g 1.345 => 1.35 33 | */ 34 | 35 | //==================================================== 36 | // if 37 | //==================================================== 38 | 39 | var day = "Friday"//.lowercased() 40 | 41 | if day == "friday" { 42 | print("woohoo TGIF 🍺") 43 | } 44 | print("control flow is cool") 45 | 46 | 47 | //==================================================== 48 | // if / else 49 | //==================================================== 50 | 51 | day = "Monday".lowercased() 52 | 53 | if day == "saturday" { 54 | print("it's a beach day") 55 | } else { 56 | print("just another day") 57 | } 58 | 59 | day = "monday" 60 | 61 | print("Today is \(day)") 62 | 63 | 64 | 65 | //==================================================== 66 | // if / else if / else 67 | //==================================================== 68 | 69 | var temperature: Double = 0 // degrees 70 | 71 | if temperature < 45 { // scope of if block is within curly bracket { ... } 72 | print("it's cold don't forget your gloves") 73 | if temperature == 0 { // nested if statements 74 | print("I'm dead") 75 | // danger zone approaching pyramid of death 💀 76 | // if { 77 | // if { 78 | // if { 79 | // if { 80 | // 81 | // } 82 | // } 83 | // } 84 | // } 85 | } 86 | } else if temperature == 85 { 87 | print("this is my kind of weather") 88 | print("cool let's have a picnic") 89 | } else { 90 | print("the temperature for today is \(temperature)") 91 | } 92 | 93 | 94 | //==================================================== 95 | // Ternary Operator - means 3 96 | // 97 | // (condition - means evaluates to true or false) 98 | // (conditon) ? execute if true : execute if false 99 | // vs 100 | // if (condition) { 101 | // // code here 102 | // } else { 103 | // 104 | // } 105 | //==================================================== 106 | 107 | var age = 20 108 | 109 | print(age > 20 ? "you can have that drink 🍺" : "get back to Grandma's house") 110 | 111 | 112 | 113 | //==================================================== 114 | // Switch Statement 115 | //==================================================== 116 | 117 | var cohort = "web".lowercased() // input 118 | 119 | switch cohort { 120 | case "iOS".lowercased(): 121 | print("iOS is awesome!!!!") // outputd 122 | print("great to have you guys") 123 | case "android": 124 | print("droids.....") 125 | case "web": 126 | print("full stack dudes and duddettes") 127 | //print("python 🐍 blah") // DRY - do not repeat yourself 128 | fallthrough // exectutes the following case 129 | case "backend": 130 | print("python 🐍 is cool") 131 | default: 132 | print("not part of Pursuit") 133 | } 134 | 135 | 136 | //==================================================== 137 | // Ranges 138 | //==================================================== 139 | 140 | let ageRequirement = 18...35 // closed range includes all values 141 | // 18 is the lowerBound and 35 is the upperBound 142 | 143 | let halfRangeExample = 18..<35 // does NOT include 35 144 | 145 | let decimalRange = 18.5...23.8 146 | 147 | 148 | //==================================================== 149 | // Switch Statement on Ranges 150 | //==================================================== 151 | 152 | let classNumber = 6.3 // 2.3 from Coalition for Queens (C4Q) prior to changing to Pursuit 153 | 154 | switch classNumber { // can switch on Bool, Int, Double, Character, String 155 | case 0..<2: // half-open range, includes 0 and 1, NOT 2 156 | print("It's 2014 Coalition for Queens got founded. Now known as Pursuit, also Swift was announced that year at WWDC") 157 | case 2..<3: 158 | print("It's 2015 and Objective-C is still the leading language to write iOS apps.") 159 | case 3..<4: 160 | print("2016") 161 | case 4..<5: 162 | print("2017") 163 | case 5..<6: 164 | print("2018") 165 | case 6..<7: 166 | print("It's 2019 and SwiftUI was introduced at WWDC in San Jose") 167 | default: 168 | print("See you in 2020") 169 | } 170 | 171 | 172 | //==================================================== 173 | // Tuples 174 | //==================================================== 175 | 176 | var coordinate = (40.7429595, -73.9441102) 177 | coordinate.0 178 | coordinate.1 179 | 180 | var socials = (twitter: "@alexpaul", instagram: "@alexcpaul") 181 | socials.twitter 182 | socials.instagram 183 | 184 | 185 | //==================================================== 186 | // Switch Statement on Tuple 187 | //==================================================== 188 | 189 | let kim = (age: 19, cohort: 6.1, passion: "music") 190 | let heather = (age: 23, cohort: 6.4, passion: "immigration rights") 191 | let nancy = (age: 34, cohort: 6.3, passion: "video games") 192 | 193 | let currentFellow = nancy 194 | 195 | switch currentFellow { 196 | case(18..<21, _, _): 197 | print("not allowed to drink at events") 198 | case(_, 6.3,_): 199 | print("iOS is awesome!!!!") 200 | case(_, _, "video games"): 201 | print("see you at Pursuit's Game night, bring the drinks") 202 | default: 203 | print("not a current a fellow") 204 | } 205 | 206 | 207 | 208 | // format for automatically indentation of code 209 | // command + a, to select all code in Playground 210 | // for formatting: control + i 211 | -------------------------------------------------------------------------------- /Unit1/Control-Flow.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Dictionaries.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Dictionary: a collection of key-value pairs, 4 | // the key needs to conform the the Hashable 5 | // protocol, this simply means the key needs 6 | // to be made unique by a hashing algorithm. 7 | // Dictionaries are unordered collections. 8 | 9 | let name = "alex" 10 | let hashValue = name.hashValue 11 | print("hash value of \(name) is \(hashValue)") 12 | 13 | //================================================ 14 | // initializing and populating dictionaries 15 | //================================================ 16 | 17 | // method 1: uses the initialization method 18 | // declared and initialized an empty dictionary 19 | // key is of type Int 20 | // value is of type String 21 | var nameOfIntegers = [Int: String]() 22 | 23 | // count number of elements in nameOfIntegers 24 | // count is a property on the Collection Protocol 25 | // dictionary, arrays and sets conform to Collection 26 | // a property is a variable or constant on a type 27 | print("there are \(nameOfIntegers.count) elements currently in the nameOfIntegers dictionary") 28 | 29 | // assign a key-value (element) pair to nameOfIntegers 30 | nameOfIntegers[16] = "sixteen" 31 | 32 | print(nameOfIntegers) 33 | 34 | print("there are \(nameOfIntegers.count) elements now") 35 | 36 | // practice - add a differenct key-value pair to nameOfIntegers 37 | nameOfIntegers[7] = "seven" 38 | 39 | print(nameOfIntegers) 40 | 41 | // can we index the first element using [0] 42 | 43 | // the code below says find me the value where the key is 0 44 | let num = nameOfIntegers[0] ?? "zero" // because our key is an Int 45 | print("num is \(num)") 46 | 47 | 48 | // method 2: 49 | //var airports: [String: String] = [:] - valid, empty dictionary 50 | var airports: [String: String] // = ["Copenhagen": "CPH"] 51 | airports = ["Copenhagen": "CPH", 52 | "Los Angeles": "LAX", "Saint Luica": "LCU"] 53 | 54 | print("there are \(airports.count) airports currently") 55 | 56 | 57 | //================================================ 58 | // accessing dictionary values 59 | //================================================ 60 | 61 | // we also have an isEmpty property on dictioary 62 | if airports.isEmpty { 63 | print("airports is empty") 64 | } else { 65 | print("there are \(airports.count) airports") 66 | } 67 | 68 | //================================================ 69 | // looping through a dictionary 70 | //================================================ 71 | let bucketLists: [String: String] = ["Sweden": "Stockholm", "Austrailia": "Cairnes", "Mexico": "Cozumel", "New Zealand": "Wellington", "Morrocco": "Cassablanca"] 72 | 73 | for (country, place) in bucketLists { 74 | print("I want to visit \(place) located in \(country)") 75 | } 76 | 77 | let destination = bucketLists["New Zealand"] ?? "unknown destination" 78 | print("your next destination is \(destination)") 79 | 80 | 81 | let favoriteAlbums = ["John Mayer": "Room for Squares", "Post Mallone": "Stoney", "Tupac": "All Eyez on Me", "Drake": "Take care", "Teyana": "K.t.s.e"] 82 | 83 | // given album name, find the artist 84 | // using a for-in loop to search for a given value 85 | var artistName = "NOT FOUND" 86 | for (currentArtist, albumName) in favoriteAlbums { 87 | if albumName == "Stoney" { 88 | artistName = currentArtist 89 | } 90 | } 91 | print("\(artistName) created the Stoney album") 92 | 93 | 94 | // get values from a dictionary 95 | // extracting all the values from the favoriteAlbums dictionary 96 | let albums = Array(favoriteAlbums.values) 97 | for album in albums { 98 | print("album is \(album)") 99 | } 100 | 101 | // get keys from a dictionary 102 | let artists = Array(favoriteAlbums.keys) 103 | for artist in artists { 104 | print("artist is \(artist)") 105 | } 106 | 107 | // dictionaries are unsorted so we will demo how to 108 | // sort the values and print in a sorted manner 109 | // question: given albums, sort by artist name 110 | // sorted() by default is ascending, means a - z 111 | // descending is z - a 112 | for artistName in favoriteAlbums.keys.sorted().reversed() { 113 | print("artist name sorted is \(artistName)") 114 | } 115 | -------------------------------------------------------------------------------- /Unit1/Dictionaries.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Enums-Part-1.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // enumerations or enums: a group of related value or items 4 | // e.g days of the week, mta train lines, number of fingers, 5 | // compass points 6 | 7 | // enum keyword starts the enum definition 8 | // followed by the name of the enum, which should start with a capital letter to keep with Swift coding convention, also this signifies that the enum is a data type to the reader of your code 9 | enum CompassPoint { 10 | case north 11 | case south 12 | case east 13 | case west 14 | } 15 | 16 | // exercise: create an enum of days of the week 17 | enum DaysOfTheWeek { 18 | case monday 19 | case tuesday 20 | case wednesday 21 | case thursday 22 | case friday 23 | case saturday 24 | case sunday 25 | } 26 | 27 | enum Planet { 28 | case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune 29 | } 30 | 31 | //============================================================== 32 | // using a switch statement we will switch on an enum instance 33 | //============================================================== 34 | 35 | // instance of a String 36 | let name = "Bob" 37 | 38 | // creating an instance of the enum DayOfTheWeek 39 | let day = DaysOfTheWeek.tuesday 40 | var weekend = DaysOfTheWeek.saturday 41 | weekend = .sunday 42 | // var someDay = .friday DOES NOT COMPILE, CAN'T INFER TYPE IS ENUM 43 | 44 | switch day { 45 | case DaysOfTheWeek.monday: 46 | print("Back to Pursuit") 47 | case DaysOfTheWeek.tuesday: 48 | print("Enums lab is due") 49 | case .wednesday: 50 | print("Professional skills") 51 | case .thursday: 52 | print("Introuduction to classes") 53 | case .friday: 54 | print("Classes and Calculator labs are due") 55 | case .saturday: 56 | print("What should I do today") 57 | case .sunday: 58 | print("Maybe I should do some prep work for class tomorrow?") 59 | //default: // will never be executed as all cases are handled above 60 | // print() 61 | } 62 | 63 | //============================================================== 64 | // Iterating through an enum's cases 65 | //============================================================== 66 | 67 | // Beverages enum is conforming to the protocol CaseIterable 68 | // by conforming to CaseIterable we are able to get a count 69 | // of all the cases in an enum 70 | enum Beverage: CaseIterable { 71 | case coffee, tea, juice 72 | } 73 | 74 | print("There are \(Beverage.allCases.count) beverages") 75 | 76 | for drink in Beverage.allCases { 77 | print("current beverage is \(drink)") 78 | } 79 | -------------------------------------------------------------------------------- /Unit1/Enums-Part-1.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Enums-Part-2.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // enums part 2 4 | 5 | //==================================================== 6 | // associated values - adds more value (types) to a case 7 | //==================================================== 8 | 9 | enum MTALine { 10 | case redLine(Int) 11 | case greenLine(Int) 12 | case purpleLine 13 | case blueLine 14 | case orangeLine 15 | case brownLine 16 | case yellowLine(trainName: Character, startTime: Int, endTime: Int) 17 | case grayLine 18 | } 19 | 20 | // 1. add an associated value for greenLine of type Int use 4, 5 or 6 to create a new instance of a constant named fiveTrain 21 | // using our trainInformation() pass in the fiveTrain instance, add a new case in the switch statement for .greenLine 22 | 23 | // instantiating a train using the MTALine 24 | // 3 instances of MTALine below, namely rTrain, oneTrain and fiveTrain 25 | let rTrain = MTALine.yellowLine(trainName: "R", startTime: 8, endTime: 12) 26 | let oneTrain = MTALine.redLine(1) 27 | let fiveTrain = MTALine.greenLine(5) 28 | 29 | func trainInformation(train: MTALine) { 30 | switch train { 31 | case .greenLine(let trainName): 32 | print("You're on the \(trainName) train, maybe stop at Bowling Green and take a city walk.") 33 | case .redLine: 34 | print("The 1, 2, 3 tains are running on time.") 35 | case .yellowLine(let trainName, let sTime, let eTime): 36 | print("\(trainName) train runs from \(sTime)am to \(eTime)am") 37 | default: 38 | print("All trains are running normally.") 39 | } 40 | } 41 | trainInformation(train: rTrain) 42 | trainInformation(train: oneTrain) 43 | trainInformation(train: fiveTrain) 44 | 45 | //========================================================== 46 | // declaring methods inside enums 47 | //========================================================== 48 | 49 | enum ProgrammingLanguage { 50 | case swift 51 | case python 52 | case objectivec 53 | case go 54 | case r 55 | case java 56 | case javascript 57 | 58 | // functions in custom types are called methods 59 | func info() { 60 | // we need to switch on an instance of ProgrammingLanguage 61 | switch self { // self if the instance that calls info() 62 | case .objectivec: 63 | print("Last major update was in 2014") 64 | case .swift: 65 | print("Swift was introduced in 2014") 66 | case .java: 67 | print("Java is used to build android apps, also heavily used on Wall Street.") 68 | default: 69 | print("All languages are fun!!!!!") 70 | } 71 | } 72 | 73 | func salaryInfo() { 74 | switch self { 75 | case .swift: 76 | print("$1 million starting salary") 77 | default: 78 | print("Wasting your time") 79 | } 80 | } 81 | } 82 | 83 | // swiftLanguage is an instance of ProgammingLanguage 84 | let swiftLanguage = ProgrammingLanguage.swift 85 | swiftLanguage.info() 86 | 87 | swiftLanguage.salaryInfo() 88 | 89 | // create a ProgrmmaingLanguage instance that's not swift and call .salaryInfo() method 90 | let javaLanguage = ProgrammingLanguage.java 91 | javaLanguage.salaryInfo() 92 | 93 | 94 | //========================================================== 95 | // raw values 96 | //========================================================== 97 | 98 | enum Day: Int { 99 | case monday = 1 // default is 0 if value not supplied 100 | case tuesday 101 | case wednesday 102 | case thursday 103 | case friday 104 | case saturday 105 | case sunday 106 | } 107 | 108 | enum Fellow { 109 | case cohortCycle 110 | } 111 | 112 | // print(Fellow.cohortCycle.rawValue) DOES NOT COMPILE NO RAWVALUE PROVIDED 113 | 114 | print(Day.monday.rawValue) // default starting case of an Int rawValue is 0 115 | 116 | print(Day.tuesday.rawValue) 117 | 118 | //========================================================== 119 | // initializing an instance of an enum with a rawValue 120 | //========================================================== 121 | 122 | // nil-coalescing to unwrap optional enum rawValue type 123 | let weekend = Day(rawValue: 10) ?? Day.saturday 124 | print(weekend) 125 | 126 | // optional-binding to unwrap optional enum 127 | if let possibleDayOff = Day(rawValue: 6) { 128 | switch possibleDayOff { 129 | case .saturday: 130 | print("Great day for a BBQ") 131 | case .sunday: 132 | print("Really want to go swimming today 🏖") 133 | default: 134 | print("Just another day") 135 | } 136 | } else { 137 | print("Not a valid day of the week.") 138 | } 139 | 140 | 141 | -------------------------------------------------------------------------------- /Unit1/Enums-Part-2.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Functions-Part-1.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Functions: a block of code that enables us to call it anywhere in our project or file 4 | 5 | /* 6 | Vocabulary 7 | - function - a block of code 8 | - argument 9 | - parameters, internal, external 10 | - input 11 | - output 12 | - function definition - description of the function 13 | - calling a function or invoking a function, execute function 14 | */ 15 | 16 | //=============================================== 17 | // function syntax 18 | //=============================================== 19 | 20 | // function definition 21 | func myFirstFunction() { // no parameters 22 | print("Happy hump day 🐫") 23 | } 24 | 25 | // call or invoke or execute our myFirstFunction 26 | myFirstFunction() // no arguments 27 | 28 | // number is an external parameter name 29 | // x is an internal parameter name 30 | // Int is the data type of the function's input 31 | // Int is also the output of this function 32 | // return type syntax is -> 33 | func doubleNumber(number x: Int) -> Int { 34 | let result = x * 2 35 | return result 36 | } 37 | 38 | let resultOfCalculation = doubleNumber(number: 10) // function takes one argument of type Int, output returned is of type Int 39 | print(resultOfCalculation) 40 | 41 | 42 | // write a function that adds two a number, then triples it 43 | // input: 10 44 | // output: 36 45 | // (10 + 2) * 3 46 | 47 | func tripleNumber(num: Int) -> Int { 48 | return (num + 2) * 3 49 | } 50 | 51 | tripleNumber(num: 10) 52 | 53 | 54 | for index in 1..<4 { 55 | print(tripleNumber(num: index)) 56 | } 57 | 58 | // write a function that adds an exclaimation mark ! to a String 59 | // input: Ameni 60 | // output: Ameni! 61 | 62 | func addExclaimationMark(str: String) -> String{ 63 | let modifiedString = str + "!" 64 | return modifiedString // Tiffany += ! 65 | } 66 | 67 | let name = "Ameni" 68 | print(addExclaimationMark(str: name)) // Ameni! 69 | 70 | //=============================================== 71 | // optional types on functions 72 | //=============================================== 73 | 74 | func githubProfile(age: Int?, employmentStatus: Bool?) -> Bool? { 75 | var profileComplete: Bool? // nil 76 | if let unwrappedAge = age, 77 | let unwrappedEmploymentStatus = employmentStatus { 78 | print("\(unwrappedAge), \(unwrappedEmploymentStatus)") 79 | profileComplete = true 80 | } 81 | return profileComplete // true or nil 82 | } 83 | 84 | print(githubProfile(age: 56, employmentStatus: false)) 85 | 86 | if let profileComplete = githubProfile(age: 20, employmentStatus: true) { 87 | print("Profile complete \(profileComplete)") 88 | } else { 89 | print("Profile incomplete.") 90 | } 91 | -------------------------------------------------------------------------------- /Unit1/Functions-Part-1.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Initialization.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class Playlist { 4 | // properties 5 | var name: String 6 | var trackCount: Int 7 | var description: String 8 | var isTop100: Bool 9 | 10 | // designated initializer initializes all the properties of the class 11 | init(name: String, 12 | trackCount: Int, 13 | description: String, 14 | isTop100: Bool){ 15 | self.name = name 16 | self.trackCount = trackCount 17 | self.description = description 18 | self.isTop100 = isTop100 19 | } 20 | 21 | // convenience initializer and failable initializer 22 | convenience init?(dict: [String: Any]) { 23 | // using guard let to unwrap value from key in dictionary 24 | // also we are using optional downcasting as? to cast to expected type 25 | guard let name = dict["name"] as? String, 26 | let trackCount = dict["trackCount"] as? Int, 27 | let description = dict["description"] as? String, 28 | let isTop100 = dict["isTop100"] as? Bool else { 29 | // return exits the initializer, does not continue 30 | // through function 31 | return nil 32 | } 33 | // if all values are available in the guard statement 34 | // then we call our designated initializer 35 | self.init(name: name, 36 | trackCount: trackCount, 37 | description: description, 38 | isTop100: isTop100) 39 | } 40 | 41 | convenience init() { 42 | let names = ["Pursuit Coding list", 43 | "Zumba rocks", 44 | "Study playlist", 45 | "90's", 46 | "Morning Run" 47 | ] 48 | self.init(name: names.randomElement() ?? "Z100", 49 | trackCount: 200, 50 | description: "Awesome coding music", 51 | isTop100: false) 52 | } 53 | 54 | convenience init?(name: String) { // "th".count = 2 55 | if name.count < 3 { 56 | return nil 57 | } 58 | self.init(name: name, 59 | trackCount: 34, 60 | description: "Currently trending", 61 | isTop100: true) 62 | } 63 | 64 | // instance method 65 | func info() { 66 | print("\(name) contains \(trackCount) tracks. \(description)") 67 | if isTop100 { 68 | print("\(name) is on the top 100 Spotify list") 69 | } 70 | } 71 | } 72 | 73 | let playlistDict: [String: Any] = ["name": "Best Pop Songs 2019", 74 | "trackCount": 128, 75 | "description": "Awesome playlist", 76 | "isTop100": true 77 | ] 78 | 79 | // create a playlist instance using the playlistDict above and print the track count of the playlist 80 | // output: 128 81 | 82 | // Mr. Eric used optional binding to unwrap the playlist 83 | if let playlist = Playlist(dict: playlistDict) { 84 | print("The amount of track in this playlist is \(playlist.trackCount)") 85 | } 86 | 87 | let otherPlaylist = Playlist(dict: playlistDict) 88 | print("track count is \(otherPlaylist?.trackCount)") 89 | 90 | otherPlaylist?.info() 91 | 92 | let randomPlaylist = Playlist() 93 | print(randomPlaylist.name) 94 | 95 | let randomPlaylist2 = Playlist() 96 | print(randomPlaylist2.name) 97 | 98 | if let playlistWithName = Playlist(name: "Reggeaton 100") { 99 | print("Playlist with \(playlistWithName.name) was created.") 100 | } else { 101 | print("Playlist not created.") 102 | } 103 | 104 | -------------------------------------------------------------------------------- /Unit1/Initialization.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Loops-Part-1.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | var str = "Hello, playground" 4 | 5 | print(str) 6 | print(str) 7 | print(str) 8 | print(str) 9 | print(str) 10 | 11 | //================================================= 12 | // range - close range and half range 13 | //================================================= 14 | 15 | let closeRange = 1...10 // inclusive or close range 16 | let halfRange = 1..<10 // exclusive or half close range 17 | 18 | 19 | //========================================= 20 | // for in loop 21 | //========================================= 22 | for num in 1...10 { // inclusively prints 1 to 10 23 | // print() default terminator is "\n" 24 | // the new line character 25 | // default parameter is "\n" replace with " " 26 | if num > 9 { 27 | print(num, terminator: "") 28 | } else { 29 | print(num, terminator: "💀") 30 | } 31 | } 32 | 33 | print() 34 | 35 | 36 | //=================================================== 37 | // preview using loops with arrays 38 | //=================================================== 39 | // array of String's 40 | let pursuitStacks = ["iOS", "web", "android"] 41 | for pursuitClass in pursuitStacks { 42 | // printing using String Interpolation 43 | print("Pursuit class is \(pursuitClass)") 44 | } 45 | 46 | let fellows = ["Tiffany", "Yulia", "Joshua", "Maitree"] 47 | for fellow in fellows { 48 | if fellow == "Joshua" { 49 | print("\(fellow) is awesome!") 50 | } else { 51 | print("\(fellow) is awesome too 👏🏾") 52 | } 53 | } 54 | 55 | let temperatures = [69, 75, 87, 64, 64, 61, 68, 100] 56 | for temp in temperatures { 57 | switch temp { 58 | case 87...: // include 87 and greater 59 | print("Catch me at the beach 🏖") 60 | default: 61 | print("Just another day") 62 | } 63 | } 64 | 65 | let message = "Happy Monday iOS 6.3" 66 | // question: use a for loop to print the message variabnle 5 times 67 | for _ in 0..<5 { // ... is inclusive, ..< exclusive 68 | // fist time it is 0 69 | // next time it is 1 70 | // next time it is 2 71 | // next time it is 3 72 | // next time is is 4 73 | print(message) 74 | } 75 | 76 | 77 | //========================================= 78 | // control transfer statement 79 | // where, break, continue 80 | //========================================= 81 | // Question: use where to print ONLY numbers ending in 5 inclusively 82 | 83 | // where 84 | for number in 1...100 where number % 10 == 5 { 85 | print("\(number)'s last digit is 5") 86 | } 87 | 88 | // break - exit loop or end loop, stop looping 89 | for num in 1...10 { 90 | if num == 7 { 91 | print("Happy birthday, Miles 🎈") 92 | break // exit loop, stop seaching, stop looping 93 | } else { 94 | print("Not your birthday yet, you're only \(num) years old") 95 | } 96 | } 97 | 98 | // continue 99 | for num in 1...10 { 100 | if num % 2 == 0 { // even numbers 101 | // increment (add) 102 | // increment to next value 103 | // e.g if current value is 2 104 | // 2 mod (modulo operator - remainder) 2 or 2 % 2 is 0 s 105 | // next value is 106 | continue // to the next value 107 | } 108 | print(num) 109 | } 110 | 111 | 112 | //========================================= 113 | // while loop 114 | //========================================= 115 | var seconds = 30 116 | while seconds >= 0 { // -1 is not greater or equal to 0 117 | if seconds == 0 { 118 | print("🚀") 119 | } else { 120 | print("countdown \(seconds)....") 121 | } 122 | // while conditon NEEDS a way to stop the loop 123 | // or it will run infinetely (forever) until your 124 | // playground explodes hahahaaaa runs out of resource 125 | 126 | // without decrementing seconds the while loop 127 | // will be in what's known as an (infinite loop) 128 | seconds -= 1 // 29, 28, 27, -1 decrementing seconds by 1 129 | } 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /Unit1/Loops-Part-1.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Loops-Part-1.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Unit1/Loops-Part-1.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Unit1/Loops-Part-1.playground/playground.xcworkspace/xcuserdata/alexpaul.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexpaul/Lecture-Resources/f5f6712fb3caa0d3931a88415d023d24b2b87c5c/Unit1/Loops-Part-1.playground/playground.xcworkspace/xcuserdata/alexpaul.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Unit1/Loops-Part-2.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Loops Part 2 4 | 5 | var str = "Hello, playground" 6 | 7 | // using the str variable print "Hello, playground" five times using a for-in loop 8 | 9 | for _ in 1...5 { 10 | print(str) // 1, 2, 3, 4, 5, 6 11 | } 12 | 13 | for num in 1...5 { 14 | print(num) 15 | } 16 | 17 | var seconds = 10 18 | while seconds >= 0 { // body, scope, block or the while all refers to what's between the open curly bracket { and the close } curly bracket 19 | print(seconds) 20 | seconds -= 1 // decrements the seconds by 1 21 | } 22 | 23 | 24 | //============================================ 25 | // repeat-while loop 26 | //============================================ 27 | var isPlaying = false 28 | var currentLevel = 1 29 | let finalLevel = 10 30 | repeat { 31 | // code here 32 | if isPlaying == true { 33 | // using String interpolation to show current level 34 | print("playing level \(currentLevel)") 35 | currentLevel += 1 36 | if currentLevel == finalLevel { // only when 10 == 10 37 | print("I will definetely recommend this game.") 38 | isPlaying = false // stops the game 39 | } 40 | } else { 41 | // player is seeing our game for the first time 42 | print("Trying out Pursuit Arcade for the first time.") 43 | isPlaying = true // in a macOS command line app you can prompt the user to continue or not, this would set isPlaying to true or false 44 | } 45 | } while isPlaying == true 46 | 47 | 48 | //============================================ 49 | // nested loops 50 | //============================================ 51 | 52 | // multiplication table from 1 to 5 53 | for i in 1...5 { // n = 5 outer for loop - executes 5 times 54 | // first time it enters the for loop i is 1 55 | for j in 1...5 { // n = 5 inner for loop - executes 5 times 56 | print("\(i) * \(j) = \(i * j)") 57 | // 1 * 1 = 1 58 | // 1 * 2 = 2 59 | // 1 * 3 = 3 60 | // 1 * 4 = 4 61 | // 1 * 5 = 5 62 | 63 | // 2 * 1 = 2 64 | // 2 * 2 = 4 65 | } 66 | } 67 | 68 | 69 | //============================================ 70 | // labels in loops 71 | //============================================ 72 | let product = 50 // produce is the multiplication of two values e.g 4 * 5 = 20 73 | outerloop: for i in 1...10 { 74 | innerloop: for j in 1...10 { 75 | if i * j == product { 76 | print("product was found by multiplying \(i) * \(j)") 77 | continue outerloop 78 | } else { 79 | print("keep searching.....") 80 | } 81 | } 82 | print("done running outerloop..") 83 | } 84 | 85 | 86 | -------------------------------------------------------------------------------- /Unit1/Loops-Part-2.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Optionals-Preview.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Optional - used to indicate that a value MAY exist 4 | // two possible outcomes 5 | // outcome 1: there is a value and it can be used as normal 6 | // outcome 2: there isn't a value, in Swift terms it's nil 7 | /* 8 | String? 9 | Bool? 10 | Int? 11 | Double? 12 | Character? 13 | */ 14 | 15 | /* 16 | Ways to unwrap an Optional: 17 | 1. forced unwrapping e.g Int(response)! 18 | 2. nil-coelescing e.g Int(response) ?? 21 19 | 3. optional binding e.g if let bindingValue = optionalValue {..we can use binding value here...} else {.....} 20 | 4. implicit unwrapping e.g var name: String! 21 | */ 22 | 23 | // attemping to cast a String to an Int using this e.g Int("45") 24 | 25 | let floatValue: Float = 45.9 26 | let doubleValue = 10.3 27 | let result = Double(floatValue) + doubleValue // Double(Float Value) 28 | 29 | let response = "27" 30 | 31 | //var age = Int(response)! - 1. force unwrapping 32 | 33 | var age = Int(response) ?? 21 // 2. nil coelescing allows you to provide a default value 34 | age + 10 35 | 36 | if let yourAge = Int(response) { // 3. optional binding 37 | print("the age you entered is \(yourAge)") 38 | } else { 39 | print("the response value is nil") 40 | } 41 | 42 | 43 | -------------------------------------------------------------------------------- /Unit1/Optionals-Preview.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Optionals.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Optionals: is a type that represents two possibilities 4 | // either we have a value or we do not have a 5 | // value (nil). 6 | 7 | // Swift data types support optionals e.g 8 | /* 9 | String 10 | */ 11 | 12 | //=============================================== 13 | // Introduction of Optionals 14 | //=============================================== 15 | 16 | var name: String = "Alex" 17 | print(name) 18 | 19 | var age: Int? = 21 // optional Int? with default value of nil 20 | print(age) // nil - doesn't have a value 21 | 22 | var num = Int("It's Monday") // optional Int? 23 | 24 | 25 | //=============================================== 26 | // Ways to unwrap Optionals 27 | // 1. Forced Unwrapping using an exclaimation mark ! 28 | // or some programmers refer to it as banging ! 29 | // 2. Nil-coalescing using two question marks ?? followed 30 | // by a default value that we provide 31 | // 3. Optional binding using if let, where a value is 32 | // assigned the existing if one is available. 33 | // 4. Implicit unwrapping e.g var name: String! 34 | // 35 | //=============================================== 36 | 37 | //=============================================== 38 | // Forced Unwrapping 39 | //=============================================== 40 | 41 | let decadeFromNow = age! + 10 // Cannot add Int? + Int 42 | print(decadeFromNow) 43 | 44 | // to be used sparingly ONLY when you the developer is 45 | // GUARANTEED a value at runtime 46 | 47 | 48 | //=============================================== 49 | // Nil-Coalescing 50 | //=============================================== 51 | 52 | var temperature: Int? = 75// degrees 53 | 54 | let validTemperature = temperature ?? 67 // 67 is the default value in the case temperature is nil 55 | print("Temperature is \(validTemperature)") 56 | 57 | 58 | var cohort: Int? 59 | 60 | var nextYearCohort = (cohort ?? -1) 61 | 62 | if nextYearCohort == -1 { 63 | print("something went wrong with the application") 64 | } else { 65 | print("everything went well") 66 | } 67 | 68 | print("Pursuit next cohort will be \(nextYearCohort)") 69 | 70 | 71 | //=============================================== 72 | // Optional binding: if let, while let 73 | //=============================================== 74 | 75 | var wage: Int? = 40_000 // dollars 76 | var year: Int? // nil by default if a value is not provided 77 | 78 | // if let unwrappes the wage variable, if it does have a value then that value gets assigned to the bindedValue constant 79 | 80 | // 1. wage within the if is still optional 81 | // 2. not idiomatic swift (swifty) 82 | if wage != nil {/*.......*/} 83 | 84 | if 5 < 2 || 5 > 10 { 85 | print("in here") 86 | } else { 87 | print("out here") 88 | } 89 | // validWage is 40000 90 | // validYear is nil 91 | if let validWage = wage, 92 | let validYear = year { 93 | // we only enter the if let block {.....} 94 | // if wage is NOT nil, in other words 95 | // ONLY if wage has a value 96 | 97 | // if wage has a value the if let is TRUE 98 | // if wage is nil the if let is FALSE 99 | print("You entered \(validWage) as your wage in the current year of \(validYear)") 100 | } else { // else codition is false, or wage is nil 101 | print("Values are unavailable") 102 | } 103 | 104 | // string interpolation 105 | var modelYear: Int? 106 | print("model year is \(modelYear ?? 1959)") 107 | 108 | 109 | //=============================================== 110 | // testing optional for equality 111 | //=============================================== 112 | 113 | var someValue: Int? = 7 114 | if someValue == 7 { 115 | print("\(String(describing: someValue)) is equal to 7") 116 | } 117 | 118 | 119 | //=============================================== 120 | // looping through and optional array 121 | //=============================================== 122 | 123 | var numbers: [Int?] 124 | numbers = [4, 9, nil, 10, 20, nil] 125 | 126 | // add ONLY valid or non-nil integers 127 | var sumUnwrappedUsingOptionalBinding = 0 128 | var sumUsingNilCoalescing = 0 129 | for currentNum in numbers { 130 | // optional binding to unwrap 131 | if let validNum = currentNum { 132 | sumUnwrappedUsingOptionalBinding += validNum 133 | } 134 | 135 | // using nil-coalescing 136 | sumUsingNilCoalescing += currentNum ?? 0 137 | } 138 | print("the sum of numbers using optional binding \(sumUnwrappedUsingOptionalBinding)") 139 | print("the sum of numbers using nil-coalescing \(sumUsingNilCoalescing)") 140 | 141 | 142 | var isAbscent: Bool? = false // Bool, Int, Double, Float... 143 | if let unwrappedValue = isAbscent { 144 | print(unwrappedValue) 145 | } else { 146 | print("isAbscent does not have a value") 147 | } 148 | -------------------------------------------------------------------------------- /Unit1/Optionals.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-10-04-19.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Questions Review: October 4, 2019 4 | 5 | // String Lab 6 | // Question: Given a String use a for-in loop to reverse it. e.g input: "hello" output: "olleh" 7 | let message = "hello" 8 | var reversedString = "" 9 | 10 | let str1 = " " // whitespace character 11 | let str2 = "" 12 | 13 | if str1.isEmpty { 14 | print("str1 is empty ") 15 | } else { 16 | print("str1 is NOT empty") 17 | } 18 | 19 | if str2.isEmpty { 20 | print("str2 is empty") 21 | } 22 | 23 | for currentChar in message { 24 | // we want to loop through the given message String and add the characters we visit in reverse order to our reversedString variable 25 | 26 | //reversedString = currentChar.description + reversedString 27 | print("currentChar: \(currentChar) reversedString: \(reversedString)") 28 | 29 | reversedString = String(currentChar) + reversedString 30 | 31 | print("currentChar: \(currentChar) reversedString: \(reversedString)") 32 | 33 | print("============================") 34 | // (currentChar + reversedString) 35 | // 1. "h" + "" => reversedString = "h" 36 | // 2. "e" + "h" => reversedString ="eh" 37 | // 3. "l" + "eh" => "leh" 38 | // 4. "l" + "leh" => "lleh" 39 | // 5. "o" + "lleh" = > "olleh" 40 | } 41 | print(reversedString) 42 | 43 | 44 | 45 | // Arrays Lab 46 | /* 47 | Question: 48 | Given an array of Strings, find the String with the most a's in it. 49 | 50 | input: ["apes","abba","apple"] 51 | 52 | output: "abba" 53 | */ 54 | let arr = ["apes","abba","apple", "blh", "haah"] 55 | 56 | // how do we keep track of the String with the most "a" characters? 57 | var overallCount = 0 58 | var stringWithMostAs = "" 59 | 60 | for str in arr { 61 | // in the future we can use filter{} here 62 | 63 | // we will create a local variable to keep track of a's in current String 64 | var localCount = 0 // has local scope within the for-in loop 65 | // scope entails a variable can ONLY be accessed with its curly bracket boundaries {....} 66 | for char in str { // String.Element is the same as Character 67 | if char == "a" { // "apes" 68 | localCount += 1 69 | } 70 | } 71 | // here we will compare a's count 72 | if localCount > overallCount { // 1st time looking at apes, apes is more 73 | overallCount = localCount // override overallCount 74 | stringWithMostAs = str // override String being tracked 75 | } 76 | } 77 | print("\(stringWithMostAs) has the most a's which has a count of \(overallCount)") 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-10-04-19.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-Closures-Custom-map.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Question review from Closures lab 4 | 5 | // Question Four 6 | // Write a function called sortedNamesByLastName(in:) that takes in an array of tuples 7 | // of type (String, String) and returns an array of tuples sorted by last name. 8 | 9 | 10 | // Your function here 11 | 12 | // input of our function: unsorted last name array of tuples 13 | // output of our function: sorted by last name array of tuples 14 | 15 | func sortedNamesByLastName(in names: [(String, String)]) -> [(String, String)] { 16 | let result = names.sorted { name1, name2 in 17 | // < means ascending, or a....z 18 | // > means descending, or z....a 19 | name1.1 < name2.1 20 | } 21 | return result 22 | } 23 | 24 | // Uncomment out the following lines to check your solution 25 | let firstAndLastTuples = [ 26 | ("Johann S.", "Bach"), 27 | ("Claudio", "Monteverdi"), 28 | ("Duke", "Ellington"), 29 | ("W. A.", "Mozart"), 30 | ("Nicolai","Rimsky-Korsakov"), 31 | ("Scott","Joplin"), 32 | ("Josquin","Des Prez") 33 | ] 34 | let expectedOutputFour = [ 35 | ("Johann S.", "Bach"), 36 | ("Josquin","Des Prez"), 37 | ("Duke", "Ellington"), 38 | ("Scott","Joplin"), 39 | ("Claudio", "Monteverdi"), 40 | ("W. A.", "Mozart"), 41 | ("Nicolai","Rimsky-Korsakov") 42 | ] 43 | 44 | print(sortedNamesByLastName(in: firstAndLastTuples)) 45 | 46 | 47 | let outputFour = sortedNamesByLastName(in: firstAndLastTuples) 48 | assert(outputFour.elementsEqual(expectedOutputFour, by: { $0 == $1 }), "Expected output to be \(expectedOutputFour), but found \(outputFour)") 49 | 50 | 51 | let arr = [4, 5, 1, -7, -99, 56, 23] 52 | // return an array where elements are less than 5 53 | // output [-99, -7, 1, 4] 54 | 55 | // using sorted() which does not take any arguments 56 | print(arr.filter { $0 < 5 }.sorted()) 57 | 58 | let filteredArr = arr.filter { $0 < 5 } 59 | print(filteredArr) // [4, 1, -7, -99] 60 | 61 | let sortedArr = filteredArr.sorted 62 | 63 | // sorted using closure which takes 2 arguments 64 | let names = ["Alex", "Tiffany", "Antonio", "Genesis"] 65 | // > descending z...->a and < ascending from a....->z 66 | let sortedNamesUsingClosure = names.sorted { $0 > $1 } 67 | print(sortedNamesUsingClosure) 68 | 69 | 70 | // given an array of names return all the names uppercased 71 | // input: ["Alex", "Tiffany", "Antonio", "Genesis"] 72 | // output: ["ALEX", "TIFFANY", "ANTONIO", "GENESIS"] 73 | // use map, filter or reduce to solve exercise 74 | let sortedNamesUsingMap = names.map { $0.uppercased()} 75 | print(sortedNamesUsingMap) 76 | 77 | 78 | // re-creating the built-in map function 79 | // map function will take 2 paramters, 80 | // first parameter is an array on ints 81 | // second parameter is a closure 82 | func customMap(arr: [Int], closure: (Int) -> Int) -> [Int] { 83 | var transformedArr = [Int]() 84 | 85 | for num in arr { 86 | // perform transformation based on closure and append result in 87 | // transformedArr 88 | transformedArr.append(closure(num)) 89 | } 90 | 91 | return transformedArr 92 | } 93 | 94 | // using customMap function above take in an array of numbers and return 95 | // the squared values of each of those elements 96 | // input: [1, 2, 3, 4, 5, 6, 7] 97 | // output: [1, 4, 9, 16, 25, 36, 49] 98 | 99 | let numberArray = [1, 2, 3, 4, 5, 6, 7] 100 | let squaredNumberArray = customMap(arr: numberArray) { number in 101 | number * number 102 | } 103 | print(squaredNumberArray) 104 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-Closures-Custom-map.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-Enums.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Questions review: enums 4 | 5 | // Question Three 6 | // You are given a Coin enumeration which describes different coin values. 7 | // Write a function called getTotalValue(from:) that takes in an array 8 | // of tuples of type (number: Int, coin: Coin), and returns the total value of all coins in cents. 9 | enum Coin: Int { 10 | case penny = 1 11 | case nickle = 5 12 | case dime = 10 13 | case quarter = 25 14 | } 15 | 16 | // Your function here 17 | 18 | func getTotalValue(from tuples: [(numberOfCoins: Int, typeOfCoin: Coin)]) -> Int { 19 | var totalNumberOfCents = 0 20 | for tuple in tuples { 21 | switch tuple.typeOfCoin { 22 | case .penny: 23 | totalNumberOfCents += Coin.penny.rawValue * tuple.numberOfCoins 24 | case .nickle: 25 | totalNumberOfCents += Coin.nickle.rawValue * tuple.numberOfCoins 26 | case .dime: 27 | totalNumberOfCents += Coin.dime.rawValue * tuple.numberOfCoins 28 | case .quarter: 29 | totalNumberOfCents += Coin.quarter.rawValue * tuple.numberOfCoins 30 | } 31 | } 32 | return totalNumberOfCents 33 | } 34 | 35 | // Uncomment the lines below to test your solution 36 | let coinArr: [(Int, Coin)] = [ 37 | (10, .penny), 38 | (15, .nickle), 39 | (3, .quarter), 40 | (20, .penny), 41 | (3, .dime), 42 | (7, .quarter) 43 | ] 44 | let expectedTotal = 385 45 | let total = getTotalValue(from: coinArr) 46 | assert(total == expectedTotal, "Was expecting \(expectedTotal), but got \(total)") 47 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-Enums.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-Optionals-Dictionaries.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Questions Review: Optionals and Dictionaries 4 | // Optionals 5 | /* 6 | Question 6 7 | a. Given the variable numbers below, write code that prints "The sum of all the numbers is " 8 | followed by their sum. If a number is nil, don't add it to the sum. If all numbers are nil, 9 | the sum is zero. 10 | var numbers = [Int?]() 11 | for _ in 0..<10 { 12 | numbers.append(Bool.random() ? Int.random(in: 0...100) : nil) 13 | } 14 | b. Using the same variable, find the average of all non-nil values. 15 | */ 16 | 17 | var messages: [String] = ["Good, Morning"] 18 | for _ in 0..<10 { 19 | messages.append("Hello, Yulia") // append() - adds to array 20 | } 21 | print(messages.count) 22 | 23 | 24 | // a - add only non-nil values 25 | var numbers = [Int?]() 26 | for _ in 0..<10 { 27 | numbers.append(Bool.random() ? Int.random(in: 0...100) : nil) 28 | } 29 | 30 | var sum = 0 31 | for num in numbers { 32 | sum += num ?? 0 // nil-coalescing to unwrap num 33 | } 34 | print("The sum of all the numbers is \(sum)") 35 | 36 | 37 | // b - average of non-nil values 38 | sum = 0 // clearing sum 39 | var nonNilValueCount = 0 40 | for num in numbers { 41 | // use optional binding to unwrap num 42 | if let unwrappedNum = num { 43 | // valid integer here, increment nonNilValueCount by 1 44 | nonNilValueCount += 1 45 | sum += unwrappedNum 46 | } 47 | } 48 | print(numbers) 49 | print("The average of the \(nonNilValueCount) non-nil values is \(sum / nonNilValueCount)") 50 | 51 | 52 | // Dictionaries 53 | // Question Four 54 | // You are given an array of dictionaries. Each dictionary in the array describes the score of a person. Find the person with the highest score and print his / her full name. 55 | 56 | var peopleWithScores: [[String: String]] = [ 57 | [ 58 | "firstName": "Calvin", 59 | "lastName": "Newton", 60 | "score": "13" 61 | ], 62 | [ 63 | "firstName": "Garry", 64 | "lastName": "Mckenzie", 65 | "score": "23" 66 | ], 67 | [ 68 | "firstName": "Leah", 69 | "lastName": "Rivera", 70 | "score": "10" 71 | ], 72 | [ 73 | "firstName": "Sonja", 74 | "lastName": "Moreno", 75 | "score": "3" 76 | ], 77 | [ 78 | "firstName": "Noel", 79 | "lastName": "Bowen", 80 | "score": "16" 81 | ] 82 | ] 83 | 84 | var highestScore = 0 85 | var fullName = "" 86 | for currentPersonDictionary in peopleWithScores { 87 | print("currently looking at \(currentPersonDictionary["firstName"] ?? "")") 88 | let scoreAsString = currentPersonDictionary["score"] ?? "0" 89 | let scoreAsInt = Int(scoreAsString) ?? 0 90 | if scoreAsInt > highestScore { // e.g 13 > 0 91 | highestScore = scoreAsInt // e.g 13 92 | let firstName = currentPersonDictionary["firstName"] ?? "Jane" 93 | let lastName = currentPersonDictionary["lastName"] ?? "Doe" 94 | fullName = firstName + " " + lastName 95 | } 96 | print("\n") 97 | } 98 | print("\(fullName) has the highest score of \(highestScore)") 99 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-Optionals-Dictionaries.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-Sets.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | 4 | // Questions Review: Sets 5 | 6 | // Questions Two 7 | // Create a new array scoresThatAppearOnce that has all the elements from scores that appear exactly once. 8 | // It should be in the same order as the original. 9 | let scores = [1, 77, 83, 32, 77, 77, 83, 32, 99] 10 | 11 | var scoresThatAppearOnce = [Int]() 12 | 13 | // Your code here 14 | 15 | var visitedScores: Set = [] 16 | for (_, score) in scores.enumerated() { 17 | if !visitedScores.contains(score) { // haven't seen this score 18 | visitedScores.insert(score) 19 | scoresThatAppearOnce.append(score) 20 | } else { // visited this value before, so it's not unique 21 | if let foundIndex = scoresThatAppearOnce.firstIndex(of: score) { 22 | scoresThatAppearOnce.remove(at: foundIndex) 23 | } 24 | } 25 | } 26 | 27 | // runtime efficiency of the algorithm 28 | // contains on a Set in constant time O(1) 29 | // contains on an Array is linear time O(n) 30 | 31 | assert(scoresThatAppearOnce == [1, 99], "Was expecting [1, 99], but got \(scoresThatAppearOnce)") 32 | 33 | 34 | 35 | // Question Five 36 | // Determine if a String is a pangram. A pangram is a string that contains every letter of 37 | // the alphabet at least once. 38 | // e.g "The quick brown fox jumps over the lazy dog" is a pangram 39 | // e.g "The quick brown fox jumped over the lazy dog" is NOT a pangram 40 | let strOne = "The quick brown fox jumps over the lazy dog" 41 | let strTwo = "The quick brown fox jumped over the lazy dog" 42 | let strThree = "Sphinx of black quartz, judge my vow" 43 | 44 | var strOneIsPangram: Bool = false 45 | var strTwoIsPangram: Bool = false 46 | var strThreeIsPangram: Bool = false 47 | 48 | // Your code here 49 | 50 | let alphabets: Set = Set("abcdefghijklmnopqrstuvwxyz") 51 | 52 | var trimmedStr = "" 53 | for char in strOne.lowercased() { 54 | if alphabets.contains(char) { 55 | trimmedStr += String(char) 56 | } 57 | } 58 | 59 | strOneIsPangram = Set(trimmedStr) == alphabets 60 | 61 | assert(strOneIsPangram == true, "Was expecting true, but got \(strOneIsPangram)") 62 | //assert(strTwoIsPangram == false, "Was expecting false, but got \(strTwoIsPangram)") 63 | //assert(strThreeIsPangram == true, "Was expecting true, but got \(strThreeIsPangram)") 64 | -------------------------------------------------------------------------------- /Unit1/Questions-Review-Sets.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/README.md: -------------------------------------------------------------------------------- 1 | ## Unit 1 - Swift Langugage Fundamentals 2 | 3 | #### In-class Xcode Playgrounds and Projects 4 | 5 | 1. [Types, Variables and Logic](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Types-Variables.playground/Contents.swift) 6 | 1. [Control Flow](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Control-Flow.playground/Contents.swift) 7 | 1. [Loops, Part 1](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Loops-Part-1.playground/Contents.swift) 8 | 1. [Loops, Part 2](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Loops-Part-2.playground/Contents.swift) 9 | 1. [Strings, Part 1](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Strings-Part-1.playground/Contents.swift) 10 | 1. [Strings, Part 2](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Strings-Part-2.playground/Contents.swift) 11 | 1. [Arrays, Part 1](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Arrays-Part-1.playground/Contents.swift) 12 | 1. [Arrays, Part 2](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Arrays-Part-2.playground/Contents.swift) 13 | 1. [Optionals](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Optionals.playground/Contents.swift) 14 | 1. [Dictionaries](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Dictionaries.playground/Contents.swift) 15 | 1. [Sets](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Sets.playground/Contents.swift) 16 | 1. [Functions, Part 1](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Functions-Part-1.playground/Contents.swift) 17 | 1. [Closures, Part 1](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Closures-Part-1.playground/Contents.swift) 18 | 1. [Enumerations (Enums), Part 1](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Enums-Part-1.playground/Contents.swift) 19 | 1. [Enumerations (Enums), Part 2](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Enums-Part-2.playground/Contents.swift) 20 | 1. [Structs](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Structs.playground/Contents.swift) 21 | 1. [Classes](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Classes.playground/Contents.swift) 22 | 1. [Structs and Classes Wrapup](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Structs-and-Classes-Wrapup.playground/Contents.swift) 23 | 1. [Initialization](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Initialization.playground/Contents.swift) 24 | 1. [Encapsulation](https://gist.github.com/alexpaul/ab4c53b36c1ccfc068a32c45fefbc4a6) 25 | 26 | 27 | #### In-class Project Demo 28 | 29 | 1. [readline() demo](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/ReadLineDemo/ReadLineDemo/main.swift) 30 | 1. [TriviaGame](https://github.com/alexpaul/Pursuit-Core-iOS/tree/master/Unit1/TriviaGame/TriviaGame) 31 | 32 | 33 | #### Questions Review Playgrounds and Projects 34 | 35 | 1. [Reverse a String, Find the String with the most a's in an Array](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Questions-Review-10-04-19.playground/Contents.swift) 36 | 1. [Optionals and Dictionary](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Questions-Review-Optionals-Dictionaries.playground/Contents.swift) 37 | 1. [Sets](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Questions-Review-Sets.playground/Contents.swift) 38 | 1. [Dictionary and Closures](https://gist.github.com/alexpaul/5403e38feb13e954cb1b58856fda73e5) 39 | 1. [Closures and Implementing a custom map function](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Questions-Review-Closures-Custom-map.playground/Contents.swift) 40 | 1. [Enums](https://github.com/alexpaul/Pursuit-Core-iOS/blob/master/Unit1/Questions-Review-Enums.playground/Contents.swift) 41 | 42 | 43 | #### Lecture Videos 44 | 45 | 1. [Pushing a Local Repository to Github](https://www.youtube.com/watch?v=UBIULfmEynA&list=PLjdVqs-1R8wG5UCYQzbvAYP0wCEUySPey&index=6&t=4s) 46 | 1. [Types, Variables and Logic](https://www.youtube.com/watch?v=svm8SU1AuFA&list=PLjdVqs-1R8wG5UCYQzbvAYP0wCEUySPey&index=5&t=8s) 47 | 1. [Control flow](https://www.youtube.com/watch?v=zXozLu5jhqE&list=PLjdVqs-1R8wG5UCYQzbvAYP0wCEUySPey&index=4&t=3s) 48 | 1. [Introduction to Optionals](https://www.youtube.com/watch?v=ahviHGF3260&list=PLjdVqs-1R8wG5UCYQzbvAYP0wCEUySPey&index=3&t=6s) 49 | 1. [Loops, Part 1](https://www.youtube.com/watch?v=v79dGoMFmrM&t=1277s) 50 | 1. [Loops, Part 2](https://www.youtube.com/watch?v=kJQJiNpP5Jk&t=663s) 51 | 1. [Strings, Part 1](https://www.youtube.com/watch?v=0ov2jpoIRYw&t=4s) 52 | 1. [Strings, Part 2](https://youtu.be/JKUJ8Ns67s4) 53 | 1. [Arrays, Part 1](https://youtu.be/8EEEruma-lg) 54 | 1. [Arrays, Part 2](https://www.youtube.com/watch?v=SAt0d3Zqqyg&t=40s) 55 | 1. [Optionals](https://www.youtube.com/watch?v=AHegXlW7Lg4&list=PLjdVqs-1R8wG5UCYQzbvAYP0wCEUySPey&index=1) 56 | 1. [Dictionaries](https://www.youtube.com/watch?v=MZVckABm8dI&list=PLjdVqs-1R8wG5UCYQzbvAYP0wCEUySPey&index=2) 57 | 1. [Sets](https://youtu.be/dJWw4jdyd2I) 58 | 1. [Functions, Part 1](https://www.youtube.com/watch?v=bSEw2efBMvU&t=160s) 59 | 1. [Closures, Part 1](https://youtu.be/em5lUr4gh6c) 60 | 1. [Enumerations (Enums), Part 1](https://youtu.be/mo5EogdY1kw) 61 | 1. [Enumerations (Enums), Part 2](https://youtu.be/Wn3o3EdIs0E) 62 | 1. [Structs](https://youtu.be/TJUHqNw7fi4) 63 | 1. [Classes](https://youtu.be/fePinLSpJ_8) 64 | 1. [Structs and Classes Wrap up](https://youtu.be/rmyJy77kBOE) 65 | 1. [Initialization](https://youtu.be/H9_HKtk3i6Q) 66 | 67 | 68 | #### Questions Review Videos 69 | 70 | 1. [Reverse a String, Find the String with the most a's in an Array](https://www.youtube.com/watch?v=KVuEyVMcAx4&t=104s) 71 | 1. [Optionals and Dictionary](https://youtu.be/E3l3w62fXf8) 72 | 1. [Sets](https://www.youtube.com/watch?v=c9D4dxp117k&t=3s) 73 | 1. [Solving algorithms and Pair programming](https://youtu.be/FpDznrg5ZcI) 74 | 1. [Dictionary and Closures](https://youtu.be/OBPWLLiPcZ0) 75 | 1. [Closures and implementing custom map](https://youtu.be/tvxw1kC3750) 76 | 1. [Enums](https://youtu.be/tiDCGx3nm-U) 77 | 78 | 79 | #### Project Demo Videos 80 | 81 | 1. [Using readline() and macOS Command Line Tool to create a Text Adventure app](https://www.youtube.com/watch?v=QXyiVYO56_w&list=PLjdVqs-1R8wG5UCYQzbvAYP0wCEUySPey&index=2&t=2893s) 82 | 1. [TriviaGame, Part 1](https://youtu.be/5QGVZFkQtY0) 83 | 1. [TriviaGame, Part 2](https://youtu.be/JaQRfmf7RF4) 84 | 1. [TriviaGame, Part 3](https://youtu.be/J-tvDMz5ZiM) 85 | 1. [TriviaGame, Part 4](https://youtu.be/SePUzHKbqrw) 86 | 87 | 88 | #### Lab Assignment Overview Videos 89 | 90 | 1. [Hangman Commmand-line macOS application](https://www.youtube.com/watch?v=8fIK_q6EGcY) 91 | 1. [Calculator Command-line macOS application](https://youtu.be/Ozy8WHpRLoE) 92 | 93 | #### Swift Lightning Round Videos 94 | 95 | 1. [Using CharacterSet - CharacterSet is great when you are looking for a particular set of characters](https://youtu.be/x_yzKLPa2L0) 96 | 1. [Creating the alphabets using UnicodeScaler and Range](https://www.youtube.com/watch?v=_uPqpa969Ds&t=94s) 97 | 1. [Unwrapping optionals using guard in functions](https://www.youtube.com/watch?v=8AzVFhsNIvQ&t=41s) 98 | 99 | -------------------------------------------------------------------------------- /Unit1/ReadLineDemo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexpaul/Lecture-Resources/f5f6712fb3caa0d3931a88415d023d24b2b87c5c/Unit1/ReadLineDemo/.DS_Store -------------------------------------------------------------------------------- /Unit1/ReadLineDemo/ReadLineDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 573DB13A233EAA4E00AEE72E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 573DB139233EAA4E00AEE72E /* main.swift */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 573DB134233EAA4E00AEE72E /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 573DB136233EAA4E00AEE72E /* ReadLineDemo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ReadLineDemo; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 573DB139233EAA4E00AEE72E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 573DB133233EAA4E00AEE72E /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 573DB12D233EAA4E00AEE72E = { 42 | isa = PBXGroup; 43 | children = ( 44 | 573DB138233EAA4E00AEE72E /* ReadLineDemo */, 45 | 573DB137233EAA4E00AEE72E /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 573DB137233EAA4E00AEE72E /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 573DB136233EAA4E00AEE72E /* ReadLineDemo */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 573DB138233EAA4E00AEE72E /* ReadLineDemo */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 573DB139233EAA4E00AEE72E /* main.swift */, 61 | ); 62 | path = ReadLineDemo; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 573DB135233EAA4E00AEE72E /* ReadLineDemo */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 573DB13D233EAA4E00AEE72E /* Build configuration list for PBXNativeTarget "ReadLineDemo" */; 71 | buildPhases = ( 72 | 573DB132233EAA4E00AEE72E /* Sources */, 73 | 573DB133233EAA4E00AEE72E /* Frameworks */, 74 | 573DB134233EAA4E00AEE72E /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = ReadLineDemo; 81 | productName = ReadLineDemo; 82 | productReference = 573DB136233EAA4E00AEE72E /* ReadLineDemo */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 573DB12E233EAA4E00AEE72E /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastSwiftUpdateCheck = 1100; 92 | LastUpgradeCheck = 1100; 93 | ORGANIZATIONNAME = "Alex Paul"; 94 | TargetAttributes = { 95 | 573DB135233EAA4E00AEE72E = { 96 | CreatedOnToolsVersion = 11.0; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = 573DB131233EAA4E00AEE72E /* Build configuration list for PBXProject "ReadLineDemo" */; 101 | compatibilityVersion = "Xcode 9.3"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | Base, 107 | ); 108 | mainGroup = 573DB12D233EAA4E00AEE72E; 109 | productRefGroup = 573DB137233EAA4E00AEE72E /* Products */; 110 | projectDirPath = ""; 111 | projectRoot = ""; 112 | targets = ( 113 | 573DB135233EAA4E00AEE72E /* ReadLineDemo */, 114 | ); 115 | }; 116 | /* End PBXProject section */ 117 | 118 | /* Begin PBXSourcesBuildPhase section */ 119 | 573DB132233EAA4E00AEE72E /* Sources */ = { 120 | isa = PBXSourcesBuildPhase; 121 | buildActionMask = 2147483647; 122 | files = ( 123 | 573DB13A233EAA4E00AEE72E /* main.swift in Sources */, 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXSourcesBuildPhase section */ 128 | 129 | /* Begin XCBuildConfiguration section */ 130 | 573DB13B233EAA4E00AEE72E /* Debug */ = { 131 | isa = XCBuildConfiguration; 132 | buildSettings = { 133 | ALWAYS_SEARCH_USER_PATHS = NO; 134 | CLANG_ANALYZER_NONNULL = YES; 135 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 136 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 137 | CLANG_CXX_LIBRARY = "libc++"; 138 | CLANG_ENABLE_MODULES = YES; 139 | CLANG_ENABLE_OBJC_ARC = YES; 140 | CLANG_ENABLE_OBJC_WEAK = YES; 141 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 142 | CLANG_WARN_BOOL_CONVERSION = YES; 143 | CLANG_WARN_COMMA = YES; 144 | CLANG_WARN_CONSTANT_CONVERSION = YES; 145 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 146 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 147 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 148 | CLANG_WARN_EMPTY_BODY = YES; 149 | CLANG_WARN_ENUM_CONVERSION = YES; 150 | CLANG_WARN_INFINITE_RECURSION = YES; 151 | CLANG_WARN_INT_CONVERSION = YES; 152 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 154 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 155 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 156 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 157 | CLANG_WARN_STRICT_PROTOTYPES = YES; 158 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 159 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 160 | CLANG_WARN_UNREACHABLE_CODE = YES; 161 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 162 | COPY_PHASE_STRIP = NO; 163 | DEBUG_INFORMATION_FORMAT = dwarf; 164 | ENABLE_STRICT_OBJC_MSGSEND = YES; 165 | ENABLE_TESTABILITY = YES; 166 | GCC_C_LANGUAGE_STANDARD = gnu11; 167 | GCC_DYNAMIC_NO_PIC = NO; 168 | GCC_NO_COMMON_BLOCKS = YES; 169 | GCC_OPTIMIZATION_LEVEL = 0; 170 | GCC_PREPROCESSOR_DEFINITIONS = ( 171 | "DEBUG=1", 172 | "$(inherited)", 173 | ); 174 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 175 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 176 | GCC_WARN_UNDECLARED_SELECTOR = YES; 177 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 178 | GCC_WARN_UNUSED_FUNCTION = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | MACOSX_DEPLOYMENT_TARGET = 10.15; 181 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 182 | MTL_FAST_MATH = YES; 183 | ONLY_ACTIVE_ARCH = YES; 184 | SDKROOT = macosx; 185 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 186 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 187 | }; 188 | name = Debug; 189 | }; 190 | 573DB13C233EAA4E00AEE72E /* Release */ = { 191 | isa = XCBuildConfiguration; 192 | buildSettings = { 193 | ALWAYS_SEARCH_USER_PATHS = NO; 194 | CLANG_ANALYZER_NONNULL = YES; 195 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 196 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 197 | CLANG_CXX_LIBRARY = "libc++"; 198 | CLANG_ENABLE_MODULES = YES; 199 | CLANG_ENABLE_OBJC_ARC = YES; 200 | CLANG_ENABLE_OBJC_WEAK = YES; 201 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 202 | CLANG_WARN_BOOL_CONVERSION = YES; 203 | CLANG_WARN_COMMA = YES; 204 | CLANG_WARN_CONSTANT_CONVERSION = YES; 205 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 206 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 207 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 208 | CLANG_WARN_EMPTY_BODY = YES; 209 | CLANG_WARN_ENUM_CONVERSION = YES; 210 | CLANG_WARN_INFINITE_RECURSION = YES; 211 | CLANG_WARN_INT_CONVERSION = YES; 212 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 213 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 214 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 215 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 216 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 217 | CLANG_WARN_STRICT_PROTOTYPES = YES; 218 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 219 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 220 | CLANG_WARN_UNREACHABLE_CODE = YES; 221 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 222 | COPY_PHASE_STRIP = NO; 223 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 224 | ENABLE_NS_ASSERTIONS = NO; 225 | ENABLE_STRICT_OBJC_MSGSEND = YES; 226 | GCC_C_LANGUAGE_STANDARD = gnu11; 227 | GCC_NO_COMMON_BLOCKS = YES; 228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 230 | GCC_WARN_UNDECLARED_SELECTOR = YES; 231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 232 | GCC_WARN_UNUSED_FUNCTION = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | MACOSX_DEPLOYMENT_TARGET = 10.15; 235 | MTL_ENABLE_DEBUG_INFO = NO; 236 | MTL_FAST_MATH = YES; 237 | SDKROOT = macosx; 238 | SWIFT_COMPILATION_MODE = wholemodule; 239 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 240 | }; 241 | name = Release; 242 | }; 243 | 573DB13E233EAA4E00AEE72E /* Debug */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | CODE_SIGN_STYLE = Automatic; 247 | DEVELOPMENT_TEAM = ZEKMNK5YD3; 248 | ENABLE_HARDENED_RUNTIME = YES; 249 | PRODUCT_NAME = "$(TARGET_NAME)"; 250 | SWIFT_VERSION = 5.0; 251 | }; 252 | name = Debug; 253 | }; 254 | 573DB13F233EAA4E00AEE72E /* Release */ = { 255 | isa = XCBuildConfiguration; 256 | buildSettings = { 257 | CODE_SIGN_STYLE = Automatic; 258 | DEVELOPMENT_TEAM = ZEKMNK5YD3; 259 | ENABLE_HARDENED_RUNTIME = YES; 260 | PRODUCT_NAME = "$(TARGET_NAME)"; 261 | SWIFT_VERSION = 5.0; 262 | }; 263 | name = Release; 264 | }; 265 | /* End XCBuildConfiguration section */ 266 | 267 | /* Begin XCConfigurationList section */ 268 | 573DB131233EAA4E00AEE72E /* Build configuration list for PBXProject "ReadLineDemo" */ = { 269 | isa = XCConfigurationList; 270 | buildConfigurations = ( 271 | 573DB13B233EAA4E00AEE72E /* Debug */, 272 | 573DB13C233EAA4E00AEE72E /* Release */, 273 | ); 274 | defaultConfigurationIsVisible = 0; 275 | defaultConfigurationName = Release; 276 | }; 277 | 573DB13D233EAA4E00AEE72E /* Build configuration list for PBXNativeTarget "ReadLineDemo" */ = { 278 | isa = XCConfigurationList; 279 | buildConfigurations = ( 280 | 573DB13E233EAA4E00AEE72E /* Debug */, 281 | 573DB13F233EAA4E00AEE72E /* Release */, 282 | ); 283 | defaultConfigurationIsVisible = 0; 284 | defaultConfigurationName = Release; 285 | }; 286 | /* End XCConfigurationList section */ 287 | }; 288 | rootObject = 573DB12E233EAA4E00AEE72E /* Project object */; 289 | } 290 | -------------------------------------------------------------------------------- /Unit1/ReadLineDemo/ReadLineDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Unit1/ReadLineDemo/ReadLineDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Unit1/ReadLineDemo/ReadLineDemo.xcodeproj/project.xcworkspace/xcuserdata/alexpaul.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexpaul/Lecture-Resources/f5f6712fb3caa0d3931a88415d023d24b2b87c5c/Unit1/ReadLineDemo/ReadLineDemo.xcodeproj/project.xcworkspace/xcuserdata/alexpaul.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Unit1/ReadLineDemo/ReadLineDemo.xcodeproj/xcuserdata/alexpaul.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ReadLineDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Unit1/ReadLineDemo/ReadLineDemo/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // ReadLineDemo 4 | // 5 | // Created by Alex Paul on 9/27/19. 6 | // Copyright © 2019 Alex Paul. All rights reserved. 7 | // 8 | 9 | 10 | import Foundation 11 | 12 | // Objective: 13 | // Use ReadLine() to get input from the user 14 | 15 | print("Enter how many days you will swim, bike or run this week?") 16 | var numberOfDays = Int(readLine() ?? "") ?? -1 17 | 18 | var workoutCount = numberOfDays 19 | print() // creates a new line 20 | 21 | /* 22 | repeat { 23 | // execute code 24 | } while (condition is true) 25 | */ 26 | 27 | repeat { // repeat-while loop 28 | if numberOfDays == 0 { 29 | break // exits the loop 30 | } else if numberOfDays == -1 { 31 | break 32 | } 33 | 34 | if numberOfDays < 0 || numberOfDays > 7 { 35 | numberOfDays = -2 36 | workoutCount = numberOfDays 37 | break 38 | } 39 | 40 | print("enter the type of workout, swim, bike or run: ") 41 | let workout = readLine()?.lowercased() 42 | print() // creates a new line 43 | 44 | switch workout { 45 | case "swim": 46 | print("swim \(Int.random(in: 1...100)) lengths of the pool") 47 | case "bike": 48 | print("bike \(Int.random(in: 1...100)) loops around Central Park") 49 | case "run": 50 | print("run \(Int.random(in: 1...100)) laps around the track") 51 | default: 52 | print("no such workout") 53 | } 54 | 55 | numberOfDays -= 1 // decrementing e.g 5 days, 4...3...2...1...0 => while loop condition is met 56 | print() // creates space betwen lines 57 | } while numberOfDays > 0 58 | 59 | switch workoutCount { 60 | case -2: 61 | print("invalid number of days entered") 62 | case -1: 63 | print("bad data was entered") 64 | case 1..<5: 65 | print("Good job this week") 66 | case 5...: 67 | print("YOU'RE A ROCKSTAR 🏊🏾‍♂️ 🚵🏾‍♂️ 🏃🏾‍♂️ 🔥🔥🔥🔥🔥🔥🔥🔥🔥") 68 | default: 69 | print("Slacker you can do better......") 70 | } 71 | 72 | // command + b => only builds and checks for errors 73 | // command + r => builds and runs the application 74 | -------------------------------------------------------------------------------- /Unit1/Sets.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Sets: an unordered collection whose elements are unique 4 | 5 | //==================================================== 6 | // initializing and populating a set 7 | //==================================================== 8 | 9 | // protocols: Hashable, Sequence, Collection 10 | 11 | var accountNumbers: Set = [] // use type annotation 12 | var accountNumbers2 = Set() // use set initialization 13 | 14 | var accountNumbers3: Set = [37198473, 94275942789, 95727589278] // using a literal collection 15 | 16 | // heterogeneous array 17 | var mixedArr: [Any] = [45253, "Tiff", false] 18 | for element in mixedArr { 19 | if let num = element as? Int { // typecasting - optional downcasting as?, forced downcasting as! 20 | print("num is \(num)") 21 | } 22 | if let str = element as? String { 23 | print("string is \(str)") 24 | } 25 | if let bool = element as? Bool { 26 | print("bool value is \(bool)") 27 | } 28 | } 29 | 30 | 31 | //==================================================== 32 | // accessing values in a set 33 | //==================================================== 34 | 35 | // isEmpty 36 | if accountNumbers.isEmpty { 37 | print("accountNumbers is empty") 38 | } 39 | 40 | // count 41 | print("There are \(accountNumbers3.count) elements in accountNumbers3") 42 | 43 | // converting array to a set 44 | // removes any duplicates from the array since elements in a set has to be unique 45 | let colors = Set(["blue", "white", "red", "yellow", "white"]) 46 | print(colors) 47 | 48 | 49 | //==================================================== 50 | // using contains to find an element in a set 51 | //==================================================== 52 | 53 | var fellows: Set = ["Christian", "Gregg", "Maitree", "Joshua"] 54 | 55 | for fellow in fellows { 56 | print(fellow) 57 | } 58 | 59 | if fellows.contains("Christian") { 60 | print("found fellow") 61 | } 62 | 63 | 64 | //==================================================== 65 | // removing and inserting in a set 66 | //==================================================== 67 | 68 | let inserted = fellows.insert("Nancy") 69 | // returns a tuple indicating value insert status 70 | // (inserted: true, memberAfterInsert: "Nancy") 71 | 72 | print(inserted) 73 | fellows.insert("Paul") 74 | 75 | print(fellows) 76 | // ["Christian", "Joshua", "Gregg", "Nancy", "Maitree", "Paul"] 77 | 78 | fellows.remove("Paul") 79 | print(fellows) 80 | // ["Joshua", "Nancy", "Christian", "Gregg", "Maitree"] 81 | 82 | 83 | //==================================================== 84 | // performing set operations 85 | //==================================================== 86 | 87 | let a: Set = [1, 2, 3, 4, 5, 6] 88 | let b: Set = [5, 6, 7, 8] 89 | 90 | // intersection 91 | let intersection = a.intersection(b).sorted() // ascending is the default order of sorted() 92 | print(intersection) // [5,6] 93 | 94 | // symmetricDifference 95 | let symmetricDifference = a.symmetricDifference(b).sorted() 96 | print(symmetricDifference) // [1, 2, 3, 4, 7, 8] 97 | 98 | // union 99 | let union = a.union(b).sorted() 100 | print(union) // [1, 2, 3, 4, 5, 6, 7, 8] 101 | 102 | // subtracting 103 | let subtracting = a.subtracting(b).sorted() 104 | print(subtracting) 105 | 106 | 107 | let houseAnimals: Set = ["🐶", "🐱"] 108 | let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"] 109 | let cityAnimals: Set = ["🐦", "🐭"] 110 | 111 | houseAnimals.isSubset(of: farmAnimals) 112 | // true 113 | farmAnimals.isSuperset(of: houseAnimals) 114 | // true 115 | farmAnimals.isDisjoint(with: cityAnimals) 116 | // true 117 | -------------------------------------------------------------------------------- /Unit1/Sets.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Strings-Part-1.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // String - a collection of unicode compliant characters 4 | 5 | /* 6 | Vocabulary 7 | - unicode 8 | - character 9 | - literal String e.g "hello" 10 | */ 11 | 12 | // declaring and initializing a literal String 13 | var message = "Good morning iOS 6.3" 14 | 15 | // iterate or loops over a String using a for-in loop 16 | for char in message { 17 | print("character is \(char)") 18 | } 19 | 20 | // length of String using the count property 21 | print("message count is \(message.count)") 22 | 23 | "melinda".count 24 | 25 | // ============================================ 26 | // unicode 27 | // e.g a space in unicode U+0020 28 | // ============================================ 29 | 30 | // a character is made up or one or more unicode scalars 31 | // e.g of unicode scaler \u{301} `e 32 | 33 | // combining unicode scalars 34 | let name = "al\u{0065}\u{301}x" 35 | 36 | let bagel = "\u{1F96F}" 37 | 38 | 39 | // comparing unicode scalar with character 40 | let unicodeLowercaseE = "\u{0065}" 41 | let eCharacter = "e" 42 | if unicodeLowercaseE == eCharacter { 43 | print("they are equal") 44 | } 45 | 46 | // accessing and modifying String 47 | let programmingLanguage = "Swift" 48 | 49 | let fellows = ["Kelby", "Stephanie"] 50 | 51 | fellows.count // 2 52 | 53 | let firstFellow = fellows[0] 54 | 55 | // access the first character in "Swift" => "S" 56 | // programmingLanguage[0] - DOES NOT COMPILE 57 | 58 | // firstIndex is of type String.Index 59 | let firstIndex = programmingLanguage.startIndex 60 | 61 | // only way to subscript [] into a String is using a String.Index value 62 | let firstCharacter = programmingLanguage[firstIndex] 63 | print("first character in \(programmingLanguage) is \(firstCharacter)") 64 | 65 | let endIndex = programmingLanguage.endIndex 66 | let lastCharacterIndex = programmingLanguage.index(before: endIndex) 67 | let lastCharacter = programmingLanguage[lastCharacterIndex] 68 | print("last character in \(programmingLanguage) is", lastCharacter) 69 | 70 | 71 | // ============================================ 72 | // making a range using indices 73 | // ============================================ 74 | 75 | let alphabets = "abcdefghijklmnopqrstuvwxyz" 76 | 77 | // using a for loop print out the first 6 characters in the alphabet 78 | var counter = 0 79 | for char in alphabets { // 0, 1, 2, 3, 4, 5 80 | if counter < 6 { 81 | print(char) // a, b, c, d, e, f 82 | counter += 1 83 | } else { break } 84 | } 85 | print("for loop has ended") 86 | 87 | // using a for-loop and enumerated print the first six alphabets 88 | for (index, char) in alphabets.enumerated() { 89 | if index < 6 { // 0, 1, 2, 3, 4, 5 90 | print("\(char) at index \(index)") 91 | } else { 92 | break 93 | } 94 | print("going through alphabets") 95 | } 96 | 97 | let alphabetsStartIndex = alphabets.startIndex 98 | 99 | 100 | 101 | // ============================================ 102 | // multi-line Strings 103 | // ============================================ 104 | 105 | let swiftBird = """ 106 | :'######::'##:::::'##:'####:'########:'########: 107 | '##... ##: ##:'##: ##:. ##:: ##.....::... ##..:: 108 | ##:::..:: ##: ##: ##:: ##:: ##:::::::::: ##:::: 109 | . ######:: ##: ##: ##:: ##:: ######:::::: ##:::: 110 | :..... ##: ##: ##: ##:: ##:: ##...::::::: ##:::: 111 | '##::: ##: ##: ##: ##:: ##:: ##:::::::::: ##:::: 112 | . ######::. ###. ###::'####: ##:::::::::: ##:::: 113 | :......::::...::...:::....::..:::::::::::..::::: 114 | """ 115 | 116 | print(swiftBird) 117 | 118 | 119 | // ascii art 120 | let multilineString = """ 121 | /////////////////////////////////////////////////////////////////////////////// 122 | //////////////////////////////////////////.//////////////////////////////////// 123 | //////////////////////////////////////////// *///////////////////////////////// 124 | ///////////////////////////// ////////////((( ./////////////////////////////// 125 | ///////////////////////// ///// ///////((((((/ ////////////////////////////// 126 | /////////////////////////// //// ///((((((((( //////////////////////////// 127 | //////////////////////////// /// *((((((((( /////////////////////////// 128 | ////////////////////////////// ,( (((((((. ,////////////////////////// 129 | ///////////////////////////////( ( (((( ////////////////////////// 130 | /////////////////////////////((((( .( ////////////////////////// 131 | //////////////////////////(((((((((/ ,///////////////////////// 132 | ////////////////////////(((((((((((((( ////////////////////////// 133 | ////////////////////// (((((((((((((((( ////////////////////////// 134 | //////////////////////// *((((((( ///////////////////////// 135 | ////////////////////////// //////////////////////// 136 | ///////////////////////////// /////////////////////// 137 | ///////////////////////////////// ///////// /////////////////////// 138 | /////////////////////////////////////////////////////////////////////////////// 139 | /////////////////////////////////////////////////////////////////////////////// 140 | /////////////////////////////////////////////////////////////////////////////// 141 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 142 | ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 143 | """ 144 | print(multilineString) 145 | 146 | 147 | -------------------------------------------------------------------------------- /Unit1/Strings-Part-1.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Strings-Part-2.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Strings Part 2 4 | 5 | // question: given a String switch on it and print all the characters if it is even or print every other character if it is odd 6 | 7 | let message = "Bad boy" 8 | 9 | print("there are \(message.count) characters in the string") 10 | 11 | if message.count % 2 == 0 { 12 | print("string is even") 13 | } else { 14 | print("string is odd") 15 | } 16 | 17 | // solution for question above: 18 | switch message { 19 | case message where message.count % 2 == 0: 20 | for char in message { 21 | print(char, terminator: " ") 22 | } 23 | default: 24 | for (index, char) in message.enumerated() where index % 2 == 0 { 25 | print(char, terminator: " ") 26 | } 27 | } 28 | print() 29 | // "\n" is the endline escape character 30 | 31 | //================================================ 32 | // escape characters 33 | // e.g "\n" - newline "\t" - tab "\"" - quote 34 | //================================================ 35 | // newline example 36 | let message1 = "Hello\niOS 6.3\nGreat to have you!" 37 | print(message1) 38 | 39 | let tabMessage = "\tProgramming in fun" 40 | print(tabMessage) 41 | 42 | let quote = "In \"2014\" Swift was introduced" 43 | print(quote) 44 | 45 | let multiline = """ 46 | Hello 47 | It's 48 | Hot out today 49 | """ 50 | 51 | print(multiline) 52 | 53 | 54 | //================================================ 55 | // Using String initialization methods 56 | //================================================ 57 | 58 | // declaring and initializing a Character 59 | // we have to explictly use type annotation to get a valid Character data type 60 | let char: Character = "a" 61 | 62 | // initializing a String from a Character 63 | let str = String(char) 64 | 65 | print(type(of: char)) 66 | print(type(of: str)) 67 | 68 | // initialize a String from an Integer (Int) 69 | let currentYear = String(2019) 70 | print("current year is \(currentYear)") 71 | 72 | let float: Float = 23.56 73 | let double = 45.12 74 | let result = Double(float) + double 75 | print(result) 76 | 77 | //================================================ 78 | // string format e.g formatting decimal places 79 | //================================================ 80 | print("the result of the calculation above is", String(format: "%.2f", result)) 81 | 82 | 83 | //================================================ 84 | // creating a range on a String 85 | //================================================ 86 | let messageToSelf = "I really love Swift and I'm passionate about coding." 87 | 88 | // getting the first position of messageToSelf 89 | let startIndex = messageToSelf.startIndex 90 | 91 | let offsetToSomeCharIndex = messageToSelf.index(startIndex, offsetBy: 18) 92 | let range = startIndex...offsetToSomeCharIndex 93 | 94 | // DOES NOT COMPILE SUBSCRIPT [Int] NOT ALLOWED USING AN INT, ONLY WORKS ON A [String.Index] type 95 | //let substring = messageToSelf[0] 96 | 97 | let substring = messageToSelf[range] 98 | 99 | print("substring is \(substring)") 100 | 101 | 102 | //================================================ 103 | // search for the index of a character in a String 104 | //================================================ 105 | let swiftMessage = "I really love Swift ♥️" 106 | // emoji => control, command, space 107 | 108 | let charIndex = swiftMessage.firstIndex(of: "♥️") ?? swiftMessage.startIndex 109 | 110 | print("We found \"\(swiftMessage[charIndex])\" in swiftMessage String") 111 | 112 | 113 | //================================================ 114 | // prefix and suffix 115 | //================================================ 116 | 117 | // hasPrefix 118 | let name = "alex" 119 | if name.hasPrefix("al") { // hasPrefix() method return a Bool whether the prefix in the String was found 120 | print("Hi Al!") 121 | } 122 | 123 | // hasSuffix 124 | let message2 = "questions" 125 | if message2.hasSuffix("ions") { 126 | print("we also have onions") 127 | } 128 | 129 | // contains 130 | if message2.contains("q") { // runtime for contains is linear or big o of n or O(n) 131 | print("message2 contains q") 132 | } 133 | 134 | 135 | //================================================ 136 | // some Character properties 137 | //================================================ 138 | let character1: Character = "y" 139 | if character1.isLetter { 140 | print("\(character1) is a letter") 141 | } 142 | 143 | // isCurrency e.g $ 144 | 145 | // isPunctuation e.g ? 146 | 147 | // isNumber e.g 4 148 | 149 | 150 | //================================================ 151 | // NSString is an Objective-C API 152 | // API: application programming interface 153 | //================================================ 154 | var message4 = "coding" 155 | message4 = message4.replacingOccurrences(of: "g", with: "🚀") 156 | print(message4) 157 | 158 | let fullname = "Alex Paul Hurtado" 159 | let separatedNames = fullname.components(separatedBy: " ") 160 | print("there are \(separatedNames.count) items") 161 | 162 | print(separatedNames) 163 | -------------------------------------------------------------------------------- /Unit1/Strings-Part-2.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Structs-and-Classes-Wrapup.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // structs, classes and initialization 4 | 5 | // differences between class and structs 6 | /* 7 | - structs have a memberwise initializer, classes do not 8 | - classes have to provide an initializer if ANY of its properties do not have a default value 9 | - classes have inheritance and structs do not 10 | - due to the nature of the immuatability of a struct if you're in a function that modifies one of its properties that method needs to be explicitly marked "mutating" in classes this is not a fact because classes are passed by reference which makes it mutatable by default 11 | - classes have deinitializers and struct do not 12 | */ 13 | 14 | struct Fellow { 15 | // properties 16 | 17 | // type properties, class properties, static properties 18 | static let currentYear = 2019 // Fellow.currentYear 19 | // yulia.currentYear would be a compiler ERROR 20 | 21 | // instance properties 22 | var age: Int // e.g yulia.age but NOT Fellow.age 23 | var cohort: Double 24 | var currentlyEmployed: Bool // true or false 25 | 26 | 27 | // initializers if any 28 | 29 | // type methods, class methods, static methods 30 | static func programInfo() { 31 | print("This is a 10-month intensive program.") 32 | } 33 | 34 | // instance methods 35 | mutating func employed(isEmployed: Bool) { // true or false 36 | currentlyEmployed = isEmployed 37 | } 38 | } 39 | 40 | 41 | 42 | print(Int.max) // 9223372036854775807 43 | // Int.max is known as accessing an (Type property) 44 | // e.g .max ONLY works on ((type)) Int NOT an instance of Int 45 | 46 | // instance of Int 47 | let someInt = 0 48 | //someInt.max // DOES NOT COMPILE BECAUSE AN INSTANCE OF INT CANNOT CALL TYPE PROPERTY 49 | 50 | // making use of struct's memberwise initializer 51 | var yulia = Fellow(age: 21, cohort: 6.3, currentlyEmployed: false) 52 | if yulia.currentlyEmployed { 53 | print("When are you taking me out to lunch") 54 | } else { 55 | print("Lunch is on me today") 56 | } 57 | 58 | // access a Type property 59 | print("Pursuit fellows current year is \(Fellow.currentYear)") 60 | 61 | 62 | // accessing a type method programInfo() 63 | Fellow.programInfo 64 | 65 | class Animal { 66 | var age: Int 67 | var breed: String 68 | var color: String = "white" 69 | init(age: Int, breed: String) { 70 | self.age = age 71 | self.breed = breed 72 | } 73 | 74 | // instance method 75 | func info() { 76 | print("The \(breed) is \(age) old and color is \(color)") 77 | } 78 | } 79 | 80 | // Dog is inheriting Animal 81 | // subclass in Dog, parent class in Animal 82 | class Dog: Animal { 83 | 84 | } 85 | 86 | // created an instance of Dog called frechBulldog 87 | let frenchBulldog = Dog(age: 11, breed: "French Bulldog") 88 | frenchBulldog.info() 89 | -------------------------------------------------------------------------------- /Unit1/Structs-and-Classes-Wrapup.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Structs.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // structs: is a building block of a method in which we emulate an "object" in Swift 4 | 5 | // struct syntax 6 | 7 | // SomeStruct below defines an "object" 8 | // Object-oriented programming (OOP) - encapsulates properties and methods of real world objects 9 | struct SomeStruct { 10 | // definition of the struct includes the following: 11 | // properties - variables or constants on the type (struct) 12 | // initializers - the method in which you create a type 13 | // methods - function inside of a custom type (struct) 14 | } 15 | 16 | struct Resolution { 17 | // properties 18 | // stored properites - a property with a default value 19 | // a property is a variable or constant 20 | var width = 0 21 | var height = 0 22 | } 23 | 24 | //=============================================== 25 | // create an instance of Resolution struct 26 | //=============================================== 27 | 28 | var someResolution = Resolution() 29 | 30 | // accessing properties of Resolution using dot syntax 31 | someResolution.width = 1080 32 | 33 | print(someResolution) 34 | 35 | // structs have a ((memberwise initializer)) as opposed to 36 | // a class that does not 37 | var vga = Resolution(width: 640, height: 480) 38 | print(vga) 39 | 40 | //=============================================== 41 | // structs and enums are *****value types***** 42 | //=============================================== 43 | 44 | let hd = Resolution(width: 1920, height: 1080) 45 | 46 | var cinema = hd // cinema gets a **copy** of hd 47 | // ****COPY DOES NOT CHANGE THE ORIGINAL OBJECT**** 48 | 49 | // what is the value of cinema's here // 1920 50 | print(cinema.width) // 1920 51 | 52 | cinema.width = 2048 53 | 54 | // what is the value of hd's width???? 55 | print(hd.width) // 1920 56 | 57 | //==================================================== 58 | // using object-oriented programming to model a Fellow 59 | //==================================================== 60 | 61 | enum ProgrammingLanguage { 62 | case swift 63 | case objectivec 64 | case java 65 | case javascript 66 | case python 67 | case noLanguage 68 | } 69 | 70 | struct Project { 71 | var projectName = "" 72 | var projectDescription = "" 73 | var language = ProgrammingLanguage.noLanguage 74 | } 75 | 76 | enum Cohort { 77 | case iOS 78 | case android 79 | case web 80 | case dataScience 81 | } 82 | 83 | struct Fellow { 84 | //========================================== 85 | // properties - variable and constants 86 | //========================================== 87 | var name = "John Appleseed" // stored properties 88 | var cohort = Cohort.iOS // iOS, android, web, dataScience 89 | var programmingLanguages = [ProgrammingLanguage]() 90 | var githubURL = "" 91 | var linkedInURL = "" 92 | var hasProgrammingBackground = false 93 | var projects = [Project]() // projects 94 | 95 | //========================================== 96 | // initializers 97 | //========================================== 98 | 99 | //========================================== 100 | // methods 101 | //========================================== 102 | 103 | // class methods 104 | 105 | 106 | // instance methods 107 | // can ONLY be called using instanceName.info() 108 | // or e.g gregg.info() 109 | func info() { 110 | print("\(name) currently has \(projects.count) portfolio project(s)") 111 | } 112 | 113 | func resume(language: ProgrammingLanguage) { 114 | // self represents the instance of Fellow that called 115 | // resume() e.g gregg.resume(language: .swift) 116 | if self.programmingLanguages.contains(language) { 117 | print("\(name) can be hired for this \(language) position.") 118 | } else { 119 | print("\(name) is not qualified for this position.") 120 | } 121 | } 122 | 123 | } 124 | 125 | // creating instances of "objects" 126 | 127 | // creating an instance using the default initializer of Fellow() 128 | var gregg = Fellow() 129 | gregg.name = "Gregg" 130 | gregg.cohort = .iOS 131 | gregg.projects.append(Project(projectName: "Hangman", projectDescription: "Hangman command-line macOS application", language: .swift)) 132 | gregg.info() 133 | // Fellow.info() DOES NOT COMPILE NOT A CLASS METHOD 134 | 135 | 136 | // created an instance of Fellow called oscar and used the memberwise initializer 137 | var oscar = Fellow(name: "Oscar", cohort: .iOS, programmingLanguages: [.swift], githubURL: "https://github.com", linkedInURL: "https://linkedIn.com", hasProgrammingBackground: false, projects: [Project]()) 138 | oscar.info() 139 | 140 | // intances of Project 141 | let calculatorApp = Project(projectName: "Calculator", projectDescription: "Calculator command-line application", language: .swift) 142 | let instagramClone = Project(projectName: "Instagram Clone", projectDescription: "Best photo sharing social app", language: .java) 143 | 144 | // add projects to oscar's portfolio 145 | oscar.projects.append(calculatorApp) 146 | oscar.projects.append(instagramClone) 147 | 148 | oscar.info() // 2 projects 149 | 150 | oscar.resume(language: .javascript) 151 | 152 | oscar.resume(language: .swift) // 🥳 153 | -------------------------------------------------------------------------------- /Unit1/Structs.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/TriviaGame.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexpaul/Lecture-Resources/f5f6712fb3caa0d3931a88415d023d24b2b87c5c/Unit1/TriviaGame.zip -------------------------------------------------------------------------------- /Unit1/TriviaGame/README.md: -------------------------------------------------------------------------------- 1 | # Trivia command-line app 2 | 3 | ## Description 4 | 5 | The TriviaGame takes in a user input of trivia choice they wish to play. Base on the trivia choice the user enters, the app creates an array of the choosen trivia questions. The user then goes through the series of filtered questions. 6 | 7 | ## TriviaData.swift 8 | 9 | A struct the has one single property. The property is a type property that is an array of dictionaries. The dictionaries in the array hold all the questions for the TriviaGame. 10 | 11 | ## TriviaType.swift 12 | 13 | An enum with the trivia options the user will have when starting a game. 14 | 15 | #### Challenge 16 | 1. make TriviaType a rawValue of String 17 | 18 | 19 | ## Game.swift 20 | 21 | This data type will hold all the game playing logic of the TriviaGame. 22 | 23 | #### Challenge 24 | 25 | #### Write the following properties 26 | 1. a questions array property [Question] 27 | 2. a score property 28 | 3. a total questions property 29 | 4. a computed property ```hasMoreQuestions``` that returns a Bool as to whether or not the questions array is empty. 30 | 31 | #### Write the following methods 32 | 1. write a method to get a shuffled question 33 | remove the question from the questions array above 34 | 2. write a method to start the Game, this method 35 | creates the array of questions [Question] 36 | 3. write a method to check if the answer is correct 37 | and increment the score by 1 38 | 4. Write a method that prints out the final score and total of questions. 39 | 5. Write a method that resets the game if the player wishes to continue 40 | 6. Write a method that takes in the users choice of trivia e.g "1" to play movie trivia 41 | 42 | ## Question.swift 43 | 44 | Represents a Question model. We spoke about object-oriented programming. Here we are modelling a question taken from the data array of dictionary elements. The keys in the dictionary represents the properties in the Question object. 45 | 46 | #### Challenge 47 | 48 | 1. Create a failable convenience initializer that takes in a dictionary of type ```[String: Any]``` 49 | 2. Refactor the triviaType property to be of type TriviaType, also update code so it works with the designated initializer 50 | 51 | ## Main.swift 52 | 53 | #### Challenge 54 | 55 | 1. Create a Game instance 56 | 2. Create a property called playAgain and set it to false. This will be modified base on if the user wishes to continue playiing. 57 | 3. Use a repeat-while to start playing the game. 58 | 4. In the repeat-while take the users trivia choice. 59 | 5. Call the select trivia Game instance method in order to start the Game. 60 | 6. Use an embedded repeat-while to loop over all current questions. 61 | 7. Print the current question. 62 | 8. Print the answer choices. 63 | 9. Check the user's answer. 64 | 10.Keep looping inside the inner repeat-while while there are questions left. 65 | 11.When there are no longer questions, print the final score and reset the game. 66 | 12.Ask the user if they wish to continue playing in the outer repeat-while. 67 | -------------------------------------------------------------------------------- /Unit1/TriviaGame/TriviaGame.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Unit1/TriviaGame/TriviaGame.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Unit1/TriviaGame/TriviaGame/Game.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Game.swift 3 | // TriviaGame 4 | // 5 | // Created by Alex Paul on 10/21/19. 6 | // Copyright © 2019 Alex Paul. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class Game { 12 | 13 | // MARK: Properties of Game 14 | 15 | // a questions array property [Question] 16 | // instance property 17 | var questions = [Question]() 18 | 19 | // a score property 20 | var score = 0 // stored property 21 | 22 | // keep track of total questions given to user 23 | var totalQuestions = 0 // stored property 24 | 25 | // computed property, instance property 26 | // e.g game.hasMoreQuestions, return true or false 27 | var hasMoreQuestions: Bool { 28 | // accessors available in Swift are 29 | // getters and setters 30 | // using the not ! symbol to negate or toggle the current value 31 | return !questions.isEmpty 32 | } 33 | 34 | 35 | // MARK: Methods of Game 36 | // write a method to get a shuffled question 37 | func getQuestion() -> Question? { 38 | // shuffle the array 39 | questions = questions.shuffled() 40 | // popLast removes the last element and returns it 41 | return questions.popLast() 42 | } 43 | 44 | 45 | // 2. write a method to start the Game, this method 46 | // creates the array of questions [Question] 47 | // e.g start(.movieType) or start(triviaType: .movieType) 48 | func createQuestions(_ triviaType: TriviaType) { 49 | // step 1 - loop through the array (TriviaData.data) 50 | for dict in Trivia.data { 51 | // step 2 - using key triviaType in the dictionary 52 | // we need to access the value 53 | if let unwrappedTrivia = dict["triviaType"] as? String { 54 | // step 3 - compare the user's triviaType 55 | // with the current triva type in the dictionary 56 | if unwrappedTrivia == triviaType.rawValue { 57 | // step 4 - create a Question and append to 58 | // the questions array 59 | 60 | // step 5 - unwrap Question and add to array 61 | if let question = Question(dict: dict) { 62 | questions.append(question) 63 | } 64 | } 65 | } 66 | } 67 | totalQuestions = questions.count 68 | } 69 | 70 | 71 | // method to check if the answer is correct 72 | // and increment the score by 1 73 | func checkAnswer(usersAnswer: String, question: Question) { 74 | if usersAnswer == question.correctAnswer { 75 | // increment the score by 1 76 | score += 1 77 | print("Correct Answer.\n\(question.fact)") 78 | } else { 79 | print("Wrong answer. Answer is \(question.correctAnswer)\n\(question.fact)") 80 | } 81 | } 82 | 83 | // Write a method that prints out the final score and total number of questions. 84 | func finalScore() { 85 | print("Your final score is \(score) out of \(totalQuestions)") 86 | } 87 | 88 | // Write a method that resets the game if the player wishes to continue 89 | func reset() { 90 | score = 0 91 | //questions = [Question]() 92 | questions.removeAll() 93 | } 94 | 95 | // revisit function parameter names 96 | // there is external paramter name 97 | // internal parameter name 98 | func selectTrivia(_ userResponse: String) { // "1"..."4" 99 | switch userResponse { 100 | case "1": 101 | createQuestions(.movieTrivia) 102 | case "2": 103 | createQuestions(.sportsTrivia) 104 | case "3": 105 | createQuestions(.musicTrivia) 106 | case "4": 107 | createQuestions(.nycTrivia) 108 | case "5": 109 | createQuestions(.secondGradeMath) 110 | default: 111 | print("Trivia type is unavailable") 112 | } 113 | } 114 | 115 | func questionsInfo() { 116 | if questions.isEmpty { 117 | print("Last question.\n") 118 | } else { 119 | print("There are \(questions.count + 1) questions left.\n") 120 | } 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /Unit1/TriviaGame/TriviaGame/Question.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Question.swift 3 | // TriviaGame 4 | // 5 | // Created by Alex Paul on 10/21/19. 6 | // Copyright © 2019 Alex Paul. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class Question { // this should be a struct 12 | var questionPrompt: String 13 | var correctAnswer: String 14 | var choices: String 15 | var fact: String 16 | var triviaType: TriviaType // movieTrivia, musicTrivia, sportsTrivia, nycTrivia 17 | 18 | // designated initializer 19 | init(questionPrompt: String, 20 | correctAnswer: String, 21 | choices: String, 22 | fact: String, 23 | triviaType: TriviaType) { 24 | self.questionPrompt = questionPrompt 25 | self.correctAnswer = correctAnswer 26 | self.choices = choices 27 | self.fact = fact 28 | self.triviaType = triviaType 29 | } 30 | 31 | // failable convenience initializer that 32 | // takes in a dictionary of type [String: Any] 33 | convenience init?(dict: [String: Any]) { 34 | guard let questionPrompt = dict["question"] as? String, 35 | let correctAnswer = dict["correctAnswer"] as? String, 36 | let choices = dict["choices"] as? String, 37 | let fact = dict["fact"] as? String, 38 | let triviaType = dict["triviaType"] as? String else { 39 | return nil 40 | } 41 | // a valid TriviaType from the enum to add to the designated initializer below 42 | self.init(questionPrompt: questionPrompt, 43 | correctAnswer: correctAnswer, 44 | choices: choices, 45 | fact: fact, 46 | // creating a TriviaType using the rawValue 47 | // initializer 48 | triviaType: TriviaType(rawValue: triviaType) ?? TriviaType.sportsTrivia) 49 | } 50 | } 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Unit1/TriviaGame/TriviaGame/TriviaData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TriviaData.swift 3 | // TriviaGame 4 | // 5 | // Created by Alex Paul on 10/21/19. 6 | // Copyright © 2019 Alex Paul. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // https://www.usefultrivia.com/movie_trivia/ 12 | // https://www.factmonster.com/take-quiz/new-york-city 13 | struct Trivia { 14 | static let data: [[String: Any]] = [ 15 | // movie 16 | ["question": "What is the highest grossing movie of all time?", 17 | "correctAnswer": "d", 18 | "choices": "a. Avatar\nb. Titanic\nc. Dark Knight\nd. Avenger Endgame", 19 | "fact": "Surpassed James Cameron's Avatar in 2019 with a gross box office number of $2.79 billion.", 20 | "triviaType": "movieTrivia"], 21 | ["question": "What is the longest movie ever made?", 22 | "correctAnswer": "a", 23 | "choices": "a. The cure for insomnia\nb. Hamlet\nc. The Stand\nd. Dances with Wolves", 24 | "fact": "he Cure for Insomnia (1987) is the longest movie ever made at a total running\ntime of 85 hours (5,220 min). It premiered in its entirety at The School Of The Art Institute in Chicago, Illinois\nfrom January 31 to February 3, 1987, in one continuous showing.", 25 | "triviaType": "movieTrivia"], 26 | ["question": "What was the first movie by Pixar to receive a rating higher than G in the United States?", 27 | "correctAnswer": "c", 28 | "choices": "a. Finding Nemo\nb. Monsters Inc.\nc. The Incredibles\nd. Toy Story", 29 | "fact": "The Incredibles received a PG rating for \"action violence\".", 30 | "triviaType": "movieTrivia"], 31 | ["question": "In The Wizard of Oz (1939), what was used to simulate snow during the poppy scene?", 32 | "correctAnswer": "a", 33 | "choices": "a. Asbestos\nb. Powdered Sugar\nc. Coconut Flakes\nd. Cornflakes", 34 | "fact": "The snow wasn't the only asbestos-laden element of production: \nThe Wicked Witch's broom was made of asbestos, as was the Scarecrow's entire outfit.", 35 | "triviaType": "movieTrivia"], 36 | ["question": "What movie popularized the phrase: \"May the Force be with you\"?", 37 | "correctAnswer": "d", 38 | "choices": "a. E.T\nb. The Matrix\nc. Star Trek\nd. Star Wars", 39 | "fact": "In the Star Wars movies, \"May the Force be with you\" was a phrase \nused to wish good luck or good will. The phrase was often used as individuals\nparted ways or in the face of an impending challenge.", 40 | "triviaType": "movieTrivia"], 41 | 42 | // music 43 | ["question": "What pop singer is known as \"The Material Girl\"?", 44 | "correctAnswer": "b", 45 | "choices": "a. Taylor Swift\nb. Madonna\nc. Britney Spears\nd. Christina Aguilera", 46 | "fact": "Madonna became known as \"The Material Girl\" after her hit single of\nthe same name hit the charts in 1984. She hates it, claiming she\nwould never have done the song if she knew the name would stick.", 47 | "triviaType": "musicTrivia"], 48 | ["question": "What singer holds the world record for most words in a hit single?", 49 | "correctAnswer": "c", 50 | "choices": "a. Kanye West\nb. Busta Rhymes\nc. Eminem\nd. 50 Cents", 51 | "fact": "The Detroit rapper achieved a world record with \"Rap God\".\nThe six-minute track contains 1,560 words which means that\nEminem is rapping a tongue-twisting 4.28 words per second.", 52 | "triviaType": "musicTrivia"], 53 | 54 | // sports 55 | ["question": "Who was the only person in NBA history to be named Most Valuable Player, Coach of the Year, and Executive of the Year?", 56 | "correctAnswer": "a", 57 | "choices": "a. Larry Bird\nb. Michael Jordan\nc. Bill Russel\nd. Phil Jackson", 58 | "fact": "Drafted into the NBA sixth overall by the Boston Celtics in\n1978, Larry Bird played his entire professional career for\nBoston, winning three NBA championships and two NBA\nFinals MVP awards. He then served as head coach of the Indiana Pacers\nfrom 1997 to 2000, and in 2003 assumed the role of president of basketball\noperations for the Pacers.", 59 | "triviaType": "sportsTrivia"], 60 | 61 | // nyc 62 | ["question": "The New York Aquarium is located in which New York City borough?", 63 | "correctAnswer": "c", 64 | "choices": "a. Queens\nb. Bronx\nc. Brooklyn\nd. Manhattan", 65 | "fact": "In 1896, the New York Aquarium first opened in Battery Park, Manhattan,\nbut it was moved to its current location in Brooklyn in 1957.", 66 | "triviaType": "nycTrivia"], 67 | ["question": "What stadium located in Flushing, Queens, is home to the New York Mets?", 68 | "correctAnswer": "d", 69 | "choices": "a. Yankee Stadium\nb. Ebbets Field\nc. Polo Grounds\nd. Shea Stadium", 70 | "fact": "The first game played at Shea Stadium in 1964 was between\nthe New York Mets and the Pittsburgh Pirates in front of 48,736 fans.", 71 | "triviaType": "nycTrivia"], 72 | 73 | // second grade math 74 | ["question": "Which shows a way to find the difference?\n15 - 6 = ____", 75 | "correctAnswer": "a", 76 | "choices": "a. 10 - 1 = 9\nb. 10 - 4 = 6\nc. 10 - 5 = 5\nd. 10 - 6 = 4", 77 | "fact": "10 - 1 = 9 has the same result as 15 - 6 = 9", 78 | "triviaType": "secondGradeMath", 79 | "level": "hard"], 80 | ["question": "Which shows a way to find the sum?\n8 + 5 = ____", 81 | "correctAnswer": "a", 82 | "choices": "a. 10 + 3 = 13\nb. 10 + 5 = 15\nc. 10 + 6 = 16\nd. 10 + 8 = 18", 83 | "fact": "8 + 5 = 13 has the same result as 10 + 3 = 13", 84 | "triviaType": "secondGradeMath", 85 | "level": "3"], 86 | ["question": "Chris has 3 rows of plates.\nThere are 5 plates in each row.\nHow many plates are there in all?", 87 | "correctAnswer": "d", 88 | "choices": "a. 3 + 3 + 3 = 9\nb. 3 + 3 + 5 = 11\nc. 4 + 4 + 4 = 12\nd. 5 + 5 + 5 = 15", 89 | "fact": "", 90 | "triviaType": "secondGradeMath", 91 | "level": "3"], 92 | ["question": "Sally counts 7 stars. Mike\ncounts 1 more star than Sally.\nHow many stars do they count\nin all?\n____stars.", 93 | "correctAnswer": "15", 94 | "choices": "", 95 | "fact": "7 stars for Sally + (7 stars + 1 star for Mike)\n7 + 8 = 15 stars counted in all\n", 96 | "triviaType": "secondGradeMath", 97 | "level": "3"], 98 | ["question": "Phillip puts 5 pencils on each\ndesk. How many pencils does\nPhillip put on 4 desks?/nDraw to show what you did.\n____pencils.", 99 | "correctAnswer": "20", 100 | "choices": "", 101 | "fact": "Desk1: ✏️✏️✏️✏️✏️\nDesk2: ✏️✏️✏️✏️✏️\nDesk3: ✏️✏️✏️✏️✏️\nDesk4: ✏️✏️✏️✏️✏️\n", 102 | "triviaType": "secondGradeMath", 103 | "level": "3"], 104 | ["question": "Tania has 3 rows of stickers.\nThere are 4 stickers in each\nrow. How many stickers does\nTania have in all?\n____stickers.", 105 | "correctAnswer": "12", 106 | "choices": "", 107 | "fact": "Row 1: 🦊 🐻 🐝 🦖\nRow 2: 🦊 🐻 🐝 🦖\nRow 3: 🦊 🐻 🐝 🦖\n", 108 | "triviaType": "secondGradeMath", 109 | "level": "3"], 110 | ["question": "Abe needs 11 football stickers. He has 2 stickers.\nHow many more stickers does Abe need?\n____stickers\nShow how you solved the problem.", 111 | "correctAnswer": "9", 112 | "choices": "", 113 | "fact": "Row 1: 🦊 🐻 🐝 🦖\nRow 2: 🦊 🐻 🐝 🦖\nRow 3: 🦊 🐻 🐝 🦖\n", 114 | "triviaType": "secondGradeMath", 115 | "level": "3"], 116 | ["question": "What is the sum?\n7 + 3", 117 | "correctAnswer": "d", 118 | "choices": "a. 7\nb. 8\nc. 9\nd. 10\n", 119 | "fact": "", 120 | "triviaType": "secondGradeMath", 121 | "level": "1"], 122 | ["question": "What is the difference?\n\n14 - 9 = ____", 123 | "correctAnswer": "c", 124 | "choices": "a. 23\nb. 9\nc. 5\nd. 3\n", 125 | "fact": "", 126 | "triviaType": "secondGradeMath", 127 | "level": "1"], 128 | ["question": "Mia has 8 magnets. Rob has\n7 magnets.\n\nWhich doubles fact can you\nuse to find how many magnets\nthey have is all?\n", 129 | "correctAnswer": "b", 130 | "choices": "a. 9 + 9 = 18\nb. 8 + 8 = 16\nc. 6 + 6 = 12\nd. 5 + 5 = 10\n", 131 | "fact": "", 132 | "triviaType": "secondGradeMath", 133 | "level": "3"], 134 | ["question": "Sharon puts 3 oranges in each\nbag. There are 5 bags. How\nmany oranges are there\nis all?\n", 135 | "correctAnswer": "c", 136 | "choices": "a. 8\nb. 12\nc. 15\nd. 18\n", 137 | "fact": "Bag 1: 🍊 🍊 🍊\nBag 2: 🍊 🍊 🍊\nBag 3: 🍊 🍊 🍊\nBag 4: 🍊 🍊 🍊\nBag 5: 🍊 🍊 🍊\n", 138 | "triviaType": "secondGradeMath", 139 | "level": "3"], 140 | ["question": "Janie has 4 toy dogs, 3 toy\ncats, and 3 toy bears. How\nmany toys does Janie have\nin all?\n", 141 | "correctAnswer": "d", 142 | "choices": "a. 6\nb. 7\nc. 9\nd. 10\n", 143 | "fact": "4 + 3 + 3 = 10 toys in all", 144 | "triviaType": "secondGradeMath", 145 | "level": "1"], 146 | ["question": "What is the sum?\n\n5 + 6 + 7 = ____\n", 147 | "correctAnswer": "d", 148 | "choices": "a. 11\nb. 13\nc. 16\nd. 18\n", 149 | "fact": "", 150 | "triviaType": "secondGradeMath", 151 | "level": "1"], 152 | ["question": "There are 7 ducks on a pond.\nSome more ducks joined them.\nThen there were 12 ducks on\nthe pond. How many ducks\njoined them?\n", 153 | "correctAnswer": "b", 154 | "choices": "a. 4\nb. 5\nc. 12\nd. 19\n", 155 | "fact": "12 - 7 = 5 ducks joined.", 156 | "triviaType": "secondGradeMath", 157 | "level": "2"], 158 | ["question": "What is the missing number in\nthe related subraction fact?\n\n6 + 5 = 11\n11 - 6 = ____\n", 159 | "correctAnswer": "c", 160 | "choices": "a. 11\nb. 6\nc. 5\nd. 4\n", 161 | "fact": "", 162 | "triviaType": "secondGradeMath", 163 | "level": "1"], 164 | ["question": "Ally has 12 dimes. Louis has 5\ndimes. How many more dimes\ndoes Ally have than Louis?\n", 165 | "correctAnswer": "a", 166 | "choices": "a. 7\nb. 8\nc. 9\nd. 17\n", 167 | "fact": "12 - 5 = 7 (Ally has 7 more dimes than Louis)", 168 | "triviaType": "secondGradeMath", 169 | "level": "2"], 170 | 171 | 172 | ["question": "Glenn has 6 markers in his\ndesk. He has 1 marker in his\npocket. How many markers\ndoes Glenn have\n____markers\n", 173 | "correctAnswer": "7", 174 | "choices": "", 175 | "fact": "6 + 1 = 7 markers", 176 | "triviaType": "secondGradeMath", 177 | "level": "2"], 178 | 179 | ] 180 | } 181 | -------------------------------------------------------------------------------- /Unit1/TriviaGame/TriviaGame/TriviaType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TriviaType.swift 3 | // TriviaGame 4 | // 5 | // Created by Alex Paul on 10/21/19. 6 | // Copyright © 2019 Alex Paul. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum TriviaType: String { 12 | case movieTrivia // movieTrivia.rawValue = "movieTrivia" 13 | case musicTrivia 14 | case sportsTrivia 15 | case nycTrivia 16 | case secondGradeMath 17 | } 18 | -------------------------------------------------------------------------------- /Unit1/TriviaGame/TriviaGame/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // TriviaGame 4 | // 5 | // Created by Alex Paul on 10/21/19. 6 | // Copyright © 2019 Alex Paul. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // create a Game instance 12 | let game = Game() 13 | 14 | var playAgain = false 15 | 16 | let userPrompt = """ 17 | Select the type of Trivia you would like to play? 18 | 1. Movie Trivia 19 | 2. Sports Trivia 20 | 3. Music Trivia 21 | 4. NYC Trivia 22 | 5. Second Grade Math 23 | """ 24 | 25 | repeat { // checks if user wants to continue 26 | print(userPrompt) 27 | let userResponse = readLine() ?? "" 28 | print() 29 | game.selectTrivia(userResponse) 30 | repeat { // goes through the questions array 31 | guard let question = game.getQuestion() else { 32 | break 33 | } 34 | game.questionsInfo() 35 | print(question.questionPrompt) 36 | print(question.choices) 37 | let userAnswer = readLine() ?? "" 38 | game.checkAnswer(usersAnswer: userAnswer, question: question) 39 | print() 40 | }while game.hasMoreQuestions 41 | 42 | game.finalScore() 43 | 44 | // prompt the user whether or not they want to keep 45 | // playing 46 | print("Do you wish to continue playing? (yes, no)") 47 | let shouldContinuePlaying = readLine() ?? "" 48 | if shouldContinuePlaying == "yes" { 49 | game.reset() 50 | playAgain = true 51 | } else { 52 | playAgain = false 53 | } 54 | print() 55 | } while playAgain 56 | -------------------------------------------------------------------------------- /Unit1/Types-Variables.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | var str = "Hello, playground" 4 | 5 | // - comment 6 | // Data Types: String, Int (Integer) 7 | //============================================== 8 | // String 9 | //============================================== 10 | 11 | // declared a variable fellowName of type String 12 | // Type Inference: implicit declaration of a variable I 13 | var fellowName = "David Lin" 14 | 15 | print(fellowName) // David Lin 16 | 17 | fellowName = "Chelsi Christmas" 18 | 19 | print(fellowName) // Chelsi Christmas 20 | 21 | fellowName = "34" 22 | 23 | 24 | // DOES NOT COMPILE - CANNOT ADD DIFFERENT DATA TYPES 25 | //let newString = "34" + 12 26 | 27 | // concatenation - adding together 28 | let fullName = "Alex" + " Paul" // Alex Paul 29 | 30 | var fallCycle = "iOS 6.3" 31 | 32 | // using String Interpolation we are printing fullName's description 33 | print(fullName + "is the iOS Instructor for \(fallCycle)") 34 | 35 | // Type Annotation - explicity writing the data type using : (colon) 36 | var cohort: String = "iOS 6.3" 37 | 38 | let lowercaseName = "alex" 39 | let uppercaseName = "Alex" 40 | 41 | let stringResult = lowercaseName == uppercaseName 42 | 43 | let alphabeticalOrder = "Kelyby" < "Lorraine" 44 | print("alphabeticalOrder result \(alphabeticalOrder)") 45 | 46 | //============================================== 47 | // Character 48 | //============================================== 49 | var alphabet: Character = "c" 50 | 51 | // mutating cohort 52 | // var is mutable - meaning can be changed 53 | cohort = "iOS 7.3" 54 | 55 | 56 | //============================================== 57 | // Int 58 | //============================================== 59 | // declared variable age and initialized value to 32 60 | var ageOfFellow = 32 61 | 62 | var futureAge = ageOfFellow + 8 63 | 64 | // String interpolation is embedding a variable into a String using \(variable name) syntax as seen below 65 | print("Age of fellow 8 years from now is \(futureAge)") 66 | 67 | // integer division truncates decimals (removes them) 68 | let integerDivison = 16 / 3 69 | print("integer division is \(integerDivison)") 70 | 71 | 72 | //============================================== 73 | // Division by 0 74 | //============================================== 75 | // 89 / 0 DOES NOT COMPILE 76 | 77 | 78 | //============================================== 79 | // Double 80 | //============================================== 81 | var balance = 100005.9 82 | 83 | // re-assign balance a new value of 85000 84 | balance = balance + 85000 85 | 86 | print(balance) 87 | 88 | 89 | // floating point division keeps decimals 90 | //let floatingPointDivison = 16.0 / 3.0 (also valid to keep decimal points) 91 | let floatingPointDivison: Double = 16 / 3 92 | print("floating point division is \(floatingPointDivison)") 93 | 94 | 95 | //============================================== 96 | // Float vs Double 97 | // Float holds 32-bit vs 64-bit of a Double 98 | //============================================== 99 | let floatNum: Float = 67.990776788943 100 | let doubleNum = 67.990776788943 101 | print("float is \(floatNum) and double is \(doubleNum)") 102 | 103 | // DOES NOT COMPILE - CANNOT ADD A FLOAT WITH A DOUBLE 104 | //let accountBalance = floatNum + doubleNum 105 | 106 | // here we are casting (converting) a Float to a Double 107 | let accountBalance = Double(floatNum) + doubleNum 108 | print("account balance is now \(accountBalance)") 109 | 110 | 111 | 112 | //============================================== 113 | // Short hand arithmetic 114 | //============================================== 115 | balance -= 180000 116 | 117 | print(balance) 118 | 119 | 120 | 121 | //============================================== 122 | // Boolean - Bool, Comparison Operators 123 | //============================================== 124 | var result = 70 < 100 125 | 126 | print(result) 127 | 128 | var otherResult = result && true 129 | 130 | print(otherResult) 131 | 132 | 133 | -5 > -2 && 3 >= -5 134 | 135 | //============================================== 136 | // Arithmetic operators 137 | //============================================== 138 | //============================================== 139 | // THIS DOES NOT COMPILE - let is immuatable - constant 140 | //============================================== 141 | //let salary = 20000 142 | //salary *= 2 143 | //print(salary) 144 | var salary = 20000 145 | salary *= 2 146 | // this line above is the same as (salary = salary * 2) 147 | print(salary) 148 | 149 | 150 | var marathonTime = 6 // 6 hours 151 | marathonTime /= 2 152 | print(marathonTime) // 3 153 | 154 | //============================================== 155 | // Modulo operator or Remainder operator 156 | //============================================== 157 | var modResult = 16 % 3 158 | print(modResult) 159 | 160 | var even = 12 % 6 161 | print(even) 162 | 163 | 164 | //============================================== 165 | // Constants 166 | //============================================== 167 | let pi = 3.14 168 | 169 | -------------------------------------------------------------------------------- /Unit1/Types-Variables.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit1/Types-Variables.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Unit1/Types-Variables.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Unit1/Types-Variables.playground/playground.xcworkspace/xcuserdata/alexpaul.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexpaul/Lecture-Resources/f5f6712fb3caa0d3931a88415d023d24b2b87c5c/Unit1/Types-Variables.playground/playground.xcworkspace/xcuserdata/alexpaul.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Unit2/Big-O-Notation.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | //==================================================== 4 | // Lecture Video: https://youtu.be/b9AvLEFihFw 5 | //==================================================== 6 | 7 | // Big O Notation: calculating the performanc of a given algorithm 8 | 9 | // Big O has two performance metrics: 10 | // 1. time complexity 11 | // 2. space complexity 12 | 13 | 14 | // fastest to slowest runtimes (time complexity) 15 | // O(1), O(log n), O(n), O(n log n), O(n ^ 2), O(2 ^ n), O(n!) 16 | 17 | 18 | 19 | //==================================================== 20 | // O(1) - constant time 21 | //==================================================== 22 | func printFirstElement(arr: [String]) { 23 | guard let first = arr.first else { 24 | return 25 | } 26 | print(first) 27 | } 28 | printFirstElement(arr: ["Greg", "Matt"]) 29 | 30 | 31 | let fellows = ["Mel", "Yulia", "Stephanie"] 32 | 33 | // what is the runtime of the line below? 34 | fellows[2] // O(1) 35 | 36 | let firstTwoFellows = fellows.prefix(10) // O(1) 37 | print(firstTwoFellows) 38 | 39 | let numbers: Set = [1, 2, 3, 4] 40 | numbers.contains(3) // O(1) 41 | 42 | 43 | 44 | //==================================================== 45 | // O(log n) - logorithmic time 46 | // on every iteration the the problem increments 47 | // or decrements by double the current value 48 | //==================================================== 49 | let n = 16 50 | var j = 1 51 | while j < n { 52 | j *= 2 // 2, 4, 8, 16 53 | } 54 | 55 | 56 | 57 | 58 | //==================================================== 59 | // O(n) - linear time 60 | //==================================================== 61 | 62 | // n represents the number of elements in the collection 63 | for fellow in fellows { // O(n) => O(3) 64 | print(fellow) 65 | } 66 | 67 | var count = 0 68 | while count < 10 { 69 | print(count) 70 | count += 1 71 | } 72 | 73 | 74 | 75 | //==================================================== 76 | // O(n log n), e.g .sorted(), mergeSort, quickSort 77 | //==================================================== 78 | 79 | for _ in 0..<10 { // O(n) => 10 80 | var j = 1 81 | while j < n { // O(log n) => 4 82 | j *= 2 // 2, 4, 8, 16 83 | } 84 | } 85 | 86 | //==================================================== 87 | // O(n ^ 2) - quadratic 88 | //==================================================== 89 | 90 | let list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 91 | for i in 0.. 10 92 | for j in 0.. 10 93 | print("\(list[i]) * \(list[j]) = \(list[i] * list[j])") 94 | } 95 | } 96 | 97 | 98 | 99 | //==================================================== 100 | // deriving compound runtimes 101 | //==================================================== 102 | func compoundRuntimes(arr: [Int]) { 103 | for _ in 0..<1000 { 104 | print("Hi!") 105 | } 106 | for num in arr { 107 | print(num) 108 | } 109 | for (indexOne,numOne) in arr.enumerated() { // O(n) 110 | for (indexTwo, numTwo) in arr.enumerated() { //O(n) 111 | if indexOne != indexTwo && numOne == numTwo { 112 | print("It's a match! \(numOne) and \(numTwo) are equal") 113 | } 114 | } 115 | } 116 | } 117 | // solution: O(n ^ 2) 118 | 119 | 120 | -------------------------------------------------------------------------------- /Unit2/Big-O-Notation.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit2/Protocols.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | //=================================================== 4 | // Lecture Video: https://youtu.be/A_2GhR1GEt0 5 | //=================================================== 6 | 7 | 8 | // Protocol: is a blueprint that list properties, methods or initializers that a (conforming type - could be an enum, a struct or a class) is required to implement 9 | 10 | protocol SomeProtocol { 11 | // properties 12 | var someString: String { get set } 13 | var someInt: Int { get } 14 | 15 | //init(age: Int) 16 | 17 | // methods 18 | func someMethod() 19 | mutating func someMutatingMethod() 20 | } 21 | 22 | // conforming object, conforms to SomeProtocol 23 | // conform: enter agreement whereby this type 24 | // WILL implement all listed required properties, methods 25 | // and initializers 26 | struct SomeStruct: SomeProtocol { 27 | var someString: String = "" 28 | 29 | var someInt: Int { 30 | return 10 31 | } 32 | 33 | func someMethod() { 34 | print("some method") 35 | } 36 | 37 | mutating func someMutatingMethod() { 38 | print("some mutating method") 39 | } 40 | } 41 | var someStruct = SomeStruct() 42 | someStruct.someString = "message" 43 | 44 | 45 | protocol Race { 46 | var type: String { get } 47 | var distance: Double { get } 48 | var name: String { set get } 49 | 50 | func info() 51 | } 52 | 53 | struct Marathon: Race { 54 | var type: String { 55 | return "Marathon" 56 | } 57 | var distance: Double { // is a get-only property, cannot mutate 58 | return 26.2 59 | } 60 | // attempt to use a setter to mutate distance 61 | // nycMarathon.distance = 13.1 62 | 63 | var name: String = "NYC Marathon" // both a setter and getter 64 | // setter 65 | // example nycMarathon.name = "TCS NYC Marathon" 66 | 67 | // getter 68 | // example print(nycMaraton.name) // TCS NYC Marathon 69 | 70 | var location: String = "New York City" 71 | 72 | func info() { 73 | print("The \(name) is a \(type) and it is \(distance) long.") 74 | } 75 | } 76 | var nycMarathon = Marathon(name: "TCS NYC Marathon") 77 | nycMarathon.info() 78 | 79 | 80 | // create a protocol and create a struct that conforms to that protocol, create an instance of the struct and test 81 | 82 | protocol Human { 83 | var eat: String { get } 84 | var sleep: Int { get } 85 | var name: String { set get } 86 | func drink() 87 | } 88 | 89 | struct Kelby: Human { 90 | var name: String = "Kelby" 91 | var eat: String { 92 | return "food" 93 | } 94 | var sleep: Int { 95 | return 7 // hours 96 | } 97 | 98 | func drink() { 99 | print("My name is \(name), I eat \(eat), I sleep \(sleep) hours a night and I must drink water ") 100 | } 101 | } 102 | 103 | var kelby = Kelby() 104 | kelby.drink() 105 | 106 | 107 | protocol FullyNamed { 108 | var fullName: String { get } 109 | } 110 | 111 | struct Person: FullyNamed, CustomStringConvertible, Equatable { 112 | var age: Int 113 | var occupation: String 114 | var fullName: String { // get-only property 115 | return "John Appleseed" 116 | } 117 | var description: String { 118 | return "\(fullName) is \(age) years old and is a \(occupation)" 119 | } 120 | } 121 | var john = Person(age: 56, occupation: "Web Developer") 122 | print(john) 123 | 124 | var greg = Person(age: 19, occupation: "Ruby Developer") 125 | 126 | if john == greg { 127 | print("It's the same person") 128 | } else { 129 | print("different peopple") 130 | } 131 | 132 | 133 | // create a Movie struct, declare at least 2 properties in the Movie struct (name, genre), create 2 instances of Movie and conform to Equatable, test your solution, e.g movie1 == movie2 or movie1 != movie2 134 | 135 | // code here 136 | struct Movie: Equatable { 137 | var name: String 138 | var genre: String 139 | var rating: Double 140 | } 141 | 142 | var favMovie = Movie(name: "Coming to America", genre: "Comedy", rating: 9.9) 143 | var secFavMovie = Movie(name: "Diary of a Mad Black Woman", genre: "Comedy", rating: 8.2) 144 | 145 | if favMovie == secFavMovie { 146 | print("They are equal") 147 | } else { 148 | print("They are not the same") 149 | } 150 | 151 | // create a Fellow struct, create 2 instances of Fellow, create the following properties (name: String, cohort: Double), then compare the Fellow instances to verify who is in the most recent cohort, first fellow instance should be 5.0 and second should be 6.0, e.g fellow1 > fellow2 152 | 153 | // code here 154 | 155 | struct Fellow: Comparable { 156 | 157 | // e.g mel < matt 158 | static func > (lhs: Fellow, rhs: Fellow) -> Bool { 159 | print("> got called") 160 | return lhs.cohort > rhs.cohort 161 | } 162 | 163 | static func < (lhs: Fellow, rhs: Fellow) -> Bool { 164 | print("< got called") 165 | return lhs.cohort < rhs.cohort 166 | } 167 | 168 | var name: String 169 | var cohort: Double 170 | } 171 | 172 | var mel = Fellow(name: "Mel", cohort: 5.0) 173 | var matt = Fellow(name: "Matt", cohort: 6.0) 174 | var eric = Fellow(name: "Eric", cohort: 6.0) 175 | 176 | if mel < matt { // 5.0 < 6.0 177 | print("Mel is an alumn") 178 | } else { 179 | print("Mel is in the current cohort") 180 | } 181 | 182 | if matt > mel { // 6.0 > 5.0 183 | print("Matt is in the current cohort") 184 | } else { 185 | print("Matt is a graduate.") 186 | } 187 | 188 | if matt >= eric { 189 | print("They're in the same cohort") 190 | } else { 191 | print("Not is the same cohort") 192 | } 193 | 194 | 195 | //=================================================== 196 | // Delegation 197 | //=================================================== 198 | 199 | // Delegation is a design pattern in Swift that enables 200 | // objectA notifications on objectB 201 | 202 | // AnyObject restricts the GameDelegate protocol to ONLY 203 | // classes 204 | protocol GameDelegate: AnyObject { 205 | // all methods here are required 206 | func startGame() 207 | func endGame(score: Int) 208 | } 209 | 210 | class BlackJackGame { 211 | 212 | // weak break strong reference retain cycles 213 | // basically when two objects has a strong reference to each 214 | // other that creates a memory leak, more on that later 215 | weak var delegate: GameDelegate? 216 | 217 | func gameStatus() { 218 | let score = Int.random(in: 18...25) 219 | delegate?.endGame(score: score) 220 | } 221 | } 222 | 223 | // .e.g UITextFieldDelegate, UITableViewDelegate. UICollectionViewDelegate 224 | class BlackJackViewController: UIViewController, GameDelegate { 225 | func startGame() { 226 | print("BlackJack game started.") 227 | } 228 | 229 | func endGame(score: Int) { 230 | switch score { 231 | case 21: 232 | print("BlackJack") 233 | case ...20: 234 | print("Keep playing \(score)") 235 | case 22...: 236 | print("Busted with a score of \(score)") 237 | default: 238 | print("score not available") 239 | } 240 | } 241 | } 242 | 243 | var blackJackGame = BlackJackGame() 244 | var viewcontroller = BlackJackViewController() 245 | 246 | // in order to get notifications from the BlackJackGame we need to set the delegate and assign the conforming class 247 | blackJackGame.delegate = viewcontroller 248 | 249 | // viewcontroller instance is registered as a delegate of blackJackGame to listen for changes on the game 250 | blackJackGame.gameStatus() 251 | 252 | 253 | -------------------------------------------------------------------------------- /Unit2/Protocols.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit2/README.md: -------------------------------------------------------------------------------- 1 | ## Unit 2 - iOS Development with UIKit 2 | -------------------------------------------------------------------------------- /Unit3/JSONParsing.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // New topics related to JSON parsing in Swift 4 | /* 5 | - JSON - Web formatted data in Javascript formatting, root level object and be an array or a dictionary 6 | - Codable - swift type needs to conform to Codable in order to decode JSON to that object 7 | - do{...}catch{...} - is a block of code we are attempting to execute that can throw an error 8 | in the do{...} block is the code we are attempting to execute 9 | in the catch{...} block is the error if any, that was thrown 10 | - JSONDecoder() - is the swift class that does that actual decoding of the JSON data to our swift object, e.g here JSON -> the Person() object 11 | */ 12 | 13 | // Codable is an alias that encapsulates the (Decodable and Encodable) protocol 14 | struct Person: Codable { // we need to conform to Codable in order to decode the JSON data 15 | let name: String 16 | let occupation: String 17 | let age: Int 18 | let latitude: Double 19 | } 20 | 21 | let jsonData = """ 22 | { 23 | "name": "Alex Paul", 24 | "occupation": "iOS Instructor", 25 | "age": 41, 26 | "latitude": 40.73 27 | } 28 | """.data(using: .utf8)! 29 | 30 | 31 | // Person.self implies that the JSON root level object is a dictionary 32 | // [Person].self implies that the JSON root level object is an array 33 | do { 34 | let person = try JSONDecoder().decode(Person.self, from: jsonData) 35 | print("Person's name is \(person.name) and occupation is \(person.occupation)") 36 | } catch { 37 | print("decoding error: \(error)") 38 | } 39 | -------------------------------------------------------------------------------- /Unit3/JSONParsing.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit3/README.md: -------------------------------------------------------------------------------- 1 | # Unit 3 - Networking in iOS - Parsing JSON, RESTFul Web APIs, Concurrency and GCD, URLSession 2 | -------------------------------------------------------------------------------- /Unit4/Generics-inout-Functions-Stacks.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Objectives 4 | /* 5 | - inout function 6 | - generics, generic function 7 | - stack: using a generic type 8 | */ 9 | 10 | // inout function allow us to change variables outside 11 | // the scope of a function 12 | // *****in-place means our function should be an inout function**** 13 | func swapTwoInts(int1: inout Int, int2: inout Int) { 14 | let temp = int1 // saved the value of int1 to avoid overriden it 15 | int1 = int2 16 | int2 = temp 17 | } 18 | 19 | var num1 = 4 20 | var num2 = 13 21 | 22 | print("values of ints before swap is \(num1) \(num2)") 23 | swapTwoInts(int1: &num1, int2: &num2) 24 | print("values of ints after swap is \(num1) \(num2)") 25 | 26 | func swapTwoStrings() { 27 | 28 | } 29 | 30 | func swapTwoFellows() { 31 | 32 | } 33 | 34 | // generic function 35 | func swapTwoValues(value1: inout T, value2: inout T) { 36 | let temp = value1 37 | value1 = value2 38 | value2 = temp 39 | } 40 | 41 | var name1 = "Alex" 42 | var name2 = "Paul" 43 | 44 | print("values of swap before \(name1) \(name2)") 45 | swapTwoValues(value1: &name1, value2: &name2) 46 | print("values of swap after \(name1) \(name2)") 47 | 48 | 49 | // Any is not type-safe 50 | // Generic enforces type-safety 51 | 52 | var arr: [Any] = [45, 7, 0, true, 90.8] 53 | arr.append("fellow") 54 | 55 | 56 | 57 | // implement a Generic Stack using an array 58 | 59 | struct IntStack { 60 | private var elements = [Int]() 61 | } 62 | 63 | // generic type 64 | struct Stack { 65 | private var elements = [T]() // works with any type 66 | 67 | public var peek: T? { 68 | return elements.last 69 | } 70 | 71 | public mutating func push(item: T) { 72 | elements.append(item) 73 | } 74 | 75 | public mutating func pop() -> T? { 76 | guard !elements.isEmpty else { 77 | return nil 78 | } 79 | return elements.removeLast() 80 | } 81 | } 82 | 83 | var cohorts = Stack() 84 | cohorts.push(item: 1.0) 85 | cohorts.push(item: 2.0) 86 | cohorts.push(item: 3.0) 87 | cohorts.push(item: 4.0) 88 | cohorts.push(item: 5.0) 89 | cohorts.push(item: 6.3) 90 | 91 | print(cohorts.peek) // 6.3 92 | 93 | cohorts.pop() 94 | cohorts.pop() 95 | cohorts.pop() 96 | cohorts.pop() 97 | cohorts.pop() 98 | cohorts.pop() 99 | cohorts.pop() 100 | cohorts.pop() 101 | cohorts.pop() 102 | cohorts.pop() 103 | 104 | 105 | print(cohorts.peek) // 4.0 106 | 107 | 108 | struct Fellow { 109 | let name: String 110 | let language: String 111 | let isEmployed: Bool 112 | } 113 | 114 | let ameni = Fellow(name: "Ameni", language: "Swift", isEmployed: true) 115 | let tom = Fellow(name: "Tom", language: "Kotlin", isEmployed: false) 116 | 117 | var fellows = Stack() 118 | fellows.push(item: tom) 119 | print(fellows) // ["Tom"] 120 | 121 | -------------------------------------------------------------------------------- /Unit4/Generics-inout-Functions-Stacks.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit4/LinkedList.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // implementing a Node abstract data structure 4 | class Node: Equatable { 5 | var value: T 6 | var next: Node? // Singly linked list 7 | //var previous: Node? // Doubly linked list 8 | 9 | // required function for Equatable 10 | // (lhs) tail == (rhs) head 11 | static func ==(lhs: Node, rhs: Node) -> Bool { 12 | // T && T == true 13 | // T && F == false 14 | return lhs.value == rhs.value && lhs.next == rhs.next 15 | } 16 | 17 | init(_ value: T) { 18 | self.value = value 19 | } 20 | } 21 | 22 | // implementing CustomStringConvertible to customize description of a Node 23 | extension Node: CustomStringConvertible { 24 | var description: String { 25 | guard let next = next else { 26 | return "\(value) -> nil" // 12 -> nil 27 | } 28 | // if we have connected nodes 29 | return "\(value) -> \(next)" 30 | } 31 | } 32 | 33 | // instantiating node instances 34 | let car12 = Node(12) 35 | let car99 = Node(99) 36 | 37 | // link our nodes (linked list using connected nodes) 38 | car12.next = car99 39 | //car99.previous = car12 <-> 40 | 41 | // print the current state of the linked node 42 | // in order to print our connected nodes in a readable manner 43 | // we conformed to CustomStringConvertible 44 | // implement var description and wrote the print logic 45 | print(car12) // 12 -> 99 46 | 47 | // array implement description 48 | //let fellows1 = ["Ameni", "Lilia"] 49 | //print(fellows1) 50 | 51 | 52 | // implementation of a Linked List 53 | 54 | class LinkedList { 55 | var head: Node? // nil 56 | var tail: Node? // nil 57 | 58 | // first computed property 59 | public var first: Node? { 60 | return head 61 | } 62 | 63 | // last computed property 64 | public var last: Node? { 65 | return tail 66 | } 67 | 68 | // isEmpty computed property 69 | public var isEmpty: Bool { 70 | print("empty list") 71 | return head == nil // if head equal to nil then list is empty 72 | } 73 | 74 | // append method - adds a Node to the end of the list 75 | public func append(_ value: T) { 76 | // create a Node 77 | let newNode = Node(value) 78 | // scenario 1: appending to an empty list 79 | guard let lastNode = tail else { 80 | // empty list 81 | head = newNode 82 | tail = head 83 | return 84 | } 85 | // scenario 2: existing nodes 86 | lastNode.next = newNode 87 | tail = newNode 88 | } 89 | 90 | // removeLast method - removes the last node from the end of the list 91 | public func removeLast() -> Node? { 92 | // scenario 1 - empty list 93 | if isEmpty { 94 | return nil 95 | } 96 | var removedNode: Node? 97 | if head == tail { 98 | // scenario 2 - if head and tail are pointing to the same Node 99 | removedNode = head 100 | head = nil 101 | tail = nil 102 | return removedNode 103 | } 104 | // scenario 3 - iterate, traverse, walk the linked list starting from the head 105 | 106 | var currentNode = head 107 | 108 | while currentNode?.next != tail { // stop at Node before the tail 109 | // keep traversing 110 | currentNode = currentNode?.next // increment currentNode by 1 111 | } 112 | 113 | // where is currentNode at the end of the while loop 114 | 115 | // save the tail's node before removing the last node (tail) 116 | removedNode = tail 117 | 118 | // set tail to Node before the last node 119 | tail = currentNode 120 | 121 | currentNode?.next = nil 122 | 123 | return removedNode 124 | } 125 | } 126 | 127 | extension LinkedList: CustomStringConvertible { 128 | // stored property 129 | // var name = 90 - DOES NOT COMPILE, EXTENSIONS ARE NOT ALLOWED TO HAVE STORED PROPERTIES 130 | 131 | // computed property 132 | var description: String { 133 | guard let head = head else { 134 | return "empty list" 135 | } 136 | return "\(head)" 137 | } 138 | } 139 | 140 | 141 | let fellows = LinkedList() 142 | fellows.append("Oscar") 143 | fellows.append("Tanya") 144 | fellows.append("David") 145 | 146 | print(fellows) // Oscar -> Tanya -> David -> nil 147 | 148 | 149 | // test removing last node 150 | fellows.removeLast() // Oscar -> Tanya -> nil 151 | 152 | print(fellows) 153 | 154 | fellows.append("Luba") // Oscar -> Tanya -> Luba -> nil 155 | 156 | print(fellows) 157 | 158 | fellows.removeLast() 159 | fellows.removeLast() 160 | fellows.removeLast() 161 | fellows.removeLast() 162 | fellows.removeLast() 163 | fellows.removeLast() 164 | 165 | 166 | 167 | 168 | // 7 -> 1 -> 0 169 | // 0 -> 1 -> 7 170 | -------------------------------------------------------------------------------- /Unit4/LinkedList.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit4/README.md: -------------------------------------------------------------------------------- 1 | # Unit 4 - Persistence, CollectionViews, UIImagePickerController, Animation 2 | -------------------------------------------------------------------------------- /Unit5/BinarySearch.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // binary search - implemented using recursion 4 | 5 | // binary search - we use this searching algorithm to search for a 6 | // given value 7 | 8 | // runtime - O(log n) - as array is dividing on each pass 9 | 10 | // array MUST be sorted 11 | // array is divided in halves to find the middle index 12 | // based on the current value at the middle index we 13 | // either continue searching to the left of the middle index 14 | // or 15 | // continue searching for the value to the right of the middle index 16 | // we use divide and conquer and implement the steps above 17 | // until we find our value or do not find a value when steps 18 | // have been exhausted 19 | 20 | // implementing binary search using recursion 21 | func binarySearch(_ arr: [T], searchKey: T, range: Range) -> Int? { 22 | 23 | // check to ensure that the upper bound is higher than the lower bound 24 | //if 5 > 0 return nil 25 | 26 | //[4, 5, 8] 27 | // lower bound 0 28 | // upper bound 2 29 | if range.lowerBound >= range.upperBound { 30 | return nil 31 | } 32 | 33 | // calculate middle index 34 | let middleIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2 35 | 36 | // 3 checks 37 | // 1. is middle index value equal to search key (if it is we have found the search key) 38 | // 2. if the value at the middle index is greater than the search key, we will now look at the left side of the middle index 39 | // 3. if the value at the middel index is less than search value, we look look to the right 40 | 41 | // check 1 42 | if arr[middleIndex] == searchKey { 43 | return middleIndex 44 | } 45 | 46 | // check 2 47 | else if arr[middleIndex] > searchKey { // left side of middle index 48 | return binarySearch(arr, searchKey: searchKey, range: range.lowerBound.. 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit5/BubbleSort.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // bubble sort 4 | // sorting algorithm 5 | // runtime: O(n ^ 2) - quadratic (considered as the worse sorting algorithm) 6 | // space complexity: O(1) - constant - sorts in place 7 | // sorts in place - inout function 8 | 9 | func bubbleSort(_ arr: inout [Int]) { // inout indicates in place manipulation 10 | guard arr.count >= 2 else { return } 11 | for _ in 0.. 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit5/InsertionSort.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // sorting algorithms: 4 | // slower: O(n ^ 2) - bubble sort, insertion sort 5 | // faster: O(n log n) - merge sort, quicksort 6 | 7 | // insertion sort 8 | // runtime: O(n ^ 2) 9 | // space: O(1) because sorts in place 10 | // slighly more performant than bubble sort 11 | // given a partially sorted and small sized array could be a good choice sorting algorithm 12 | 13 | // swift's sorting algorithm (hybrib algorithm) is n log n, uses insertion sort on small, partially sorted arrays 14 | 15 | // [4, 5, 9, -2] 16 | 17 | func insertionSort(_ arr: inout [Int]) { 18 | guard arr.count >= 2 else { return } 19 | for current in 1.. 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit5/MergeSort.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // merge sort 4 | // worst, best and average runtime is O(n log n) 5 | // uses divide and conquer 6 | // splits the array in two using the middle index 7 | // uses recursion until a base case count is greater than 1 8 | // then merges individual arrays back together while sorting 9 | 10 | // Instagram due today 11:59 11 | 12 | // Firebase Auth - due wednesday 13 | 14 | // Firebase Firestore - due 6pm on Friday 15 | 16 | // DSA questions review 17 | 18 | // next week mon, tue for extra review 19 | 20 | // next wed CTA iOS assessment 21 | 22 | 23 | 24 | func mergeSort(_ arr: [T]) -> [T] { 25 | // base case count is greater than 1 26 | guard arr.count > 1 else { return arr } 27 | let middleIndex = arr.count / 2 28 | 29 | // left array includes beginning array up to but not including the middle index 30 | let leftArray = mergeSort(Array(arr[..(_ leftArray: [T], _ rightArray: [T]) -> [T] { 39 | var leftIndex = 0 40 | var rightIndex = 0 41 | var resultsArray = [T]() 42 | 43 | while leftIndex < leftArray.count && rightIndex < rightArray.count { 44 | let leftElement = leftArray[leftIndex] 45 | let rightElement = rightArray[rightIndex] 46 | 47 | // compare 48 | if leftElement < rightElement { 49 | resultsArray.append(leftElement) 50 | leftIndex += 1 51 | } else if leftElement > rightElement { 52 | resultsArray.append(rightElement) 53 | rightIndex += 1 54 | } else { // both equal, append both to the results array 55 | resultsArray.append(leftElement) 56 | leftIndex += 1 57 | resultsArray.append(rightElement) 58 | rightIndex += 1 59 | } 60 | } 61 | 62 | // out here append elements remaining in left, right arrays 63 | if leftIndex < leftArray.count { 64 | resultsArray.append(contentsOf: leftArray[leftIndex...]) 65 | } 66 | 67 | if rightIndex < rightArray.count { 68 | resultsArray.append(contentsOf: rightArray[rightIndex...]) 69 | } 70 | 71 | return resultsArray 72 | } 73 | 74 | let list = [12, 8, 29, -100, 0, 234] 75 | let sortedList = mergeSort(list) 76 | print(sortedList) // [-100, 0, 8, 12, 29, 234] 77 | 78 | -------------------------------------------------------------------------------- /Unit5/MergeSort.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit5/Queues.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Queues: is a abstract data type that is a FIFO structure (meaning: first object added is the first object to be removed from the data structure) 4 | 5 | // methods of a Queue: 6 | 7 | // enqueue: add item to the back of the queue 8 | 9 | // dequeue: remove item from the front of the queue 10 | 11 | // properties: count, isEmpty, peek 12 | 13 | struct Queue { 14 | // implementing a queue using an array 15 | private var elements = [T]() 16 | // private var linkedList = LinkedList() 17 | // private var stack = [Int]() 18 | 19 | public var isEmpty: Bool { 20 | return elements.isEmpty 21 | } 22 | 23 | public var count: Int { 24 | return elements.count 25 | } 26 | 27 | // returns the items at the front of the queue, doen not 28 | // remove it 29 | public var peek: T? { 30 | return elements.first 31 | } 32 | 33 | // add item to elements 34 | public mutating func enqueue(_ item: T) { 35 | elements.append(item) 36 | } 37 | 38 | // remove item from front of elements array 39 | public mutating func dequeue() -> T? { 40 | guard !isEmpty else { return nil } 41 | return elements.removeFirst() 42 | } 43 | } 44 | 45 | var queue = Queue() 46 | queue.enqueue("Mel") 47 | queue.enqueue("Kelby") 48 | queue.enqueue("Oscar") 49 | 50 | print("\(queue.peek ?? "") is at the front of the line") 51 | 52 | queue.dequeue() 53 | 54 | print("fellows left in line are \(queue)") 55 | 56 | queue.enqueue("Eric") 57 | 58 | print("there are \(queue.count) fellows on line") 59 | 60 | // iterate through a queue structure 61 | 62 | var queueCopy = queue 63 | 64 | while let value = queueCopy.dequeue() { 65 | print("fellow: \(value)") 66 | } 67 | 68 | print("there are \(queueCopy.count) fellows left in queueCopy") 69 | 70 | -------------------------------------------------------------------------------- /Unit5/Queues.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit5/QuickSort.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // Quick Sort implementation using Lomuto's Partitioning algorithm 4 | // Quick Sort uses a pivot in our example we use the last element (Lomuto's Partitioning) as the pivot 5 | // Using this pivot we split the array to the left of the pivot and to the right of the pivot 6 | // example 10, -9, 0, -11, (pivot is 13) , 80 7 | // Quick Sort uses divide and conquer approach to solve the sorting algorithm, divide and conquer is spliting the problem in half on every interation (or recursive call) 8 | // runtime: O(n log n) 9 | 10 | // implement Lomoto's partitioning 11 | 12 | // return new index which we will use as the pivot to partition 13 | // the array into a left and right side array 14 | func lomutoPartition(_ arr: inout [Int], low: Int, high: Int) -> Int { 15 | let pivot = arr[high] // using last element in array 16 | var i = low 17 | 18 | // iterate through the array using j variable as our marker 19 | for j in low.. O(n ^ 2) 54 | if arr[j] < arr[j - 1] { 55 | arr.swapAt(j, j - 1) 56 | } 57 | } 58 | } 59 | } 60 | var bubbleList = [80, 10, -9, 0, -11, 13, 80, 10, -9, 0, -11, 13, 80, 10, -9, 0, -11, 13, 78, -100] 61 | bubbleSort(&bubbleList) 62 | print(bubbleList) 63 | -------------------------------------------------------------------------------- /Unit5/QuickSort.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit5/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexpaul/Lecture-Resources/f5f6712fb3caa0d3931a88415d023d24b2b87c5c/Unit5/README.md -------------------------------------------------------------------------------- /Unit6/Contiguous-Array-LeetCode.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | func findMaxLenght(_ nums: [Int]) -> Int { 4 | var count = 0 5 | var maxLength = 0 6 | var freqDict = [Int: Int]() // [count: index] 7 | // if we have seen the count before we are looking at the contiguous subarray 8 | for (currentIndex, num) in nums.enumerated() { 9 | if num == 0 { 10 | count -= 1 11 | } else { 12 | count += 1 13 | } 14 | // keep track of seen counts and indices 15 | if let firstSeenIndex = freqDict[count] { 16 | maxLength = max(maxLength, currentIndex - firstSeenIndex) 17 | } else { 18 | freqDict[count] = currentIndex // first time we have seen this count 19 | } 20 | } 21 | return maxLength 22 | } 23 | 24 | findMaxLenght([0, 0, 1, 0, 1, 0]) // 4 25 | 26 | // 9 = max(5, 9) 27 | 28 | -------------------------------------------------------------------------------- /Unit6/Contiguous-Array-LeetCode.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit6/README.md: -------------------------------------------------------------------------------- 1 | ## Unit 6 2 | 3 | ## Repos 4 | 5 | [AVFounddation - MediaFeed](https://github.com/alexpaul/AVFoundation-MediaFeed) 6 | -------------------------------------------------------------------------------- /Unit7/BinarySearchTree.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class TreeNode { 4 | var left: TreeNode? 5 | var right: TreeNode? 6 | var value: Int 7 | init(_ value: Int) { 8 | self.value = value 9 | } 10 | } 11 | 12 | extension TreeNode { 13 | func insert(_ newValue: Int) { 14 | if newValue < value { // go left if newValue is greater than current node's value 15 | if left != nil { 16 | // keep calling insert recursively on left node 17 | left!.insert(newValue) 18 | } else { 19 | // create a new node and attach as left child 20 | left = TreeNode(newValue) 21 | } 22 | } else { // go right 23 | if right != nil { 24 | // call insert recursively on right child 25 | right!.insert(newValue) 26 | } else { 27 | right = TreeNode(newValue) 28 | } 29 | } 30 | } 31 | 32 | // search logic 33 | /* 34 | 1. check current node to verify if target value 35 | 2. if target value is less than current node value then search left 36 | 3. else search right 37 | */ 38 | 39 | func contains(_ targetValue: Int) -> Bool { 40 | // 1. check current node to verify if target value 41 | if targetValue == value { // equal to current node value 42 | return true 43 | } 44 | // 2. if target value is less than current node value then search left 45 | if targetValue < value { // search left 46 | if left != nil { 47 | // call contains recursively on left child 48 | return left!.contains(targetValue) 49 | } else { 50 | return false 51 | } 52 | } else { // search right 53 | if right != nil { 54 | // visit recursively 55 | return right!.contains(targetValue) 56 | } else { 57 | return false 58 | } 59 | } 60 | } 61 | 62 | func inOrderTraversal() { 63 | left?.inOrderTraversal() // vist left 64 | print("\(value)", terminator: " ") // visit current node 65 | right?.inOrderTraversal() // visit right 66 | } 67 | } 68 | 69 | 70 | // write a function that takes a tree and a given value 71 | // and delete the value and returns the modified tree 72 | 73 | func delete(_ root: TreeNode?, _ targetValue: Int) -> TreeNode? { 74 | guard let _ = root else { 75 | return nil 76 | } 77 | 78 | // we need to modify root so we will make it mutable 79 | var root = root 80 | 81 | // check the target value to find out if we are looking 82 | // left or right 83 | if targetValue < root!.value { // left 84 | root?.left = delete(root?.left, targetValue) 85 | } else if targetValue > root!.value { // right 86 | root?.right = delete(root?.right, targetValue) 87 | } else { // we've found the node to be deleted 88 | // scenario 1: no children 89 | if root?.right == nil && root?.left == nil { 90 | root = nil 91 | return root 92 | } 93 | 94 | // scenario 2: one child 95 | else if root?.left == nil { 96 | root = root?.right 97 | } 98 | else if root?.right == nil { 99 | root = root?.left 100 | } 101 | else { 102 | // scenario 3: both children 103 | // steps to delete a node where it has both children 104 | // 1. get minimum value of right subtree 105 | let tempNode = minimum(root?.right) 106 | 107 | // 2. replace value at root with minimum value 108 | 109 | root?.value = tempNode!.value 110 | 111 | // 3. delete minimum value 112 | root?.right = delete(root?.right, tempNode!.value) 113 | } 114 | } 115 | return root // represents the modified tree after deletion 116 | } 117 | 118 | // helper function to find the minimum value (node) 119 | // of a binary search tree 120 | func minimum(_ root: TreeNode?) -> TreeNode? { 121 | var currentNode = root 122 | while let next = currentNode?.left { 123 | currentNode = next 124 | } 125 | return currentNode 126 | } 127 | 128 | 129 | /* 130 | 12 131 | / \ 132 | 5 32 133 | */ 134 | 135 | 136 | // 5 12 32 137 | 138 | 139 | let rootNode = TreeNode(12) 140 | rootNode.insert(5) 141 | rootNode.insert(32) 142 | rootNode.insert(3) 143 | rootNode.insert(11) 144 | rootNode.insert(15) 145 | rootNode.insert(13) 146 | rootNode.insert(21) 147 | rootNode.insert(40) 148 | rootNode.insert(50) 149 | rootNode.insert(35) 150 | rootNode.insert(65) 151 | 152 | 153 | // if using in-order traversal, the print order of the elements 154 | // is guaranteed to be ascending... 155 | rootNode.inOrderTraversal() // 5 12 32 -> binary search tree 156 | print() 157 | 158 | delete(rootNode, 32) // scenario 3: both children 159 | 160 | rootNode.inOrderTraversal() 161 | print() 162 | 163 | delete(rootNode, 50) // scenario 2: one child 164 | rootNode.inOrderTraversal() 165 | print() 166 | 167 | delete(rootNode, 65) // scenario 1: no children 168 | rootNode.inOrderTraversal() 169 | 170 | -------------------------------------------------------------------------------- /Unit7/BinarySearchTree.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit7/DoublyLinkedList.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // helper method to help while testing different methods below 4 | func example(_ str: String, action: () -> ()) { // "testing append" 5 | print(str) 6 | action() 7 | print() 8 | } 9 | 10 | // singly linked node 11 | class SLNode { 12 | var next: DLNode? 13 | var value: Int 14 | init(_ value: Int) { 15 | self.value = value 16 | } 17 | } 18 | 19 | class SinglyLinkedList { 20 | private var head: SLNode? 21 | private var tail: SLNode? 22 | 23 | func append() { 24 | 25 | } 26 | } 27 | 28 | // implement (Doubly Linked Node) class 29 | class DLNode { // hint: conform to Equatable 30 | var next: DLNode? 31 | weak var previous: DLNode? 32 | var value: Int 33 | init(_ value: Int) { 34 | self.value = value 35 | } 36 | } 37 | 38 | // implement (Doubly Linked List) class 39 | 40 | class DoublyLinkedList { 41 | private (set) var head: DLNode? 42 | private (set) var tail: DLNode? 43 | 44 | func append(_ value: Int) { 45 | // 1 46 | // create a new node 47 | let newNode = DLNode(value) 48 | 49 | // 2 50 | // guard against tail being nil i.e (list being empty) 51 | guard let lastNode = tail else { 52 | // 3 53 | // append to empty list 54 | head = newNode 55 | tail = newNode 56 | return 57 | } 58 | // list has values 59 | // 4 60 | lastNode.next = newNode 61 | // 5 62 | newNode.previous = lastNode 63 | // 6 64 | tail = newNode 65 | } 66 | 67 | func printForward() { // 5 -> 1 -> 10 -> nil 68 | var currentNode = head 69 | while let node = currentNode { 70 | print(node.value, terminator: " -> ") 71 | currentNode = node.next 72 | } 73 | print("nil") 74 | } 75 | 76 | func printReverse() { // 10 -> 1 -> 5 -> nil 77 | var currentNode = tail 78 | while let node = currentNode { 79 | print(node.value, terminator: " -> ") 80 | currentNode = node.previous 81 | } 82 | print("nil") 83 | } 84 | 85 | // TODO: 1 86 | // prepend - add a node to the front of the list 87 | // existing list: 10 -> 7 -> 5 -> nil 88 | // add value 8 89 | // new list should be: 8 -> 10 -> 7 -> 5 -> nil 90 | 91 | // TODO: 2 92 | // delete head 93 | // exiting list: 8 -> 10 -> 7 -> 5 -> nil 94 | // deleteHead() 95 | // new list: 10 -> 7 -> 5 -> nil 96 | 97 | 98 | // TODO: 3 99 | // delete tail 100 | // exiting list: 8 -> 10 -> 7 -> 5 -> nil 101 | // new list: 8 -> 10 -> 7 -> nil 102 | 103 | // TODO: 4 104 | // insert value after node 105 | // exiting list: 8 -> 10 -> 7 -> 5 -> nil 106 | // insert(list.head.next, 3) 107 | // new list: 8 -> 10 -> 3 -> 7 -> 5 -> nil 108 | func insertNode(_ node: DLNode, value: Int) {} 109 | 110 | // TODO: 5 111 | // delete node at index 112 | // exiting list: 8 -> 10 -> 7 -> 5 -> nil 113 | // delete(atIndex: 0) 114 | // new list: 10 -> 7 -> 5 -> nil 115 | } 116 | 117 | let list = DoublyLinkedList() 118 | 119 | example("testing append") { 120 | list.append(10) 121 | list.append(7) 122 | list.append(5) 123 | list.printForward() // 10 -> 7 -> 5 -> nil 124 | } 125 | 126 | example("print reverse") { 127 | list.printReverse() 128 | } 129 | 130 | example("insert after") { 131 | list.insertNode(list.head!.next!, value: 3) 132 | } 133 | -------------------------------------------------------------------------------- /Unit7/DoublyLinkedList.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit7/HashTable.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | // 4 | 5 | var buckets = Array(repeating: 0, count: 2) 6 | 7 | // hashValue is a built-in hash function 8 | // returns a hash value for a key 9 | // it's possible to get a negative number 10 | // how can we fix this - take the absolute value of the operation 11 | let alexIndex = abs("Alex".hashValue % buckets.count) 12 | let brendonIndex = abs("Brendon".hashValue % buckets.count) 13 | let ahadIndex = abs("Ahad".hashValue % buckets.count) 14 | let tanyaIndex = abs("Tanya".hashValue % buckets.count) 15 | 16 | print("goes in \(alexIndex) index") 17 | print("goes in \(brendonIndex) index") 18 | print("goes in \(ahadIndex) index") 19 | print("goes in \(tanyaIndex) index") 20 | 21 | 22 | var dict = [String: Int]() 23 | dict["Sweden"] = 1 24 | 25 | 26 | // Implemenet Hash Table 27 | 28 | // e.g HashTable(capacity: 4) 29 | struct HashTable { 30 | // (key, value) e.g "Tiffany": 21 31 | private typealias Element = (key: Key, value: Value) 32 | 33 | // collision resolution being implemented using chaining 34 | private typealias Bucket = [Element] // this represent the chains 35 | 36 | private var buckets: [Bucket] 37 | 38 | private (set) var count = 0 // getter is public, setter is private 39 | 40 | init(capacity: Int) { 41 | assert(capacity > 0) // crashes if not 42 | buckets = Array(repeating: [], count: capacity) 43 | // e.g buckets = [[], [], [(key: "Tiffany": 21)], []] 44 | } 45 | 46 | // method to return index where key will be stored 47 | func index(forKey key: Key) -> Int { 48 | return abs(key.hashValue % buckets.count) 49 | } 50 | 51 | // method to search for a value given a key 52 | func value(forKey key: Key) -> Value? { 53 | let index = self.index(forKey: key) 54 | for element in buckets[index] { 55 | if element.key == key { 56 | return element.value 57 | } 58 | } 59 | return nil 60 | } 61 | 62 | // method to update a value for a given key 63 | mutating func update(value: Value, forKey key: Key) -> Value? { 64 | let index = self.index(forKey: key) 65 | for (i, element) in buckets[index].enumerated() { 66 | if element.key == key { 67 | let oldValue = element.value 68 | // update the current value 69 | buckets[index][i].value = value 70 | return oldValue 71 | } 72 | } 73 | // we get here if there's no value 74 | buckets[index].append((key: key, value: value)) 75 | count += 1 76 | return nil // to signify there wasn't an existing value 77 | } 78 | 79 | // method to remove an element at a given key 80 | mutating func removeValue(forKey key: Key) -> Value? { 81 | let index = self.index(forKey: key) 82 | for (i, element) in buckets[index].enumerated() { 83 | if element.key == key { 84 | buckets[index].remove(at: i) 85 | count -= 1 86 | return element.value 87 | } 88 | } 89 | return nil 90 | } 91 | 92 | // we can have multiple subscipt methods taking in varied arguments 93 | subscript(key: Key) -> Value? { 94 | get { 95 | return value(forKey: key) 96 | } set { 97 | if let value = newValue { 98 | update(value: value, forKey: key) 99 | } else { 100 | removeValue(forKey: key) 101 | } 102 | } 103 | } 104 | } 105 | 106 | // test the hash table 107 | 108 | // key is String and the value is an Int and capacity is 4 109 | var hashTable = HashTable(capacity: 4) 110 | 111 | hashTable["Tiffany"] = 21 112 | //hashTable.update(value: 21, forKey: "Tiffany") 113 | hashTable.update(value: 25, forKey: "Eric") 114 | 115 | hashTable.count 116 | 117 | print(hashTable) 118 | 119 | //hashTable.removeValue(forKey: "Tiffany") 120 | hashTable["Tiffany"] = nil 121 | 122 | print(hashTable.count) // 1 123 | 124 | print(hashTable) 125 | 126 | // optional binding 127 | if let age = hashTable["Alex"] { 128 | print("\(age) exist") 129 | } else { 130 | print("does not exist") 131 | } 132 | 133 | // nil coalescing 134 | let age = hashTable["Cameron"] ?? 100 135 | print(age) 136 | -------------------------------------------------------------------------------- /Unit7/HashTable.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Unit7/README.md: -------------------------------------------------------------------------------- 1 | ## Unit 7 2 | 3 | ## Repos 4 | 5 | 1. [Firebase Asynchronous Testing](https://github.com/alexpaul/Firebase-Asynchronous-Testing) 6 | 2. [Code Coverage](https://github.com/alexpaul/CodeCoverage.git) 7 | 3. [Introduction to Diffable Data Source - Countdown app](https://github.com/alexpaul/Diffable-Data-Source) 8 | 4. [Diffable Data Source - ShoppingList app](https://github.com/alexpaul/Diffable-Data-Source/tree/master/ShoppingList) 9 | 5. [Firebase Security Rules](https://github.com/alexpaul/Firebase-Security-Rules) 10 | --------------------------------------------------------------------------------