Code for Swift 5.0.1

import Cocoa

//page 41
struct Vector: CustomStringConvertible {

var x: Double
var y: Double

// page 42
init(){
    self.init(x: 0, y:0)
}

init (x: Double, y:Double){
    self.x = x
    self.y = y
}

//page 43 and 44
func vectorByAddingVector (vector: Vector) -> Vector {
    return Vector (x: x + vector.x,
                   y: y + vector.y)
}

// page 44
static func +(left: Vector, right: Vector) -> Vector{
    return left.vectorByAddingVector(vector: right)
}

static func *(left: Vector, right: Double) -> Vector {
    return Vector(x: left.x * right, y: left.y * right)
}

// page 52
var length: Double {
    return sqrt(x*x + y*y)
}

//page 55
var description: String {
    return "(\(x), \(y))"
}

}

let gravity = Vector(x: 0.0, y: -9.8)

let twoGs = gravity + gravity
let twoGsAlso = gravity * 2.0

// page 45
class Particle {

var position: Vector
var velocity: Vector
var acceleration: Vector

init(position: Vector){
    self.position = position
    self.velocity = Vector()
    self.acceleration = Vector()
}

// page 46
convenience init() {
    self.init(position: Vector())
}

// page 47
func tick(dt: TimeInterval) {
    velocity = velocity+acceleration*dt
    position = position + velocity*dt
    position.y = max(0,position.y)
}

}

// page 47
class Simulation {

var particles: [Particle] = []
var time: TimeInterval = 0.0

func addParticle(particle: Particle){
    particles.append(particle)
}

func tick(dt: TimeInterval) {
    for particle in particles{
        particle.acceleration = particle.acceleration +  gravity
        particle.tick(dt: dt)
        particle.acceleration = Vector()
        particle.position.y // page 48
    }
    time += dt
    // page 48
    particles = particles.filter { particle in
        let live = particle.position.y > 0.0
        if !live {
            print("Particle terminated at time: \(self.time)")
        }
        return live
    }
}

}

// page 50
class Rocket: Particle {

let thrust: Double
var thrustTimeRemaining: TimeInterval
let direction = Vector(x: 0, y: 1)

convenience init(thrust: Double, thrustTime: TimeInterval) {
    self.init(position: Vector(), thrust: thrust, thrustTime: thrustTime)
}

init(position: Vector, thrust: Double, thrustTime: TimeInterval){
    self.thrust = thrust
    self.thrustTimeRemaining = thrustTime
    super.init(position: position)
}

override func tick(dt: TimeInterval) {
    if thrustTimeRemaining > 0.0 {
        let thrustTime = min(dt, thrustTimeRemaining)
        let thrustToApply = thrust * thrustTime
        let thrustForce = direction * thrustToApply
        acceleration = acceleration + thrustForce
        thrustTimeRemaining -= thrustTime
    }
    super.tick(dt: dt)
}

}

// page 48
let simulation = Simulation()

// page 48
//let ball = Particle()
//ball.acceleration = Vector(x: 0, y: 100)
//simulation.addParticle(particle: ball)

// page 51
let rocket = Rocket(thrust: 10, thrustTime: 60)
simulation.addParticle(particle: rocket)

while simulation.particles.count > 0 && simulation.time < 500 {
simulation.tick(dt: 1.0)
}

//page 54
print(“Gravity is (gravity).”)