Gold Challenge: I wasn’t able to get this one to stick in my head. Any help is appreciated!
Platinum Challenge
First, I wanted to create a function to calculate the Euclidean Distance for a point (passing in the point you want to calculate the distance from, in case you want to pick something different than the origin (print statement for debugging purposes). Ths also included defining a new operator that could handle exponents in the function (found the solution for the ^^ operator online, also sets precedence so things are calculated correctly):
/*
* creating the ^^ operator to use later in Euclidean Distance func.
* Also needs to be outside the struct, as it must be a file-level operator.
*/
precedencegroup ExponentiativePrecedence {
associativity: right
higherThan: MultiplicationPrecedence
}
infix operator ^^: ExponentiativePrecedence
public func ^^ (radix: Double, power: Double) -> Double {
return pow((radix), (power))
}
struct Point: Comparable {
...
func euclideanDistance(to other: Point) -> Double {
let distance = sqrt((Double(self.x) - Double(other.x))^^2 + (Double(self.y) - Double(other.y))^^2)
print("Calculated distance for (\(self.x), \(self.y)) to origin: \(distance)")
return distance
}
}
Then, you can use that in the < operator definition to calculate the distance for each point passed in, and determine whether or not one is equal to the other:
struct Point: Comparable {
...
static func <(lhs: Point, rhs: Point) -> Bool {
let originPoint = Point(x: 0, y: 0)
let lhsDistance = originPoint.euclideanDistance(to: lhs)
let rhsDistance = originPoint.euclideanDistance(to: rhs)
return lhsDistance < rhsDistance
}
...
}
Now it works as expected.
Note for authors: learning about precedence at the end of the chapter would’ve been very helpful in one of the previous challenges when we were working on the lexer/parsing engine and had to figure out how to set precedence for multiplcation over addition and such (although I understand why it was mentioned in this chapter since this was focused on custom operators). Just pointing that out!
@macintacos, here is my solution for the Gold challenge. I was confused because after creating my people array, whenever I was typing “people.index(of:” I wasn’t getting any autocomplete. So, I just finished typing it in, “var p1Index = people.index(of:p1)”, and then I understood what the Gold challenge was asking us to do.
Essentially, it is asking us to use the index(of:) to find the index of the people array, but we have to do something to get rid of the error that comes when we just try to use index(of:) on the people array. The issue is that the class is not Equatable. Since it’s not Equatable, the index(of:) method, which finds the index of the element (by checking equality), doesn’t know how to determine index(of:). The error message is “error: cannot invoke ‘index’ with an argument list of type ‘(of: Person)’”. The solution is to make Person Equatable:
class Person: Equatable {
var name: String
var age: Int
Both x and y are of type integers (Int), The result of multiplication and addition on integers is also an integer. However, the function sqrt() (square root) which returns Double operates on parameter of type Double. So we need to cast the integer (x * x + y * y) to Double with Double()
I think you should use the euclidean distance in the operator ‘==’ too.
With the current definition (comparison of x and y of both sides), we have this strange result:
let pa = Point(x: 5, y: 3)
let pb = Point(x: 3, y: 5)
print(pa == pb) // false (although distance of pa and pb from the origin is the same)
Then we have also:
print(pa < pb) // false
print(pa > pb) // false
Whereas the goal of the platinium challenge was precisely to avoid this situation.
Here are my solutions to the Bronze and Platinum challenges (I used some help from this page):
import Cocoa
struct Point: Comparable {
let x: Int
let y: Int
// required to conform to Equatable protocol, from whcih Comparable inherits
static func ==(lhs: Point, rhs: Point) -> Bool {
return sqrt(Double((lhs.x * lhs.x) + (lhs.y * lhs.y))) == sqrt(Double((rhs.x * rhs.x) + (rhs.y * rhs.y)))
}
static func <(lhs: Point, rhs: Point) -> Bool {
let lhsDistFromOrigin = sqrt(Double((lhs.x * lhs.x) + (lhs.y * lhs.y)))
let rhsDistFromOrigin = sqrt(Double((rhs.x * rhs.x) + (rhs.y * rhs.y)))
return lhsDistFromOrigin < rhsDistFromOrigin
}
static func +(lhs: Point, rhs: Point) -> Point {
return Point(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
}
let a = Point(x: 4, y: 3)
let b = Point(x: 3, y: 4)
let abEqual = (a == b)
let abNotEqual = (a != b)
let c = Point(x: 0, y: 10)
let d = Point(x: 6, y: 8)
let cdEqual = ( c == d)
let cLessThanD = (c < d)
// the following functions are provided by default when conforming to Comparable (based on the implementation of the required '<' function)
let cLessThanEqualD = ( c <= d)
let cGreaterThanD = (c > d)
let cGreaterThanEqualD = (c >= d)
let cPlusD = c + d
print(cPlusD.x)
print(cPlusD.y)
I got the gold one to work by making Person conform to the Equatable protocol and implementing
a static function which returns true or false depending on String and Int comparisons of Point’s properties.