exercises.swift
// Hello, these are homework answers, and homework is to help you learn,
// so this file contains a lot of superfluous comments to explain some
// things about Swift that I think make for good learning moments. As
// always, your homework submissions should have appropriate comments
// and not comments that try to teach your reader about Swift.
import Foundation
// Because change returns a result, we need to make a real error type.
struct NegativeAmountError: Error {}
// We didn’t talk about typealias in class, but it’s cool
typealias ChangeResult = Result<(Int, Int, Int, Int), NegativeAmountError>
// The _ is required of course, since you have to pass the tests.
func change(_ amount: Int) -> ChangeResult {
if amount < 0 {
return .failure(NegativeAmountError())
}
let (quarters, afterQuarters) = amount.quotientAndRemainder(dividingBy: 25)
let (dimes, afterDimes) = afterQuarters.quotientAndRemainder(dividingBy: 10)
let (nickels, pennies) = afterDimes.quotientAndRemainder(dividingBy: 5)
return .success((quarters, dimes, nickels, pennies))
}
extension String {
var stretched: String {
return self
.filter { !$0.isWhitespace }
.enumerated()
.map{ String(repeating: String($1), count: $0 + 1) }
.joined()
}
}
extension Array {
func mapThenUnique<T>(mapper: (Element) -> T) -> Set<T> {
return Set(self.map(mapper))
}
}
// This is the most direct way, but fancier solutions probably exist
func powers(of base: Int, through limit: Int, consume: (Int) -> Void) {
var power = 1
while power <= limit {
consume(power)
power *= base
}
}
protocol Animal {
var name: String { get }
var sound: String { get }
func speak() -> String
}
extension Animal {
func speak() -> String {
return "\(name) says \(sound)"
}
}
// You should have been able to infer these from the test case. :)
struct Cow: Animal {
let name: String
let sound = "moooo"
}
struct Horse: Animal {
let name: String
let sound = "neigh"
}
struct Sheep: Animal {
let name: String
let sound = "baaaa"
}
struct Sayer {
let phrase: String
func and(_ word: String) -> Sayer {
return Sayer(phrase: "\(self.phrase) \(word)")
}
}
func say(_ word: String) -> Sayer {
return Sayer(phrase: word)
}
// Yay, a generic function. Look how nice this looks in Swift compared to Java.
// Functions are functions, and can be called without the functional interface
// method (e.g., apply) that is requried in Java.
func twice<T>(_ f: (T) -> T, appliedTo x: T) -> T {
return f(f(x))
}
// I think it’s important to use nice short parameter names here. You got the
// argument labels from the test, but remember they look pretty funny inside
// the code. Here a and n are good. Their purpose is basically documented in
// the function definition line and the body is only one line, so it’s fine.
func uppercasedFirst(of a: [String], longerThan n: Int) -> String? {
return a.first(where: { $0.count > n })?.uppercased()
}
struct Quaternion: CustomStringConvertible, Equatable {
let a: Double
let b: Double
let c: Double
let d: Double
static let ZERO = Quaternion()
static let I = Quaternion(b: 1)
static let J = Quaternion(c: 1)
static let K = Quaternion(d: 1)
init(a: Double = 0, b: Double = 0, c: Double = 0, d: Double = 0) {
self.a = a
self.b = b
self.c = c
self.d = d
}
var coefficients: [Double] {
return [self.a, self.b, self.c, self.d]
}
var description: String {
var base = "\(self.a)+\(self.b)i+\(self.c)j+\(self.d)k"
base = base.replacingOccurrences(of: "+-", with: "-")
return base
}
}
func +(q1: Quaternion, q2: Quaternion) -> Quaternion {
return Quaternion(
a: q1.a + q2.a,
b: q1.b + q2.b,
c: q1.c + q2.c,
d: q1.d + q2.d
)
}
func -(q1: Quaternion, q2: Quaternion) -> Quaternion {
return Quaternion(
a: q1.a - q2.a,
b: q1.b - q2.b,
c: q1.c - q2.c,
d: q1.d - q2.d
)
}
func *(q1: Quaternion, q2: Quaternion) -> Quaternion {
return Quaternion(
a: q2.a * q1.a - q2.b * q1.b - q2.c * q1.c - q2.d * q1.d,
b: q2.a * q1.b + q2.b * q1.a - q2.c * q1.d + q2.d * q1.c,
c: q2.a * q1.c + q2.b * q1.d + q2.c * q1.a - q2.d * q1.b,
d: q2.a * q1.d - q2.b * q1.c + q2.c * q1.b + q2.d * q1.a
)
}