Last active
June 5, 2025 01:57
-
-
Save billbonney/0968920dc29b7d0a677f to your computer and use it in GitHub Desktop.
Revisions
-
billbonney revised this gist
Jul 27, 2023 . 1 changed file with 68 additions and 60 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,6 @@ // // Copyright © 2023 Bill Bonney. All rights reserved. // // The Swift Programming Language: Swift by Tutorials (solutions) // Author: Bill Bonney <billbonney (at) communistech.com> // @@ -9,9 +12,9 @@ // // NOTE: Not all code is identical (since I was tinkering, but should help) import Cocoa // This is all 'pure' swift, no Math libs are used. Uncomment if you want to see the difference // UPDATED to Swift 5: Just because after a decade it seems appropriate! // // Simple Values @@ -148,7 +151,7 @@ while n < 100 { n var m = 2 repeat { m = m * 2 } while m < 100 m @@ -167,7 +170,7 @@ for i in 1...10 { // NOTE: a count from 1 to 10 firstForLoop1 var secondForLoop = 0 for i in 1..<10 { secondForLoop += i } secondForLoop @@ -182,8 +185,8 @@ func greet(name:String, day:String, lunch:String) -> String { return "Helllo \(name), today is \(day) and lunch will be \(lunch)" } greet(name: "Fred", day: "Monday", lunch: "eggs") greet(name: "Wally", day: "Thursday", lunch: "surf'n'turf") func getGasPrices() -> (Double,Double,Double) { return (1.35,145,155) // Note: Prices are in (CAD$/L) @@ -200,7 +203,7 @@ func sumOf(numbers: Int...) -> Int { } sumOf() sumOf(numbers: 42,597,12) // Experiment: Create a function that creates the average of the args @@ -212,7 +215,7 @@ func average(numbers:Double...) -> Double { return sum/Double(numbers.count) } average(numbers: 10.0,20.0,30.0) func returnFifteen() -> Int { var y = 10 @@ -225,7 +228,7 @@ func returnFifteen() -> Int { returnFifteen() func makeIncrementer() -> ((Int) -> Int) { func addOne(number: Int) -> Int { return 1+number } @@ -235,7 +238,7 @@ func makeIncrementer() -> (Int -> Int) { var increment = makeIncrementer() increment(7) func hasAnyMatches(list: [Int], condition:(Int) -> Bool) -> Bool { for item in list { if condition(item){ return true; @@ -245,12 +248,12 @@ func hasAnyMatches(list: [Int], condition:Int -> Bool) -> Bool { } func lessThanTen(number:Int) -> Bool { print("number is \(number)") return number < 10 } var numbers = [ 10, 19, 7, 12] hasAnyMatches(list: numbers, condition: lessThanTen) numbers.map({ (number: Int) -> Int in @@ -271,7 +274,7 @@ numbers.map({ let mappedNumbers = numbers.map({ number in 3 * number }) mappedNumbers let sortedNumbers = numbers.sorted { $0 > $1 } sortedNumbers // Objects and Classes @@ -415,7 +418,7 @@ class Counter { } var counter = Counter() counter.incrementBy(amount: 2, numberOfTimes: 7) let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") // NOTE: Try also @@ -430,7 +433,17 @@ sideLength // Enumerations and Structures // enum Rank: Int, Sequence, IteratorProtocol { mutating func next() -> Rank? { if self.rawValue > Self.King.rawValue { return nil } else { return Rank(rawValue: self.rawValue + 1) } } typealias Element = Rank case Ace = 1 case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten case Jack, Queen, King @@ -445,13 +458,13 @@ enum Rank: Int { case .King: return "king" default: return String(self.rawValue) } } } let ace = Rank.Ace let aceRawValue = ace.rawValue // Exepriment: Write a function to compare two Rank values by comparing their raw values // NOTE: got a little carried away ;) @@ -461,19 +474,19 @@ let leftHand = Rank.King var snap = 0 var handResult: String if rightHand.rawValue < leftHand.rawValue { handResult = "Left Hand Wins!" } else if rightHand.rawValue > leftHand.rawValue { handResult = "Right Hand Wins!" } else { handResult = "Draw!" } if let convertedRank = Rank(rawValue: 3){ let threeDescription = convertedRank.simpleDescritption() } // NOTE: I think choosing a picture card demonstrates this much better if let convertedRank = Rank(rawValue: 1){ let threeDescription = convertedRank.simpleDescritption() } @@ -509,7 +522,18 @@ let heartsDescription = hearts.simpleDescription() let card = Suit.Spades card.color() struct Card: Sequence, IteratorProtocol { mutating func next() -> Card? { guard let nextRank = rank.next() else { return nil } return Card(rank: nextRank, suit: self.suit) } typealias Element = Card var rank: Rank var suit: Suit @@ -529,7 +553,7 @@ func newPack() -> [Card] { for suit in suits{ for i in 1...12 { pack += Card(rank: Rank(rawValue: i)!, suit: suit) } } return pack @@ -573,9 +597,7 @@ case let .DaylightSavingsInEffect(state): // protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } @@ -627,13 +649,13 @@ enum SimpleEnum : ExampleProtocol { mutating func adjust() { switch self { case .One: self = Self.OneOne case .Two: self = Self.TwoTwo case .OneOne, .OneTwo: self = Self.One case .TwoOne, .TwoTwo: self = Self.Two } } } @@ -662,32 +684,33 @@ extension Int: ExampleProtocol { return "The number \(self)" } mutating func adjust() { self += 42 } } 7.simpleDescription var newInt = 8 newInt.adjust() extension Double { var abs: Double { get{ if (self.sign == .minus){ // demonstrates that doubles are not POT in swift. return self * -1 } else { return self } } } } var myDouble = -20.7 myDouble.abs let value = abs(myDouble) // uncomment if using import cocoa let protocolValue: ExampleProtocol = a protocolValue.simpleDescription @@ -697,32 +720,17 @@ protocolValue.simpleDescription // Generics // func repeatThis<ItemType>(item: ItemType, times: Int) -> [ItemType] { var result = [ItemType]() for _ in 0 ..< times { result.append(item) } return result } let result = repeatThis(item: "knock", times: 4) print(result) print("end") -
billbonney renamed this gist
Oct 21, 2014 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
billbonney revised this gist
Sep 17, 2014 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,6 +5,8 @@ // This should allow you to play with the code and see behaviours, and help // solve any paticulars you get stuck on when doing the Experiments. // // Please feel free to comment on any part, I am by no means an expert in Swift ;-) // // NOTE: Not all code is identical (since I was tinkering, but should help) // import Cocoa // This is all 'pure' swift, no Math libs are used. Uncomment if you want to see the difference -
billbonney created this gist
Sep 17, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,726 @@ // The Swift Programming Language: Swift by Tutorials (solutions) // Author: Bill Bonney <billbonney (at) communistech.com> // // This is all the code in The Swift Tour section in the Apple Book on Swift. // This should allow you to play with the code and see behaviours, and help // solve any paticulars you get stuck on when doing the Experiments. // // NOTE: Not all code is identical (since I was tinkering, but should help) // import Cocoa // This is all 'pure' swift, no Math libs are used. Uncomment if you want to see the difference println("Hello Mum!") // // Simple Values // var myVariable = 42 myVariable = 50 let myConstant = 42 let implicit = 70 let implicitDoube = 70.0 let explicitDouble: Double = 20.3 // Experiment: Constant Float of value 4 // Note: I made it 20.3 to show the general rounding errors in floats // SIDENOTE: always use doubles on 64Bit systems ;) let explicitFloat: Float = 20.3 let label = "The width is " let width = 94 let widthLabel = label + String(width) // Experiment: Try removing the String conversion // let widthLabel = label + width // (uncomment as it will error otherwise) let apples = 3 let oranges = 5 let appleSummary = "I have \(apples) apples." let orangeSummary = "I have \(oranges) oranges." // Experiment: Use \() notation to include a floating point calculation let greetingPeople = "Hello People \(3 * 9)" var shoppingList = ["redfish", "yellowfish", "bluefish"] shoppingList[1] var occupations = [ "Malcolm": "capitan", "Kaylee": "mechanic" ] occupations["John"] = "domestic engineer" let emptyArray = [String()] let emptyDictionary = Dictionary<String,Float>() shoppingList = [] // // Control Flow // let individualScores = [75, 43, 103, 87, 12] var teamScore = 0 for score in individualScores { if score > 50 { teamScore += 3 } else { teamScore += 1 } } teamScore var optionalString: String? = "Hello" optionalString == nil var optionalName: String? = "Fred Shed" // Experiment: change optional name to nil // NOTE: Comment out line 66 and try.. // var optionalName: String? = nil // OR // var optionalName: String? var greeting = "Hello!" if let name = optionalName { greeting = "Hello \(name)" } else { greeting = "Who goes there?" } greeting let vegetable = "red pepper" switch vegetable { case "celery": let vegetableComment = "Add some raisins" case "cucumber","watercress": let vegetableComment = "That would make a nice cucumber sarnie." case let x where x.hasSuffix("pepper"): // Whah: Need to read up on this mystery x. let vegetableComment = "Is it spicy \(x)?" default: let vegetableComment = "Everything tastes good in soup" } //Experiment: Remove default case (see above) let interestingNumbers = [ "Pirme": [2,3,5,7,11,13], "Fibonacci": [1,1,2,3,5,8], "Square": [1, 4, 9, 16, 25], ] // Experiment: Add another variable to keep track of which kind of number was the largest. // NOTE: Also added code for the smallest var largest = 0 var largestType: String? var smallestType: String? var smallest = Int.max for (kind, numbers) in interestingNumbers { for number in numbers { if number > largest { largest = number largestType = kind } else if number < smallest { smallest = number smallestType = kind } } } largest largestType smallest smallestType var n = 2 while n < 100 { n = n * 2 } n var m = 2 do { m = m * 2 } while m < 100 m var firstForLoop = 0 for i in 0..<10 { firstForLoop += i } firstForLoop // Test to try a 1 to 10 count (sometimes useful to start at 1) var firstForLoop1 = 0 for i in 1...10 { // NOTE: a count from 1 to 10 firstForLoop1 += i } firstForLoop1 var secondForLoop = 0 for var i=0; i < 10; ++i { secondForLoop += i } secondForLoop // // Functions and Closures // // Experiment: Remove Day parameter and add lunch special greeting // NOTE: I just added lunch the param (D'oh must follow instructions) func greet(name:String, day:String, lunch:String) -> String { return "Helllo \(name), today is \(day) and lunch will be \(lunch)" } greet("Fred", "Monday", "eggs") greet("Wally", "Thursday", "surf'n'turf") func getGasPrices() -> (Double,Double,Double) { return (1.35,145,155) // Note: Prices are in (CAD$/L) } getGasPrices() func sumOf(numbers: Int...) -> Int { var sum = 0 for number in numbers { sum += number } return sum } sumOf() sumOf(42,597,12) // Experiment: Create a function that creates the average of the args func average(numbers:Double...) -> Double { var sum = 0.0 for number in numbers { sum += number } return sum/Double(numbers.count) } average(10.0,20.0,30.0) func returnFifteen() -> Int { var y = 10 func add() { y += 5 } add() return y } returnFifteen() func makeIncrementer() -> (Int -> Int) { func addOne(number: Int) -> Int { return 1+number } return addOne } var increment = makeIncrementer() increment(7) func hasAnyMatches(list: [Int], condition:Int -> Bool) -> Bool { for item in list { if condition(item){ return true; } } return false } func lessThanTen(number:Int) -> Bool { println("number is \(number)") return number < 10 } var numbers = [ 10, 19, 7, 12] hasAnyMatches(numbers, lessThanTen) numbers.map({ (number: Int) -> Int in let result = 3*number return result }) // Experiment: Show odd numbers as 0 (zero) // Only show even numbers, odd are zero'd numbers.map({ (number: Int) -> Int in if (number % 2) == 0 { return number } return 0 }) let mappedNumbers = numbers.map({ number in 3 * number }) mappedNumbers let sortedNumbers = sorted(numbers){ $0 > $1 } // Note: confused :-/ sortedNumbers // Objects and Classes class Shape { var numberOfSides = 0; func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } } var shape = Shape() shape.numberOfSides = 7 var shapeDescription = shape.simpleDescription() class NamedShape { var numberOfSides: Int = 0 var name: String init(name:String) { self.name = name } func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } } class Square: NamedShape { var sideLength: Double init(sideLength: Double, name: String){ self.sideLength = sideLength super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength //NOTE: Guessing ^2 is a import math function } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)" } } let test = Square(sideLength: 5.2, name: "my test square") test.area() test.simpleDescription() // Experiment: Make another subclass Circle class Circle : NamedShape { var radius: Double init(radius:Double, name: String){ self.radius = radius super.init(name: name) numberOfSides = 1 } func area() -> Double { return 3.14592 * (radius*radius) // return M_PI * pow(radius, 2) // uncomment when using import cocoa } override func simpleDescription() -> String { return "A circle with a radius of \(radius)" } } var testCircle = Circle(radius: 2, name: "my circle") testCircle.area() testCircle.simpleDescription() class EquilateralTriangle : NamedShape { var sideLength: Double = 0.0 init(sideLength: Double, name: String){ self.sideLength = sideLength super.init(name: name) numberOfSides = 3 } var perimeter: Double { get { return 3.0 * sideLength } set(newPerimeter) { sideLength = newPerimeter / 3.0 } } override func simpleDescription() -> String { return "An equilateral triangle with sides of length \(sideLength)" } } var triangle = EquilateralTriangle(sideLength:3.1, name:"a Triangle") triangle.sideLength triangle.perimeter triangle.perimeter = 9.9 triangle.sideLength triangle.perimeter class TriangleAndSquare { var triangle: EquilateralTriangle { willSet { square.sideLength = newValue.sideLength } } var square: Square{ willSet { triangle.sideLength = newValue.sideLength } } init(size: Double, name: String){ square = Square(sideLength: size, name: name) triangle = EquilateralTriangle(sideLength: size, name: name) } } var triangleAndSquare = TriangleAndSquare(size: 10, name:"another test shape") triangleAndSquare.square.sideLength triangleAndSquare.triangle.sideLength triangleAndSquare.square = Square(sideLength: 50, name: "larger square") triangleAndSquare.triangle.sideLength class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes times: Int){ count += amount * times } } var counter = Counter() counter.incrementBy(2, numberOfTimes: 7) let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") // NOTE: Try also //let optionalSquare: Square? = nil // OR //let optionalSquare: Square? let sideLength = optionalSquare?.sideLength sideLength // // Enumerations and Structures // enum Rank: Int { case Ace = 1 case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten case Jack, Queen, King func simpleDescritption() -> String { switch self { case .Ace: return "ace" case .Jack: return "jack" case .Queen: return "queen" case .King: return "king" default: return String(self.toRaw()) } } } let ace = Rank.Ace let aceRawValue = ace.toRaw() // Exepriment: Write a function to compare two Rank values by comparing their raw values // NOTE: got a little carried away ;) let rightHand = Rank.King let leftHand = Rank.King var snap = 0 var handResult: String if rightHand.toRaw() < leftHand.toRaw() { handResult = "Left Hand Wins!" } else if rightHand.toRaw() > leftHand.toRaw() { handResult = "Right Hand Wins!" } else { handResult = "Draw!" } if let convertedRank = Rank.fromRaw(3){ let threeDescription = convertedRank.simpleDescritption() } // NOTE: I think choosing a picture card demonstrates this much better if let convertedRank = Rank.fromRaw(1){ let threeDescription = convertedRank.simpleDescritption() } enum Suit { case Spades, Hearts, Diamonds, Clubs func simpleDescription() -> String { switch self { case .Spades: return "spades" case .Hearts: return "hearts" case .Diamonds: return "diamonds" case .Clubs: return "clubs" } } // Experiment: Add a color method to Suit to return "red" or "black" // NOTE: new feature is to group values in one case statement func color() -> String { switch self { case .Hearts, .Diamonds: return "red" case .Clubs, .Spades: return "black" } } } let hearts = Suit.Hearts let heartsDescription = hearts.simpleDescription() let card = Suit.Spades card.color() struct Card { var rank: Rank var suit: Suit func simpleDescription() -> String { return "The \(rank.simpleDescritption()) of \(suit.simpleDescription())" } } let threeOfSpades = Card(rank: .Three, suit: .Spades) let thresOfSpadesDescritpion = threeOfSpades.simpleDescription() // Experiment: Add a method to create a full deck to Card (Why to card and not separate) // NOTE: This is a method to create a pack, but it's "not added to card" (?) func newPack() -> [Card] { var pack:[Card] = [] var suits = [Suit.Spades, Suit.Hearts, Suit.Diamonds, Suit.Spades] for suit in suits{ for i in 1...12 { pack += Card(rank: Rank.fromRaw(i)!, suit: suit) } } return pack } let pack = newPack() // Experiment: Add third case to ServerResponse and to the switch enum ServerResponse { case Result(String,String) case Error(String) case DaylightSavingsInEffect(Bool) } let success = ServerResponse.Result("6:00am", "8:09pm") let failure = ServerResponse.Error("Out of cheese.") let daylightsavings = ServerResponse.DaylightSavingsInEffect(true) var servResponse = success // NOTE: uncomment the lines below to see how the switch works. //var servResponse = failure //var servResponse = daylightsavings switch servResponse { case let .Result(sunrise, sunset): let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)." case let .Error(error): let serverResponse = "Failure... \(error)" case let .DaylightSavingsInEffect(state): var serverRespsonse: String if (state){ serverRespsonse = "Daylight Savings in effect." } else { serverRespsonse = "Standard Time" } } // // Protocols and Extensions // protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } class SimpleClass: ExampleProtocol { var simpleDescription: String = "A very simple class." var anotherProperty: Int = 69105 func adjust() { simpleDescription += " now 100% adjusted." } } var a = SimpleClass() a.adjust() let aDescription = a.simpleDescription struct SimpleStructure: ExampleProtocol { var simpleDescription: String = "A simple structure" mutating func adjust() { simpleDescription += "(adjusted)" } } var b = SimpleStructure() b.adjust() let bDescription = b.simpleDescription //Experiment: Add ExampleProtocol to an enummeration enum SimpleEnum : ExampleProtocol { case One, Two, OneOne, OneTwo, TwoOne, TwoTwo var simpleDescription: String { get { switch self { case .One: return "one" case .Two: return "two" case .OneOne: return "oneone" case .OneTwo: return "onetwo" case .TwoOne: return "twoone" case .TwoTwo: return "twotwo" } } } mutating func adjust() { switch self { case .One: self = OneOne case .Two: self = TwoTwo case .OneOne, .OneTwo: self = One case .TwoOne, .TwoTwo: self = Two } } } // Below is some examples of using the enum conforming to a protocol // and it looks quite confuing, but managing a statemachine type sequence // it could become very powerful in some applications. var c = SimpleEnum.One var enumState = c.simpleDescription c.adjust() var enumNextDescritption = c.simpleDescription c.adjust() enumNextDescritption = c.simpleDescription c = SimpleEnum.TwoOne enumState = c.simpleDescription c.adjust() enumNextDescritption = c.simpleDescription c.adjust() enumNextDescritption = c.simpleDescription // Extensions extension Int: ExampleProtocol { var simpleDescription: String { return "The number \(self)" } mutating func adjust() { // NOTE: Have no idea how this works see below. self += 42 } } 7.simpleDescription var newInt = 8 var newNumber = newInt.adjust // It just shows function in the sidebar??? extension Double { var abs: Double { get{ if (self.isSignMinus){ // demonstrates that doubles are not POT in swift. return self * -1 } else { return self } // return fabs(self) // uncomment if using import cocoa } } } var myDouble = -20.7 myDouble.abs let protocolValue: ExampleProtocol = a protocolValue.simpleDescription //protocolValue.anotherProperty // Uncomment to see the error // // Generics // func repeat<ItemType>(item: ItemType, times: Int) -> [ItemType] { var result = [ItemType]() for i in 0 ..< times { result += item } return result } repeat("knock", 4)