patternswiftMinor
Project Euler #6 (Sum square difference) in Swift
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
the upper bound, and returns the result instead of printing it (as also
suggested by @user16547 while I was writing this answer):
Then you use an auxiliary function
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:
For an upper bound of 10,000, this took about 0.001 seconds on my MacBook Pro in Release mode.
But
and memory. If you use a range instead
the time is reduced to about 0.0002 seconds. This is about the same
time needed for a simple loop
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.
solution6() function takes a parameter forthe 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 secondsum, 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 timeand 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.