HiveBrain v1.2.0
Get Started
← Back to all entries
patternswiftMinor

Project Euler #6 (Sum square difference) in Swift

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
swiftsumdifferenceprojecteulersquare

Problem

import Foundation

func printTimeElapsedWhenRunningCode(title:String, operation:()->()) {
    let startTime = CFAbsoluteTimeGetCurrent()
    operation()
    let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
    println("Time elapsed for \(title): \(timeElapsed) s")
}    

func squaresSummed(first: Int, second: Int) -> Int {
    return (first + (second * second))
}

func solution6() {
    let firstHundredInts = [Int](1 ... 100)
    let summed = firstHundredInts.reduce(0) { $0 + $1 }
    let summedSquared = summed * summed

    let squaredSummed = firstHundredInts.reduce(0, combine: squaresSummed)

    let answer = summedSquared - squaredSummed

    println(String(answer))
}

printTimeElapsedWhenRunningCode("Sum square difference", solution6)


Some of the built in Swift stuff made this quite nice. The syntax for declaring an array which is a simple list of integers is very convenient. It runs faster than iterating through a loop to set all the values, types faster and reads better than typing all the values out by hand.

I quite like the reduce function on Swift arrays.

What could make this more Swift...-onic? What needs improvement?

Solution

First, I would suggest that the solution6() function takes a parameter for
the upper bound, and returns the result instead of printing it (as also
suggested by @user16547 while I was writing this answer):

func solution6(upper : Int) -> Int {
    let firstInts = [Int](1 ... upper)
    let summed = firstInts.reduce(0) { $0 + $1 }
    let summedSquared = summed * summed
    let squaredSummed = firstInts.reduce(0, combine: squaresSummed)
    return summedSquared - squaredSummed
}

printTimeElapsedWhenRunningCode("Sum square difference") {
    let answer = solution6(10_000)
    println(answer)
}


Then you use an auxiliary function squaresSummed for computing the second
sum, but not for the first (and the name of that function is not very descriptive). In my opinion it is easier to understand if the shorthand notation is used
for both summations:

func solution6(upper : Int) -> Int {
    let firstInts = [Int](1 ... upper)
    let summed = firstInts.reduce(0) { $0 + $1 }
    let squaredSummed = firstInts.reduce(0) { $0 + $1 * $1 }
    return summed * summed - squaredSummed
}


For an upper bound of 10,000, this took about 0.001 seconds on my MacBook Pro in Release mode.

But Int creates an array of all that numbers, which costs time
and memory. If you use a range instead

func solution6(upper : Int) -> Int {
    let firstInts = 1 ... upper
    let summed = reduce(firstInts, 0) { $0 + $1 }
    let squaredSummed = reduce(firstInts, 0) { $0 + $1 * $1 }
    return summed * summed - squaredSummed
}


the time is reduced to about 0.0002 seconds. This is about the same
time needed for a simple loop

func solution6(upper : Int) -> Int {
    var summed = 0
    var squaredSummed = 0
    for i in 1 ... upper {
        summed += i
        squaredSummed += i * i
    }
    return summed * summed - squaredSummed
}


which would be the most straightforward implementation of the algorithm.

Of course the fastest and shortest solution to the PE problem would be to


Find the closed formula for 1 + 2 + ... + n and 1^2 + 2^2 + ... + n^2 and use that instead of a loop.

Code Snippets

func solution6(upper : Int) -> Int {
    let firstInts = [Int](1 ... upper)
    let summed = firstInts.reduce(0) { $0 + $1 }
    let summedSquared = summed * summed
    let squaredSummed = firstInts.reduce(0, combine: squaresSummed)
    return summedSquared - squaredSummed
}

printTimeElapsedWhenRunningCode("Sum square difference") {
    let answer = solution6(10_000)
    println(answer)
}
func solution6(upper : Int) -> Int {
    let firstInts = [Int](1 ... upper)
    let summed = firstInts.reduce(0) { $0 + $1 }
    let squaredSummed = firstInts.reduce(0) { $0 + $1 * $1 }
    return summed * summed - squaredSummed
}
func solution6(upper : Int) -> Int {
    let firstInts = 1 ... upper
    let summed = reduce(firstInts, 0) { $0 + $1 }
    let squaredSummed = reduce(firstInts, 0) { $0 + $1 * $1 }
    return summed * summed - squaredSummed
}
func solution6(upper : Int) -> Int {
    var summed = 0
    var squaredSummed = 0
    for i in 1 ... upper {
        summed += i
        squaredSummed += i * i
    }
    return summed * summed - squaredSummed
}

Context

StackExchange Code Review Q#62163, answer score: 6

Revisions (0)

No revisions yet.