Cardano Triplets in Swift

Glen Yi
Swift Programming
Published in
3 min readAug 24, 2014

--

Performance comparison between Swift and Objective-C

Engineers tend to like brain teasers, and one of the problems we came across at work was the Cardano Triplets problem on Project Euler. I never actually solved it, but it was fun to play around with and it ended up with me running an experiment.

Cardano Triplets?

A triplet of positive integers, (a, b, c), is a Cardano Triplet if it satisfies the following condition:

The problem is to find all Cardano Triplets where a + b + c <= 110,000,000

Yes, one hundred and ten million… making this a near impossible problem to solve through brute force.

I’m sure there is a very elegant mathematical/programming solution to this, but instead of trying to solve for 110,000,000 I thought it would be interesting to write a brute force solution anyways, but in Apple’s new programming language, Swift. Swift is a fairly easy language to pickup and should greatly reduce the barrier to entry for anyone looking to learn iOS development (no more square brackets everywhere!). This experiment led me to do a direct comparison in performance between Swift and Objective-C using the exact same solution.

The Solution

The brute force solution was done mainly with 2 functions. The first one checks if a triplet is valid.

func isCardanoTriplet(triplet: Triplet) -> Bool
{
let bc = Double(triplet.b) * sqrt(Double(triplet.c))
let cardano = cbrt(Double(triplet.a)+bc) +
cbrt(Double(triplet.a)-bc)
// Floating point rounding errors…
let isCardano = (cardano < 1.000001 && cardano > 0.999999)
return isCardano
}

The second function creates all triplets where a + b + c <= ‘limit’. This is done with a triple nested for-loop, which is where the majority of the computing time takes place.

var count = 0
for a in 1…limit-2 {
for b in 1…(limit-a-1) {
for c in 1…(limit-a-b) {
let triplet = (a, b, c)
if self.isCardanoTriplet(triplet) {
count++
println(“\(count): \(triplet)”)
}
}
}
}

Not the most elegant solution but it gets the job done. I wrote a simple app in both Swift and Objective-C with the exact same concept as above to compare their performances in seconds.

The Test Setup

Hardware: 2012 MacBook Air (1.8 GHz Intel Core i5, 4GB 1600 MHz DDR3)
XCode Versions: 6 Beta4, 6 Beta6
XCode
Simulator: iPhone 5s

Lastly, because I didn’t want the apps to run forever, I set the limit to 1000 which correctly returns 149 Cardano Triplets.

The Results

Swift

XCode 6 Beta4: 130 seconds
XCode 6 Beta6: 56 seconds

Objective-C

XCode 6 Beta4: 8 seconds
XCode 6 Beta6: 8 seconds

Edit: The above results were run in Debug mode with no optimizations. Turning on -O optimizations quickly closed the gap.

Swift

XCode 6 Beta6: (-Os optimization): 8.5 seconds

Objective-C

XCode 6 Beta6: (-Os optimization): 6.4 seconds

This time Swift was only 32.8% slower, a huge relief from the original 600% result! Swift is still in beta and Apple will be continuously optimizing it down the road, but it was still a surprising gap between Swift and Objective-C.

This shouldn’t deter anyone from learning Swift however as it will ultimately be the future of iOS development. I also find it very refreshing to work with after years of C++ and Objective-C. Just don’t expect to solve any Project Euler problems in record time using Swift.

The full code for the project can be found on my github, so feel free to fork it and try it out for yourself!

And oh ya, header photo cred to NASA’s Hubble Space Telescope. ☺

--

--