With this assignment you will demonstrate:
Please read:
You will be adding to the private GitHub repository for this course. After adding and modifying files, your repository will look like this:
. ├── README.md ├── javascript/ │ └── (existing files from previous assignments) ├── python/ │ └── (existing files from previous assignments) ├── java/ │ └── (existing files from previous assignments) └── swift/ ├── .gitignore (You are on your own to figure out what goes here) ├── exercises.swift └── main.swift (The tests, given to you below)
Submit to BrightSpace a link to your repo. Make sure your README has the names of all the students that have worked on the project. Please submit only one solution set for your team. It does not matter under whose GitHub account your work is stored. Make sure both Julian and I are added as contributors to your repo.
You will be graded on your programming style, so make sure you are set up so that your editor or IDE auto-formats your code. Use plugins for your editor that include formatter and perhaps a linter.
Your homework submission will be the state of your repository on the main branch, at the due datetime, which is 11:59 p.m. on the due date in the America/Los Angeles time zone.
There’s nothing special here; just drop the source and test files in the same folder as indicated in the repository layout above. Professional Swift programmers set up and test real projects according to certain conventions, but at this point in the class, just focus on learning the language. You can learn the ecosystem on your own.
Your job is to write a single module with several functions and classes, and to add whatever lines are appropriate to your .gitignore file(s). The functions are described below. For unit tests, use this assert-filled program, provided free of charge, because you are special:
import Foundation // First check ensures you defined your own struct NegativeAmountError. // If you implement your solution correctly, you will get a warning // when you compile, that's ok! assert(change(200) is Result<(Int, Int, Int, Int), NegativeAmountError>) switch change(250) { case .success(let coins): assert(coins == (10, 0, 0, 0)) case _: assert(false) } switch change(-50) { case .success(_): assert(false) case .failure(let error): assert(error is NegativeAmountError) } assert(try! change(0).get() == (0, 0, 0, 0)) assert(try! change(97).get() == (3, 2, 0, 2)) assert(try! change(8).get() == (0, 0, 1, 3)) assert(try! change(144).get() == (5, 1, 1, 4)) assert(try! change(97).get() == (3, 2, 0, 2)) assert(try! change(100000000000).get() == (4000000000, 0, 0, 0)) assert((try? change(-50).get()) == nil) assert("".stretched == "") assert(" ".stretched == "") assert(" \t\n \t".stretched == "") assert(" Hi hi ".stretched == "Hiihhhiiii") assert("😁😂😱".stretched == "😁😂😂😱😱😱") assert("hello world".stretched == "heelllllllooooowwwwwwooooooorrrrrrrrllllllllldddddddddd") assert("😁👩🏽🎤🧑🏻🔧".stretched == "😁👩🏽🎤👩🏽🎤🧑🏻🔧🧑🏻🔧🧑🏻🔧") assert([].mapThenUnique { Int($0) * $0 } == Set([])) assert([2, 9, -9, 3].mapThenUnique { Int($0) * $0 } == Set([4, 9, 81])) assert(["abc", "Hi", "AbC"].mapThenUnique { $0.lowercased() } == Set(["hi", "abc"])) assert(["33", "21", "33"].mapThenUnique { Int($0) } == Set([21, 33])) var scratch = [Int]() powers(of: 2, through: 64) { scratch.append($0) } assert(scratch == [1, 2, 4, 8, 16, 32, 64]) scratch.removeAll() powers(of: 2, through: 63) { scratch.append($0) } assert(scratch == [1, 2, 4, 8, 16, 32]) scratch.removeAll() powers(of: -3, through: 300) { scratch.append($0) } assert(scratch == [1, -3, 9, -27, 81, -243]) let h: Animal = Horse(name: "CJ") assert(h.speak() == "CJ says neigh") let c: Animal = Cow(name: "Bessie") assert(c.speak() == "Bessie says moooo") assert(Sheep(name: "Little Lamb").speak() == "Little Lamb says baaaa") // Test that Animal really is a protocol with the default method struct Rat: Animal { let name: String let sound = "squeak" } assert(Rat(name:"Oreo").speak() == "Oreo says squeak") assert(say("A").phrase == "A") assert(say("A").and("B").phrase == "A B") assert(say("🐤🦇").and("$🦊👏🏽").and("!").phrase == "🐤🦇 $🦊👏🏽 !") var greet = say("Hello").and("there") assert(greet.and("nice").and("person").phrase == "Hello there nice person") assert(greet.and("Swift").phrase == "Hello there Swift") assert(twice({$0 * 2}, appliedTo: 5.0) == 20.0) assert(twice({s in s + "ee"}, appliedTo: "b") == "beeee") assert(uppercasedFirst(of: [], longerThan: 5) == nil) assert(uppercasedFirst(of: ["🎃"], longerThan: 1) == nil) assert(uppercasedFirst(of: ["a", "bcdef"], longerThan: 5) == nil) assert(uppercasedFirst(of: ["a", "abcdef", "g"], longerThan: 5) == Optional.some("ABCDEF")) assert(uppercasedFirst(of: ["ab", "abcf"], longerThan: 1) == Optional.some("AB")) let q = Quaternion(a: 3.5, b: 2.25, c: -100, d: -1.25) assert(q.a == 3.5) assert(q.b == 2.25) assert(q.c == -100.0) assert(q.d == -1.25) let q1 = Quaternion(a: 1, b: 3, c: 5, d: 2) let q2 = Quaternion(a: -2, b: 2, c: 8, d: -1) let q3 = Quaternion(a: -1, b: 5, c: 13, d: 1) let q4 = Quaternion(a: -46, b: -25, c: 5, d: 9) assert(q1 + q2 == q3) assert(q3 - q2 == q1) assert(q1 * q2 == q4) assert(Quaternion.I * Quaternion.J == Quaternion.K) assert(Quaternion.ZERO.coefficients == [0, 0, 0, 0]) assert(Quaternion.K.coefficients == [0, 0, 0, 1]) assert(Quaternion(a: 2, b: 1.5, c: 10, d: -8).coefficients == [2.0, 1.5, 10.0, -8.0]) assert(String(describing: Quaternion.ZERO) == "0.0+0.0i+0.0j+0.0k") assert(String(describing: Quaternion(a: 0, b: -1, c: 0, d: 2.25)) == "0.0-1.0i+0.0j+2.25k") assert(String(describing: Quaternion.ZERO - Quaternion.K) == "0.0+0.0i+0.0j-1.0k") assert(String(describing: Quaternion(a: -20, b: -1.75, c: 13, d: -2.25)) == "-20.0-1.75i+13.0j-2.25k") print("All tests passed")
You can test with:
$ swiftc -o main exercises.swift main.swift && ./main
Note: if you cannot install Swift on your machine, say, because you are running Windows, you can develop your code on a site like Replit.
In the file exercises.swift create a Swift module containing the following entities. For details on how each function or class should work, consult the unit tests.
Int
) and returns a Result
object that can indicate (1) for success, a 4-tuple containing the smallest number of U.S. quarters, dimes, nickels, and pennies that equal the given amount, or (2) a failure whenever a negative amount was supplied. See the unit test for information on how you are to craft the result type. Implementation restriction: use the Int
method quotientAndRemainder
.String
computed property that computes a new string equal to the receiver but with all whitespace removed and then with the i-th grapheme (1-based) repeated i times. Note that you are to repeat graphemes, not code units. Good news: Swift does this automatically.
> " Hi hi ".stretched "Hiihhhiiii" > "😁😂😱".stretched "😁😂😂😱😱😱"
Array
that maps a function over the receiver then returns the unique values after mapping.
> powers(of: 2, through: 70) { print($0) } 1 2 4 8 16 32 64
Animal
a protocol, and define the speak
function as a default implementation in a protocol extension. Each of the three structs Horse
, Cow
, and Sheep
should adapt the protocol, similar to the way the Rat
struct in the supplied unit test script does.
> say("Hello").phrase "Hello" > say("Hello").and("my").and("name").and("is").and("Colette").phrase "Hello my name is Colette"
f
and a value x
and returns f(f(x))
. Remember you are doing Swift, not Java, so you can use functions directly (no need for objects with apply
methods).Optional
, since there might not be any such string in the list. Implementation restriction: Your solution must find the first such value using the first
method, then since that returns an optional, use the optional chaining operator ?.
when you invoke the upper-casing method. This is so cool, right?