Leap Year Exercise in Lesson 11 (Making Decisions.Playground)

I am looking for an answer to the Leap Year (last) exercise in Lesson 11 (Making Decisions.Playground) of App Development with Swift, can anyone help, please.

Replies

Post the code you've written so far, and someone will probably help get it working.

I solved the problem as per below image, but I have not used func number(year, isDivisibleBy: 4). So, obviously my approach was incorrect. Appreciate anyone give me the correct answer, thanks in advance.


func isLeapYear(_ year: Int) -> Bool {

if year % 400 == 0 {

return true

} else if year % 100 == 0 {

return false

} else {

return year % 4 == 0

}

}


The original exercise is:


Exercise: Leap Years

To decide if a year is a leap year, there are several decisions that have to be made:

Is the year divisible by 4?

If so, is the year divisible by 100?

If not, it is a leap year.

If so, is the year divisible by 400?

If not, it is not a leap year.

If so, it is a leap year.

These decisions can be made inside a function.

The number(_:, isDivisibleBy:) function has been built into this playground to make this exercise easier. Below is an incomplete function for deciding if a given year is a leap year:


func isLeapYear(_ year: Int) -> Bool {

if number(year, isDivisibleBy: 4) {

/

return true

} else {

return false

}

}

/

isLeapYear(2000)

/

isLeapYear(1900)

/

isLeapYear(2012)

/

isLeapYear(2017)

Your code, but using the number(_:isDivisibleBy:) function instead of each modulo expression would be:


func isLeapYear(_ year: Int) -> Bool {
    if number(year, isDivisibleBy: 400) {
        return false
    } else if number(year, isDivisibleBy: 100) {
        return true
    } else  {
        return number(year, isDivisibleBy: 4)
    }
}


That divisibility function probably simply uses the modulo (%) operator, but there's good reason for writing and using the function: imagine you later decide to use a different technique to determine divisibility, then you could just change the internals of that function instead of changing every line of code containing a modulo expression in your original version of the leap year function.

  • Works okay. Thanks

Add a Comment

Oh! Thank you very much. I am learning Xcode and Swift according to materials provided by Apple, is this the right place for me to post questions on the learning materials?

func isLeapYear(_ year: Int) -> Bool {
    if number(year, isDivisibleBy: 400) {
        return true
    } else if number(year, isDivisibleBy: 100) {
        return false
    } else {
        return number(year, isDivisibleBy: 4)
    }
    }


There is right code, goldsdad mixed up string 04-06, they should be vice versa.

Good catch. Thanks!

Greetings, could anyone explain this solution to me please?

The task itself says:

func isLeapYear(_ year: Int) -> Bool {
    if number(year, isDivisibleBy: 4) {
        // Fill in this code
     return true
    } else {
     return false
    }
}


So the code should be filled in after the commented string.


As far as I understood from the task, we should start with function number(year, isDivisibleBy: 4), than 100, then 400.

The solution above does the opposite: it starts with division by 400 and ends by 4.

Just got to this problem this morning.

This follows the order of the question:


func isLeapYear(_ year: Int) -> Bool {
    if number(year, isDivisibleBy: 4) {
        if number(year, isDivisibleBy: 100) {
            if number(year, isDivisibleBy: 400) {
                return true
            } else {
                return false
            }
        } else { 
            return true
        } 
    } else {
        return false
    }
}

Thank you for posting this! The comments on this page helped me alot. I still wanted to find out why the code was supposed to be written the way it was written in the asnwers to your question. After an hour of trying this was my answer 🙂:


func isLeapYear(_ year: Int) -> Bool {

if number(year, isDivisibleBy: 4) {

if number(year, isDivisibleBy: 100) {

if number(year, isDivisibleBy: 400) {

return true

} else {

}

return false

}

}

return true

}

Goodness this was a tough one! As I learn code one thing I’m really learning is that there are a lot of ways to get the same results. My results are the same as manacus, but I thought it would be helpful to someone else to understand why I think this is easiest. When using the ifelse argument, swift give you a few input boxes as guides. The key to making it work is not necessarily filling in the boxes in order but instead filling them in as you would read the argument. So that you are clear with “else” statement you should be filling at that time. If the answer is true then the return should be the next argument, but it was easier to skip that and instead fill in the statement for if that argument was false first, and then return back to the example of if it was true.

Hope that makes sense.

I did it like this....Any comments? (I did change what they gave a bit)


func isItLeapYear(year: Int) -> Bool {

if year % 4 != 0 {

print("Case No. 1; The year \(year) is not leap year because it is not evenly divisible by 4.")

return false

}

else if year % 100 != 0 {

print("Case No. 2; The year \(year) is a leap year because it is not divisible by 100.")

return true

}

else if year % 400 == 0 {

print("Case No. 3; The year \(year) is a leap year because it is evenly divisible by 400.")

return true

}

else {

print("Case No. 4; The year \(year) is not a leap year because it not evenly divisible by 400.")

return false

}

}


isItLeapYear(year: 2000) //Should be true


isItLeapYear(year: 1900) //Should be false


isItLeapYear(year: 2012) //Should be true


isItLeapYear(year: 2017) //Should be false

The logic is OK, as rule for leap year is the following :

  1. if divisible by 4 and not divisible by 100, or
  2. if divisible by 400.

However, the message you give to user are not very didactic.


I would write :


func isItLeapYear(_ year: Int) -> Bool {
    if year % 4 != 0 {
        print("Case No. 1; The year \(year) is not leap year because it is not evenly divisible by 4.")
        return false
    }
    else if year % 100 != 0  {
        print("Case No. 2; The year \(year) is a leap year because it is divisible by 4 and non centenal.")
        return true
    }
    else if year % 400 == 0  {
        print("Case No. 3; The year \(year) is a leap year because it is divisible by 4, is centenal divisible by 400.")
        return true
    }
    else {
        print("Case No. 4; Even though it is divisible by 4, the year \(year) is not a leap year because it is a centenal, but not divisible by 400.")
        return false
    }
}

You get these messages:

Case No. 1; The year 2018 is not leap year because it is not evenly divisible by 4.

Case No. 2; The year 2020 is a leap year because it is divisible by 4 and non centenal.

Case No. 3; The year 2000 is a leap year because it is divisible by 4, is centenal and divisible by 400.

Case No. 4; Even though it is divisible by 4, the year 1900 is not a leap year because it is a centenal, but not divisible by 400.


For fun, you could also compare with today's year:

let today = Date()
let calendar = Calendar.current
let thisYear = calendar.component(.year, from: today)

func isItLeapYear(_ year: Int) -> Bool {
    let isVerb = thisYear >= year ? thisYear == year ? "is" : "was" : "will be"
    let isNotVerb = thisYear >= year ? thisYear == year ? "is not" : "was not" : "will not be"
    if year % 4 != 0 {
        print("Case No. 1; The year \(year) \(isNotVerb) leap year because it is not divisible by 4.")
        return false
    }
    else if year % 100 != 0  {
        print("Case No. 2; The year \(year) \(isVerb) a leap year because it is divisible by 4 and \(isNotVerb) a centenal.")
        return true
    }
    else if year % 400 == 0  {
        print("Case No. 3; The year \(year) \(isVerb) a leap year because it \(isVerb) a centenal and divisible by 400.")
        return true
    }
    else {
        print("Case No. 4; Even though it is divisible by 4, the year \(year) \(isNotVerb) a leap year because it \(isVerb) a centenal, but not divisible by 400.")
        return false
    }
}

and get:

Case No. 1; The year 2017 was not leap year because it is not divisible by 4.

Case No. 1; The year 2018 is not leap year because it is not divisible by 4.

Case No. 1; The year 2019 will not be leap year because it is not divisible by 4.


Case No. 2; The year 2016 was a leap year because it is divisible by 4 and was not a centenal.

Case No. 2; The year 2020 will be a leap year because it is divisible by 4 and will not be a centenal.


Case No. 3; The year 2000 was a leap year because it was a centenal and divisible by 400.

Case No. 3; The year 2400 will be a leap year because it will be a centenal and divisible by 400.


Case No. 4; Even though it is divisible by 4, the year 1900 was not a leap year because it was a centenal, but not divisible by 400.

Case No. 4; Even though it is divisible by 4, the year 2100 will not be a leap year because it will be a centenal, but not divisible by 400.

This is how I made it, it is a little bit confusing at the beginning. Remember that there is already a function within the playground that tells you if that year is divisible by that number, that function is: number(_:, isDivisibleBy: )


func isLeapYear(_ year: Int) -> Bool {

if number(year, isDivisibleBy: 4) {

if number(year, isDivisibleBy: 100){

if number(year, isDivisibleBy: 400){

return true

}else {

return false

}

}else {

return true

}

}else {

return false

}

}

Best solution found for this problem using SWIFT 5.3 and Xcode 12.

Put it into playgrounds, call the checkLeapYear function passing a year into it and play around.

func checkLeapYear(year: Int) {
    if year % 4 == 0{
        if year % 100 == 0 {
            if year % 400 == 0{
                print("\(year) is a Leap Year!")
            } else {
                print("\(year) is NOT a Leap Year!")
            }
        } else {
            print("\(year) is a Leap Year!")
        }
    } else {
        print("\(year) is NOT a Leap Year!")
    }
}

The algorithm is quite tricky so I suggest you use the following logic when performing it on your own:
  1. If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5.

  2. If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.

  3. If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.

  4. The year is a leap year.

  5. The year is not a leap year.

func leapYear(_ year: Int) {

if year % 4 == 0 {

    if year % 100 == 0 && year % 400 != 0 {

        print("\(year) - Not a leap year!")

    } else {

        print("\(year) - Leap year!")

        }

    } else {

        print("\(year) - Not a leap year!")

    }

}

HI all! I apologise if question is simple (I'm a complete beginner in programming). I want to enter "leapYear(2021)" and I want to see that given year is leap year or not. I want to make this code short and the question is why if I remove last else I do not get output: "2021 - Not a leap year!"