Need some help with Checkpoint 4

 Feb '22 Hi everybody! I am currently on Checkpoint 4 and there are some things I don't understand. I wrote a function that's supposed to return a square root of a given number, as well as handle errors that may occur. Here's my code: ``````enum SquareRootErrors: Error { case outOfBounds, noRoot } func findSquareRoot (for myNumber: Int) throws -> Int { for i in 1...10_000 { if myNumber < 1 || myNumber > 10_000 { throw SquareRootErrors.outOfBounds } else if myNumber == 0 { throw SquareRootErrors.noRoot } else if myNumber == i * i { print ("The square root of \(myNumber) is \(i)") } } return myNumber } let myNumber = 64 do { let result = try findSquareRoot(for: myNumber) print(result) } catch SquareRootErrors.outOfBounds { print("The number you provided isn't within the accepted range") } catch SquareRootErrors.noRoot { print("The number of your choice has no square root") } catch { print("Something went wrong.") } `````` The code sort of works. However, apart from printing the result, it also prints the number alone. It's understandable, since I wrote return myNumber, but I have no idea how to get rid of that part, so that only the square root is printed (as the function should return an integer). When I delete the return part, it gives me a warning. Also, is myNumber = 0 the only case when there is no root or am I missing something? I know these are probably very trivial things to ask, but I just didn't want to take an easy route and look for the whole solution. Thanks in advance! 1 Feb '22 Stop coding for 10 minutes. Now try to find the square root of 9. Get out a piece of paper and write down the numbers from 1 to 12. Follow your logic for 1. Write down every decision your code makes. Follow your logic for 2. Write down every decision your code makes. Continue this paper trail for the first 12 numbers. Do you see any repetition? Do you see unnecessary decisions being made? Here's one... why are you attempting 11 * 11? This number is WAAAAAAY greater than 9! In this example you stopped at 12. But your code takes this all the way up to 10_000. What other problems did you uncover while running your square root solution on paper? Coding, whether in Swift, JAVA, C++, Basic, Fortran, Visual Basic, is a lot of puzzle solving. It's not your Swift that's the problem right now. It's the logic you're using to solve the puzzle. How would you describe this solution to a young student? We could just tell you the answer! But you should probably try to solve this one on your own. First, solve the puzzle. Then figure out the Swift loops, variables, returns, and print statements. We've all been in your shoes. We're here to answer more questions, but give this another try first. 3 Feb '22 `@grabapprehensive` Well done you nearly there but this ( `} else if myNumber == 0 {` ) will never be called as if `myNumber` is zero it will be caught by the `outOfBounds` error. The only another thing is you check the number is in the range everytime you go though the loop, so you might want to think about a `guard` to bail out if the number is out side the range. `@Obelix` is right that the loop alway goes to 10_000 when noRoot found. So putting the limit of input number stops this happening The last thing is you return the orginal number! here your code amended slightly. hope this is clear. ``````func findSquareRoot (for myNumber: Int) throws -> Int { // bail out if number is not between the range guard myNumber >= 1 && myNumber <= 10000 else { throw SquareRootErrors.outOfBounds } // change the end range to input number to stop loop doing extra work for i in 1...myNumber { if myNumber == i * i { // return the root number of i return i } } // If you get here no root number found throw SquareRootErrors.noRoot } let myNumber = 101 do { let result = try findSquareRoot(for: myNumber) print ("The square root of \(myNumber) is \(result)") } catch SquareRootErrors.outOfBounds { print("The number you provided isn't within the accepted range") } catch SquareRootErrors.noRoot { print("The number of your choice has no square root") } catch { print("Something went wrong.") }`````` 2 Feb '22 You can limit the number of times you go through the central loop even more: ``````for i in 1...myNumber { //if i * i > myNumber, we know we will never hit a match // so we can bail early let i2 = i * i guard i2 < myNumber else { break } if myNumber == i2 { return i } }`````` Without a `guard` like this, your loop would run 101 times for input `101`. With it, it will only run 11 times (because `10 * 10 == 100` and `11 * 11 == 121`, so we know it's impossible to find an answer if we keep going higher). 2 Feb '22 Thank you so much for your replies. I @Obelix - thank you for giving me food for thought. I realized that my code ran up to 10_000 every single time, no matter if myNumber would be 1, 4, or 9999. Also, the line: ``````> else if myNumber == 0 { throw SquareRootErrors.noRoot`````` makes no sense, as 0 is out of the range I'm working with. I do not understand why it took me so long to see it! Thank you again for trying to change not only my code, but my line of reasoning. As I'm typing this, I noticed that there are another comments from @NigelGee and @roosterboy - now, with your improvements, it all makes sense. I hope one day I'll be able to help somebody here, just like you did. It's a loooong way to go, but also if you told me 3 weeks ago that I'd be writing pieces of code like this I wouldn't believe you. Have a great day and thanks for being so supportive ;) 2 Jun '22 I'm trying to understand why, when I change: `guard number < 10_001 && number > 1 else {` to: `guard number < 10_001 && number > 0 else {` in my playground, it goes from working as expected to saying "The playground encountered a crash and could not finish executing." "0 is out of range." prints on the console. Xcode 14 beta 2, although I doubt that's relevant. Here's the rest of the code & thanks in advance for clues! : ``````import Foundation enum SquareRootError: Error { case outofbounds, cantfind } func squareRoot(of number: Int) throws -> Int { guard number < 10_001 && number > 0 else { throw SquareRootError.outofbounds } for i in 1...number/2 { if i * i == number { return i } } throw SquareRootError.cantfind } for i in 0...10_002 { do { let foundRoot = try squareRoot(of: i) print("The square root of \(i) is \(foundRoot).") } catch SquareRootError.cantfind { print("Can't find Int square root for \(i).") } catch SquareRootError.outofbounds { print("\(i) is out of range.") } }`````` 1 Jul '22 Because the very first value in your `for` loop triggers the `guard` condition in your function. ``````for i in 0...10_002 { .... }`````` The `for` loop starts at `0`. ``````guard number < 10_001 && number > 0 else { throw SquareRootError.outofbounds }`````` If the `guard` condition encounters a `0`, it throws an `outofbounds` error. And then you get a crash here: ``````for i in 1...number/2 { ... }`````` because when the `squareRoot` function is given `1` to process, the `for` loop looks like this: ``````for i in 1...0.5 { ... }`````` and that triggers an error since a range's lower bound must be smaller than its upper bound. And why are you dividing `number` by `2` anyway? 1

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

You are not logged in