Id like to share my experience in solving the main task from Chapter 9:

Write an app that determines if the following years are leap years: 1800, 1801, 1899, 1900, 2000, 2001, 2003 and 2010. Output should be written to the console in the foll. format: "2000 is a leap year" or "2001 is not a leap year" So the the first idea on algorithm I had was to check somehow if the date Feb 29 exists for every of years in question. At the beginning I thought it would be easy - just to get it as NSDate object and to check if it's true or false. I did'nt know yet that NSDate doesn't know if the date it contains is a real one - all Feb29s were true for it))

Later I found a much easier and more known algorithm how to do it, seems it 's a common way used by almost everyone . I'm posting it here too but first - my hardest way:

HARDEST WAYThe beginning was pretty easy - creating an array. Only I had to search on how to create an array with integers-objects). It turned out the solution is NSNumber

- Code: Select all
`//creating an array and filling it with years to check`

NSMutableArray *yearsToCheck = [[NSMutableArray alloc] init];

[yearsToCheck addObject:[NSNumber numberWithInt:1899]];

[yearsToCheck addObject:[NSNumber numberWithInt:1800]];

[yearsToCheck addObject:[NSNumber numberWithInt:1801]];

[yearsToCheck addObject:[NSNumber numberWithInt:1900]];

[yearsToCheck addObject:[NSNumber numberWithInt:2000]];

[yearsToCheck addObject:[NSNumber numberWithInt:2003]];

[yearsToCheck addObject:[NSNumber numberWithInt:2010]];

Then long figuring out how to make for every year a real date of Feb 29 and how to know if they really existed That meant to make it know about a calendar - Gregorian one) : the 5 lines below helped me to actually lay the the dates on calendar by using NSDateComponents that allows to set Year Month and Day

- Code: Select all
` for (id year in yearsToCheck){ // enumeration - means for every year in the array do the following code:`

//these 5 lines below helped me to actually lay the the dates on calendar by using NSDateComponents that allows to set Year Month and Day

NSDateComponents *dateAppliedOnCalendar = [[NSDateComponents alloc] init];

[dateAppliedOnCalendar setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]];

[dateAppliedOnCalendar setYear:[year integerValue]];// setYear doesnt accept NSNumber, I had to cast integer back

[dateAppliedOnCalendar setMonth:02];

[dateAppliedOnCalendar setDay:29];

...

Here is the important moment: empirically (by means of NSlogs) I understood that when calling getter for NSDateComponents ([dateAppliedOnCalendar date]) it shows Feb 29 if it existed for leap years and !!! Mar 1 if it didnt (i.e. nonleap years). What I have left to do is to compare dates of all years to Feb 29 . Since i didnt manage to do it by comparing NSDates I decided to convert them to NSStings and compare strings . Finally that was also within the topic)

- Code: Select all
` NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];//this stuff was needed to convert date to string`

[dateFormatter setDateStyle:NSDateFormatterMediumStyle]; //this stuff allowed me convert date to the format like "Feb DD, YYYY"

NSString *stringToCompare = [dateFormatter stringFromDate:[dateAppliedOnCalendar date]];//actually converting NSDateComponents object to NSDateObject, then to NSString

...

Finally the comparing by "Feb-29" it-self and NSLogs:

- Code: Select all
` if ([stringToCompare rangeOfString:@"Feb 29"].location != NSNotFound)`

{

NSLog(@"%@ is leap",year);

}

else {

NSLog(@"%@ is not leap",year);

}

}

SEEMS, THE RIGHT WAY when the year is considered like a digit.

THe algorithm is the following:

A year will be a leap year if it is divisible by 4 but not by 100. If a year is divisible by 4 and by 100, it is not a leap year unless it is also divisible by 400.

Thus years such as 1996, 1992, 1988 and so on are leap years because they are divisible by 4 but not by 100. For century years, the 400 rule is important. Thus, century years 1900, 1800 and 1700 while all still divisible by 4 are also exactly divisible by 100. As they are not further divisible by 400, they are not leap years.

Here is the code ( creating the array, then if statement, that is it) :

- Code: Select all
` //creating an array and filling it with years to check`

NSMutableArray *yearsToCheck = [[NSMutableArray alloc] init];

[yearsToCheck addObject:[NSNumber numberWithInt:1899]];

[yearsToCheck addObject:[NSNumber numberWithInt:1800]];

[yearsToCheck addObject:[NSNumber numberWithInt:1801]];

[yearsToCheck addObject:[NSNumber numberWithInt:1900]];

[yearsToCheck addObject:[NSNumber numberWithInt:2000]];

[yearsToCheck addObject:[NSNumber numberWithInt:2003]];

[yearsToCheck addObject:[NSNumber numberWithInt:2010]];

for (id year in yearsToCheck){ // for every year in the array do the following code:

if (([year integerValue]%4 == 0 && [year integerValue]%100 !=0) ||[year integerValue]%400 ==0) {

NSLog(@"%@ is leap",year);

}

else {

NSLog(@"%@ is not leap",year);

}

}