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

Checkpoint 9: can someone help me

Forums > 100 Days of SwiftUI

I kind of understand hoe to make the logic but i don't know how to do it in a single line

   

I haven't looked at the particular challenge in question. So my comment here is in a general context and not about this particular quesiton (which I'll also go look at when time permits):

As someone who's been doing this for over 3 decades, there's a universal truth about "clever" solutions: single line "solutions" to complex problems usually end up being more trouble than they're worth in terms of how long it takes to figure it out, code readability and maintainability, friendliness to the next developer (which might be you in a year after you've forgotten all that cleverness), and changing specs or functionalities.

There. That's my cranky old guy warning. :) Now I'll go look up this particular thing and see if I can help :)

   

Try breaking it down one step at a time. First, write out your code using multiple lines. Then see what parts you can eliminate and what parts you can combine. Post what you have so far, if you're stuck.

   

Follow Vince's advice and break down the problem one step at a time.

Don't peek! But here's a previously posted solution:

Checkpoint 9 Help

   

I used a closure since it's supposed to be one line. Looks like the code works but not sure if my reasoning in the comments is correct.

// Chained the optional array of Integer "[Int]?" to  "randomElement()" which by default is also an optional in case the array is empty, then added nil coalescing to run the random number generator "Int.random(in:1...100)" in case of nil or absent value.

let randomIntReturns = {(array: [Int]?) -> Int in array? .randomElement() ?? Int.random(in: 1...100)}

//testing function
randomIntReturns([])
randomIntReturns([3,4,12,68,1233])

   

Phew! Inspired to post for the first time after completing this checkpoint. For the first time in the first fortnight, I had to watch every video again, after I'd made a first attempt at the checkpoint, before I got to my solution.

Exactly as Vince said, breaking it down step by step helped immeasurably.

First, I thought I'd create optional arrays to test the conditions of the checkpoint:

var myArray: [Int]? = [Int]()          // creates an empty optional array
var myRealArray: [Int]? = [1, 2, 3, 4] // creates an filled optional array
var doesNtExist: [Int]? = nil          // this array does not exist - it is not 'empty'
                                       // myArray and myRealArray COULD be non-optional if i wanted

Then I thought I'd practice using them to check one of the conditions - does the optional exist. First I wrote an if let for each array individually, then a function containing an if let into which an optional array could be passed:

if let myArray = myArray {             // all three arrays are optional, this one is empty
    print("Optional array exists")
    print(myArray)
}

if let myRealArray = myRealArray {     // 'if let' only works on optionals and _UNWRAPS_ them into a
    print("Optional array exists")     // temporary var or constant, traditionally of the same name
    print(myRealArray)                 // this array _has_ values which are printed
}

if let doesNtExist = doesNtExist {     // this optional array has NO value and does not
    print("Optional array exists")     // satisfy the 'if' because of that fact
    print(doesNtExist)
} else {                               // if let runs the code if the optional exists
    print("That array does not exist!")// but you can have an else statement too to do something
}

// convert our 'ifs' to a function

func doesArrayExist(name: [Int]?) {    // has to accept optional arrays; if we tell Swift we are
    if let name = name {               // passing a non-optional array, that's what it expects
        print("If let says: Optional array exists") // and so 'if let' would make no sense
        print(name)
    } else {
        print("If let says: That optional array does not exist!")
    }
}

doesArrayExist(name: myArray)
doesArrayExist(name: myRealArray)
doesArrayExist(name: doesNtExist)

I took my ages to get to that function!

But I thought it would be easy enough to reverse the order of the function with a guard let:

func doesArrayExistGuarded(name: [Int]?) { // guard let allows code to stop running as soon as a
    guard let name = name else {           // check has not been satisfied
        print("Guard says: That optional arrays does not exist")
        return
    }
    print("Guard says: Optional array exists")
    print(name)
}

doesArrayExistGuarded(name: myArray)
doesArrayExistGuarded(name: myRealArray)
doesArrayExistGuarded(name: doesNtExist)

I was fairly sure the second condition would be easy to implement with .randomElement() and so combined that with nil coalescing. I used my three test optional arrays with three different returns, for reasons that might make sense only to me! (it felt right) The optional array with values should return one of the values from that array and so the nil coalescing will never be needed. Again, for reasons only known to me, I decided to test all this in a while loop to run it three times. Maybe I'm Irish ("To be sure! To be sure! To be sure!")

var i = 0
while i < 2 {
    let randomNo1 = myRealArray?.randomElement() ?? Int.random(in: 5...100)  // passes - array exists and has values
    let randomNo2 = myArray?.randomElement() ?? Int.random(in: 5...100)      // fails - random element returns 'nil'
    let randomNo3 = doesNtExist?.randomElement() ?? Int.random(in: 101...200)// fails - optional array does not exist so 'nil' is returned
    print("\(randomNo1) & \(randomNo2) & \(randomNo3)")
    i += 1
}

When that worked I thought I could nail the one-line function:

func checkpoint(arr: [Int]?) -> Int { arr?.randomElement() ?? Int.random(in: 1...100) }

Then I thought I could be clever and pass my three arrays into the function in a loop. This caused ten minutes of head scratching until I realised the for loop was being passed an array containing optional arrays of integers. After I had said that out loud, the notation "[[Int]?]" formed in my brain, and the problem was solved:

// an arrary of optional integer arrays
let arrayOfArrays: [[Int]?] = [myArray, myRealArray, doesNtExist]

// loop through the array, calling the function
for i in arrayOfArrays {
    print("generating random number: ")
    print(checkpoint(arr: i))
}

I loved this challenge, even though it took me three times longer than any other so far!

   

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

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.