Search code examples
swiftfor-in-loop

for in loop with where clause in Swift


I have tried to update a little function to Swift 2.1. The original working code was:

import func Darwin.sqrt
func sqrt(x:Int) -> Int { return Int(sqrt(Double(x))) }

func sigma(n: Int) -> Int {
    // adding up proper divisors from 1 to sqrt(n) by trial divison
    if n == 1 { return 0 } // definition of aliquot sum
    var result = 1
    let root = sqrt(n)
    for var div = 2; div <= root; ++div {
        if n % div == 0 {
            result += div + n/div
        }
    }
    if root*root == n { result -= root }
    return (result)
}
print(sigma(10))
print(sigma(3))

After updating the for loop I get a runtime error for the last line. Any idea why that happens?

import func Darwin.sqrt
func sqrt(x:Int) -> Int { return Int(sqrt(Double(x))) }

func sigma(n: Int) -> Int {
    // adding up proper divisors from 1 to sqrt(n) by trial divison
    if n == 1 { return 0 } // definition of aliquot sum
    var result = 1
    let root = sqrt(n)
    for div in 2...root where n % div == 0 {
            result += div + n/div
    }
    if root*root == n { result -= root }
    return (result)
}
print(sigma(10))
print(sigma(3)) //<- run time error with for in loop

Solution

  • When you pass 3 to sigma, your range 2...root becomes invalid, because the left side, the root, is less than the right side, 2.

    The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b.

    root is assigned sqrt(n), which means that in order for the 2...root range to remain valid, n must be above 22.

    You can fix by supplying a lower limit for the right side, i.e.

    for div in 2...max(root,2) where n % div == 0 {
        ...
    }
    

    However, at this point your solution with the regular for loop is more readable.