🎉 Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io 🎉
Avatar of EggmanQi

EggmanQi's solution

to Meetup in the Objective-C Track

Published at Jan 02 2019 · 0 comments
Instructions
Test suite
Solution

Calculate the date of meetups.

Typically meetups happen on the same day of the week. In this exercise, you will take a description of a meetup date, and return the actual meetup date.

Examples of general descriptions are:

  • The first Monday of January 2017
  • The third Tuesday of January 2017
  • The wednesteenth of January 2017
  • The last Thursday of January 2017

The descriptors you are expected to parse are: first, second, third, fourth, fifth, last, monteenth, tuesteenth, wednesteenth, thursteenth, friteenth, saturteenth, sunteenth

Note that "monteenth", "tuesteenth", etc are all made up words. There was a meetup whose members realized that there are exactly 7 numbered days in a month that end in '-teenth'. Therefore, one is guaranteed that each day of the week (Monday, Tuesday, ...) will have exactly one date that is named with '-teenth' in every month.

Given examples of a meetup dates, each containing a month, day, year, and descriptor calculate the date of the actual meetup. For example, if given "The first Monday of January 2017", the correct meetup date is 2017/1/2.

Setup

There are two different methods of getting set up to run the tests with Objective-C:

  • Create an Xcode project with a test target which will run the tests.
  • Use the ruby gem objc as a test runner utility.

Both are described in more detail here: http://exercism.io/languages/objective-c

Submitting Exercises

When submitting an exercise, make sure your solution file is in the same directory as the test code.

The submit command will look something like:

exercism submit <path-to-exercism-workspace>/objective-c/meetup/Meetup.m

You can find the Exercism workspace by running exercism debug and looking for the line beginning with Workspace.

Source

Jeremy Hinegardner mentioned a Boulder meetup that happens on the Wednesteenth of every month https://twitter.com/copiousfreetime

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

MeetupTest.m

#import <XCTest/XCTest.h>

#if __has_include("MeetupExample.h")
# import "MeetupExample.h"
# else
# import "Meetup.h"
#endif

@interface MeetupTest : XCTestCase

@end

@implementation MeetupTest

- (void)testMonteenthOfMay2013 {
    NSDate *date = [[[Meetup alloc] initWithYear:2013 andMonth:5]
                    dayForDayOfWeek:MeetupDayOfWeekMonday andOptions:MeetupOptionsTeenth];
    XCTAssertEqualObjects(date, [self dateForMonth:5 day:13 year:2013]);
}

- (void)testSaturteenthOfFebruary2013 {
    NSDate *date = [[[Meetup alloc] initWithYear:2013 andMonth:2]
                    dayForDayOfWeek:MeetupDayOfWeekSaturday andOptions:MeetupOptionsTeenth];
    XCTAssertEqualObjects(date, [self dateForMonth:2 day:16 year:2013]);
}

- (void)testFirstTuesdayOfMay2013 {
    NSDate *date = [[[Meetup alloc] initWithYear:2013 andMonth:5]
                    dayForDayOfWeek:MeetupDayOfWeekTuesday andOptions:MeetupOptionsFirst];
    XCTAssertEqualObjects(date, [self dateForMonth:5 day:7 year:2013]);
}

- (void)testSecondMondayOfApril2013 {
    NSDate *date = [[[Meetup alloc] initWithYear:2013 andMonth:4]
                    dayForDayOfWeek:MeetupDayOfWeekMonday andOptions:MeetupOptionsSecond];
    XCTAssertEqualObjects(date, [self dateForMonth:4 day:8 year:2013]);
}

- (void)testThirdThursdayOfSeptember2013 {
    NSDate *date = [[[Meetup alloc] initWithYear:2013 andMonth:9]
                    dayForDayOfWeek:MeetupDayOfWeekThursday andOptions:MeetupOptionsThird];
    XCTAssertEqualObjects(date, [self dateForMonth:9 day:19 year:2013]);
}

- (void)testFourthSundayOfMarch2013 {
    NSDate *date = [[[Meetup alloc] initWithYear:2013 andMonth:3]
                    dayForDayOfWeek:MeetupDayOfWeekSunday andOptions:MeetupOptionsFourth];
    XCTAssertEqualObjects(date, [self dateForMonth:3 day:24 year:2013]);
}

- (void)testLastThursdayOfOctober2013 {
    NSDate *date = [[[Meetup alloc] initWithYear:2013 andMonth:10]
                    dayForDayOfWeek:MeetupDayOfWeekThursday andOptions:MeetupOptionsLast];
    XCTAssertEqualObjects(date, [self dateForMonth:10 day:31 year:2013]);
}

- (void)testLastWednesdayOfFebruary2012 {
    NSDate *date = [[[Meetup alloc] initWithYear:2012 andMonth:2]
                    dayForDayOfWeek:MeetupDayOfWeekWednesday andOptions:MeetupOptionsLast];
    XCTAssertEqualObjects(date, [self dateForMonth:2 day:29 year:2012]);
}

- (void)testFirstFridayOfDecember2012 {
    NSDate *date = [[[Meetup alloc] initWithYear:2012 andMonth:12]
                    dayForDayOfWeek:MeetupDayOfWeekFriday andOptions:MeetupOptionsFirst];
    XCTAssertEqualObjects(date, [self dateForMonth:12 day:7 year:2012]);
}

#pragma mark - Helper method

- (NSDate *)dateForMonth:(int)month day:(int)day year:(int)year {
    NSDateComponents *components = [[NSDateComponents alloc] init];
    components.month = month;
    components.day = day;
    components.year = year;
    
    return [[NSCalendar currentCalendar] dateFromComponents:components];
}

@end
//
//  Meetup.m
//  exercismOC
//
//  Created by eggman qi on 2019/1/2.
//  Copyright © 2019 EBrainStudio. All rights reserved.
//

#import "Meetup.h"

@interface Meetup ()
@property (nonatomic, strong)NSCalendar *calendar;
@property (nonatomic, assign)NSInteger myYear;
@property (nonatomic, assign)NSInteger myMonth;
@property (nonatomic, assign)NSInteger count;

@end

@implementation Meetup

- (Meetup *)initWithYear:(NSInteger)year andMonth:(NSInteger)month
{
	_calendar = [NSCalendar currentCalendar];
	_count = 1;
	_myYear = year;
	_myMonth = month;
	return self;
}

- (NSDate *)dayForDayOfWeek:(MeetupWeekDay)weekDay andOptions:(MeetupOptions)options
{
	NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
	dateComponents.month = _myMonth;
	dateComponents.year = _myYear;
	
	NSDate *oringalDate = [_calendar dateFromComponents:dateComponents];
	
	NSInteger day = [self getNumberOfDaysInMonth:oringalDate]; 
	for (NSInteger i=1; i<=day; i++) {
		dateComponents.day = i;
		if ([self isDateComponents:dateComponents
					matchDayOfWeek:weekDay 
						andOptions:options]) {
			NSDate *date = [_calendar dateFromComponents:dateComponents];
			return date;
		}
	}

	return nil;
}

- (NSInteger)getNumberOfDaysInMonth:(NSDate *)targetDate {
	NSCalendar *calendar  = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
	NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay 
								   inUnit:NSCalendarUnitMonth
								  forDate:targetDate];
	return range.length;
}

- (BOOL)isDateComponents:(NSDateComponents *)targetDataComponents 
		  matchDayOfWeek:(MeetupWeekDay)weekDay 
			  andOptions:(MeetupOptions)options
{
	NSDate *date = [_calendar dateFromComponents:targetDataComponents];
	targetDataComponents = [_calendar components:NSCalendarUnitMonth|NSCalendarUnitWeekday|NSCalendarUnitWeekOfMonth|NSCalendarUnitDay|NSCalendarUnitYear 
										fromDate:date]; 
	NSInteger numOfWeekDay = [targetDataComponents weekday]; 
	
	if (numOfWeekDay != weekDay) {
		return NO;
	}
	
	if (options == MeetupOptionsLast) {
		NSRange weekRange = [_calendar rangeOfUnit:NSCalendarUnitWeekOfMonth
											inUnit:NSCalendarUnitMonth 
										   forDate:date];
		NSInteger weeksCount=weekRange.length;
		NSInteger week = [targetDataComponents weekOfMonth];
		if (weeksCount == week) {
			return YES;
		}
	}else if (options == MeetupOptionsTeenth) {
		NSInteger day = [targetDataComponents day];
		if (day>=13 && day<=19) {
			return YES;
		}
	}else {
		if (_count == options) {
			return YES;
		}
	}
	
	_count = _count + 1;

	return NO;
}

@end

Community comments

Find this solution interesting? Ask the author a question to learn more.

What can you learn from this solution?

A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

  • What compromises have been made?
  • Are there new concepts here that you could read more about to improve your understanding?