DEV Community

Lou Franco
Lou Franco

Posted on • Edited on • Originally published at app-o-mat.com

The Swift Programming Language Companion: Review of Basics to Functions (Part 2)

This article is part of a series on learning Swift by writing code to The Swift Programming Language book from Apple.

We've covered the basics up to functions, and reviewed them in the last article, and we're going to continue reviewing those chapters in this one.

Set up a reading environment

If you are jumping around these articles, make sure you read the Introduction to see my recommendation for setting up a reading environment.

Exercises

For this chapter, we're going to write code inspired by the Maps app.

Copy this into your playground

let places: [[String: Any]] = [
    ["name": "Buckingham Palace", "location": (lat: 51.5000632, long: -0.1449567)],
    ["name": "Great Pyramid of Giza", "location": (lat: 29.9792391, long: 31.1320079)],
    ["name": "Sydney Opera House", "location": (lat: -33.8567799, long: 151.2131027)],
    ["name": "Machu Picchu", "location": (lat: -13.163136, long: -72.5471569)],
    ["name": "Victoria Falls", "location": (lat: -17.9149133, long: 25.8379429)],
    ["name": "Empire State Building", "location": (lat: 40.7484445, long: -73.9878584)],
    ["name": "The Forbidden City", "location": (lat: 39.9394501, long: 116.1152174)],
    ["name": "Parthenon", "location": (lat: 38.3336346, long: 20.9712001)],
]
Enter fullscreen mode Exit fullscreen mode

To make sure you understand how to access data in this structure, start with this code:

let name = places[0]["name"] as? String
let location = places[0]["location"] as? (lat: Double, long: Double)
location?.lat
Enter fullscreen mode Exit fullscreen mode

In your Playground write code to do the following

  1. Print out the longitude (.long) of The Sydney Opera House.
  2. Use this page to find the distance between two of these places by plugging in their latitudes and longitudes.
  3. Implement the Haversine distance formula. If you are an experienced programmer (just new to Swift), then read the Javascript version on that page and try to port it.
  4. Once you have that, write a function that takes the places data and returns the two places that are closest to each other. (In Swift, the basic math functions are all global functions: sin, cos, atan2, pow, etc)

More help for beginners

Ok, step one is to declare a function that takes two lat/long tuples and returns a Double.

Start with this:

let location1 = places[0]["location"] as? (lat: Double, long:Double)
let location2 = places[1]["location"] as? (lat: Double, long:Double)

func distanceKm(loc1: (lat: Double, long: Double)?, loc2: (lat: Double, long: Double)?) 
-> Double? {
    if let loc1 = loc1, let loc2 = loc2 {
        // Implement Haversine here
        return 0 // .. replace this line
    }
    return 0
}

distanceKm(loc1: location1, loc2: location2)
Enter fullscreen mode Exit fullscreen mode

Here is the basic algorithm:

  1. Declare a constant R which is 6371000.0 (the radius of the Earth)
  2. Declare a constant phi1 which is loc1.lat in radians: loc1.lat * .pi / 180.0 (in general: radians = degrees * .pi / 180.0)
  3. Declare a constant phi2 which is loc2.lat in radians
  4. Declare a constant deltaPhi which is (loc2.lat - loc1.lat) in radians
  5. Declare a constant deltaLambda which is (loc2.long - loc1.long) in radians
  6. Declare a constant a to be pow(sin(deltaPhi / 2), 2) + cos(phi1) * cos(phi2) * pow(sin(deltaLambda/2), 2)
  7. Declare a constant c to be 2 * atan2(sqrt(a), sqrt(1-a))
  8. Return R * c / 1000.0

distanceKm(loc1: location1, loc2: location2) should be around 3511 just like the web page.

Now see if you can find the two closest places. Start with this

func closestTo(places: [[String: Any]], loc: (lat: Double, long: Double)) -> String {
    var smallestDistance = Double.greatestFiniteMagnitude
    var closest = ""

    for p in places {
        if
            let name = p["name"] as? String,
            let loc2 = p["location"] as? (lat: Double, long: Double),
            let distance = distanceKm(loc1: loc, loc2: loc2),
            distance < smallestDistance {
                smallestDistance = distance
                closest = name
        }
    }

    return closest
}

// Find the closest place to the Eiffel Tower (should be Buckingham Palace)
closestTo(places: places, loc: (lat: 48.8583736, long: 2.2922873))
Enter fullscreen mode Exit fullscreen mode

Use this function as a start. You need to make sure you don't compare a place to itself, because that will always be the closest.

DM me or comment below if you need help.

Next: Closures

The next article will provide exercises for the Closures chapter. Read it before you move on.

Top comments (0)