WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

SOLVED: Checkpoint 4: is my logic good?

Forums > 100 Days of SwiftUI

enum Errors: Error {
    case outOfBounds
    case noRoot
}
func rootFinder(_ number: Int) throws -> String {
    for i in 1...100 {
        if number < 1 || number > 10_000 {
            throw Errors.outOfBounds
        } else if number == i * i {
            return "root = \(i)"
        } else {
            throw Errors.noRoot
        }
    }
    return "Help"
}

do {
    let result = try rootFinder(16)
    print(result)
} catch Errors.noRoot{
    print("Didn't find a root")
} catch Errors.outOfBounds {
    print("Out of bounds")
} catch {
    print("There was an error:")
}

1      

Nice work!

Here's feedback I might share during a team code review. Just some things to think about?

number may not be the best name for a variable? Start thinking about descriptive names. True, it is a number. But in your logic what does it represent? Maybe it's a potentialSquare or operand ?

Also, what does the variable i represent? In looping code, it's usually the counter. But in your case, it's the potentialRoot. This makes the next question a little easier to ask, and understand.

If the square of the potentialRoot is greater than your operand, do you still need to loop through the remaining potentialRoots? That is, if your operand is 18, and your potentialRoot is 5, so 5 x 5 = 25, you know that's not a root, and you ALSO know anything past 5 won't be roots either.

Final thought. Your function is nicely named rootFinder(). But you do not return a root! Instead you return a String. Another team code review comment, consider returning an Int, instead of a String. If the function throws, you know there's no root, but if it returns an Int, voila! Root found.

Final team review comment. Your last line is not a root, nor is it an error. Consider adding a new value to your Error enumeration. If you get to an unknown state, throw that error, instead of the Help text.

Keep coding!

1      

Just a couple of pointers

  1. You check number is in range for each loop so might good idea to have it check it once then bail out if out of range.
  2. unless 1 * 1 = number which is the first loop it will throw the error as it never go past
  3. It will never call return "Help"
  4. The only naming I would change is rootFinder as this function is looking for the square root also you put _ in exterrnal parmeter i would use of So this is what I change it to
enum Errors: Error {
    case outOfBounds
    case noRoot
}

func squareRoot(of number: Int) throws -> String {
    guard number > 1 || number <= 10_000 else { throw Errors.outOfBounds } // bail out if not in range

    for i in 1...100 {
        if number == i * i {
            return "sqaure root of \(number) = \(i)" // this read naturally
        }
    }

    throw Errors.noRoot // This after it gone though all the loop numbers and can find a square root
}

do {
    let result = try squareRoot(of: 81) // now it reads naturally
    print(result)
} catch Errors.noRoot{
    print("Didn't find a root")
} catch Errors.outOfBounds {
    print("Out of bounds")
} catch {
    print("There was an error:")
}

1      

enum Errors: Error {
    case outOfBounds
    case noRoot
}
func rootFinder(_ number: Int) throws -> String {
    for i in 1...100 {
        if number > 1 || number < 10_000 {
            if number == i * i {
            return "Root = \(i)"
            }
        } else {
            throw Errors.outOfBounds
        }
    }
    throw Errors.noRoot
}

do {
    let result = try rootFinder(16)
    print(result)
} catch Errors.noRoot{
    print("Didn't find a root")
} catch Errors.outOfBounds {
    print("Out of bounds")
} catch {
    print("There was an error:")
}

Like this?

1      

Yes that better as now it works correctly.

Just one pointer

You still do a check in the for...in loop so it does the check a possible 100 times, it would put it inside the if...else statement so that the for...inloop will not run if it out of bounds. In mine this is what the guard statement checks.

1      

Hacking with Swift is sponsored by Emerge

SPONSORED Optimize your app’s startup time, binary size, and overall performance using Emerge’s advanced app optimization and monitoring tools. Reliably measure app size, speed up your app's startup time with Emerge's Launch Booster, and much more. Emerge is actively used by many of the top mobile development teams in the world.

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.