Introduction to Swift

Apr 24 2024 · Swift 5.10, iOS 17, Xcode 15

Lesson 04: Problem Solving

Measuring Demo

Episode complete

Play next episode

Next
Transcript

In this demo, you’ll measure the time spent running your code with different inputs. Then, you’ll change your solution to use a more optimized approach.

For this demo, open the file named Demo2 in the Starter folder.

The code in the starter playground matches what you finished in the first demo. It has a small addition so Swift can measure your code’s execution time. The ContinuousClock is a struct that Apple provides for making “high resolution measurements of execution”. That’s exactly what you want to measure how long your solution takes.

Run the playground and see the results in the window’s lower pane.

You can see that counting from zero to 10, or zero to one hundred, takes a small amount of time. Now, try larger numbers. Test your code on values like one hundred thousand, one million and one hundred million.

calculateSum(minValue: 0, maxValue: 100_000)
calculateSum(minValue: 0, maxValue: 1_000_000)
calculateSum(minValue: 0, maxValue: 100_000_000)

Those underscore characters are just for humans to read these numbers more easily, like a period or comma depending on where you’re from. Swift ignores them when it performs calculations.

Run the playground and look at the time spent to calculate each.

The first should take a little over a second. The second will take longer — from 10 to 15 seconds. But the third will take so much longer that you shouldn’t wait for it to finish. It might take more than 20 minutes depending on your computer’s CPU.

Stop the playground with the same play button, which now looks like a square, so you don’t have to wait all that time.

When you test an algorithm or a solution in your head, you try smaller sets of numbers like from zero to 10. It’s easy to run it in your head, and the amount of time the computer takes is insignificant.

But computers are best for handling massive input and they produce results very quickly. The last three examples took a bit longer. A hundred thousand might feel like it didn’t last long, one million took a long time, and the last one just isn’t acceptable.

The kind of solution you have implemented is described as Brute Force. It creates a solution through primitive steps without any planning or logic to reduce the number of steps.

Luckily, the puzzle you’re working on can be solved another way. The sum of only the two minimum and maximum numbers is the same for the 2nd number from the bottom and 2nd from the top, 3rd from the bottom and 3rd from the top, and so on.

The average remains the same when you take the numbers from both sides. So a way to calculate the sum between a whole range is to take the average of the two numbers and multiply it by how many numbers are in the range.

Create a function for the new version of the solution:

func calculateSumOptimized(minValue: Int, maxValue: Int) -> Int {

}

Write this new solution in the new function:

var sum = 0
sum = (minValue + maxValue) / 2
sum *= maxValue - minValue + 1

return sum

The solution’s main part is the second and third lines. Add them in a measure, using the previous function as a pattern, and print the time measurement:

func calculateSum_optimized(minValue: Int, maxValue: Int) -> Int {
  var sum = 0
  let timeMeasure = ContinuousClock().measure {
    sum = (minValue + maxValue) / 2
    sum *= (maxValue - minValue + 1)
  }

  print("\(timeMeasure) for result \(sum)")
  return sum
}

Try the new function with the same numbers as the old one so you can compare the results:

calculateSum_optimized(minValue: 0, maxValue: 10)
calculateSum_optimized(minValue: 0, maxValue: 100)

calculateSum_optimized(minValue: 0, maxValue: 100_000)
calculateSum_optimized(minValue: 0, maxValue: 1_000_000)
calculateSum_optimized(minValue: 0, maxValue: 100_000_000)

Before you run the playground, comment or delete the line using the first function to calculate the sum from zero to one hundred million.

Now, run the playground and compare the results and the time it took to calculate them.

Notice that no matter how large the input is, the result appears almost instantly.

Your new solution is just as accurate and a lot faster. Your first solution is correct, but it’s only half a solution. Optimizing it to make it faster can go a long way, especially when you reduce the calculation time from several minutes to almost instantaneous.

See forum comments
Cinema mode Download course materials from Github
Previous: Measuring Efficiency Next: Guarding Against Bad Input