Skip to content

Instantly share code, notes, and snippets.

@mrh-is
Created December 23, 2016 10:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrh-is/35ef7aaaec8a1c467518db5749196da3 to your computer and use it in GitHub Desktop.
Save mrh-is/35ef7aaaec8a1c467518db5749196da3 to your computer and use it in GitHub Desktop.
When will Santa be at my house?
extension Location {
func closestLocationOnPath(start: Location, end: Location) -> (location: Location, t: Double, distance: Double) {
let pathVector = (latitude: end.latitude - start.latitude, longitude: end.longitude - start.longitude)
var t = (self.latitude * pathVector.latitude - start.latitude * pathVector.latitude + self.longitude * pathVector.longitude - start.longitude * pathVector.longitude) / (pow(pathVector.latitude,2) + pow(pathVector.longitude,2))
t = min(max(t, 0), 1)
let closestLocation = Location(latitude: start.latitude + t * pathVector.latitude, longitude: start.longitude + t * pathVector.longitude)
return (location: closestLocation, t: t, distance: distance(to: closestLocation))
}
func distance(to other: Location) -> Double {
return sqrt(pow(other.latitude-self.latitude,2) + pow(other.longitude-self.longitude,2))
}
}
extension Date {
static func scaled(between first: Date, and second: Date, scale: Double) -> Date {
precondition(scale <= 1 && scale >= 0, "Scale must be in [0,1].")
let difference = second.timeIntervalSinceReferenceDate - first.timeIntervalSinceReferenceDate
return first.addingTimeInterval(difference * scale)
}
}
func getArrivalTime(at location: Location, with stops: List<Stop>) -> Date {
guard stops.count > 1 else {
return stops.first?.time ?? Date()
}
var minimumDistance = Double.infinity
var closestTime = Date()
for index in 0..<(stops.count-1) {
let startStop = stops[index], endStop = stops[index+1]
guard let startLocation = startStop.location, let endLocation = endStop.location else {
continue
}
let (_, t, distance) = location.closestLocationOnPath(start: startLocation, end: endLocation)
if distance < minimumDistance {
minimumDistance = distance
closestTime = Date.scaled(between: startStop.time, and: endStop.time, scale: t)
print(index)
print(minimumDistance)
print(closestTime)
}
}
return closestTime
}
getArrivalTime(at: .sanFrancisco, with: santa.route)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment