ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# vlzware's solution

## to Meetup in the C Track

Published at Jul 13 2018 · 1 comment
Instructions
Test suite
Solution

#### Note:

This solution was written on an old version of Exercism. The tests below might not correspond to the solution code, and the exercise may have changed since this code was written.

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.

## Exercises without stub implementations

Like the majority of C programs you will write, this exercise comes without any header file (*.h) or source file (*.c).

### Add the required files

You will need to create these yourself as part of the exercise. This is so that you get to practice deciding on and creating the program's interface yourself, which is an important part of programming in C. It does mean that when you first try to run the tests, they won't compile. They will give you an error similar to:

make: *** No rule to make target 'src/exercise_name.c', needed by 'tests.out'.  Stop.

This error occurs because the makefile attempts to use a file that hasn't been created yet (exercise_name.c). To resolve this error you will need to add a matching file to the src directory. For example, for the error above you would add a file called exercise_name.c.

When you try to run the tests again you will get a slightly different error.

make: *** No rule to make target 'src/exercise_name.h', needed by 'tests.out'.  Stop.

Again the makefile still needs another file that has yet to be created (exercise_name.h). The solution to this error is similar to the last, add the matching file to the src directory. For example, for the above error you would add a file called exercise_name.h

### Add the required declarations

Running the tests a third time you see you will get new errors, similar to:

Compiling tests.out
src/exercise_name.c:1:0: error: ISO C forbids an empty translation unit [-Werror=pedantic]
cc1: all warnings being treated as errors
test/test_exercise_name.c:13:1: error: unknown type name â€˜bar_tâ€™; did you mean â€˜__bar_tâ€™?
bar_t b = foo(a, 2.5);
^~~~~~
__bar_t
test/test_exercise_name.c:15:14: error: storage size of fizz isnâ€™t known
struct baz fizz;
^~~~
test/test_exercise_name.c:29:20: error: implicit declaration of function â€˜fooâ€™ [-Werror=implicit-function-declaration]
bar_t b = foo_function(fizz, 2.5);

This error means that you need to add function, type and variable decarations to the header file to match those the test file is attempting to use. In doing this you will need to look at the build errors and the test code to determine what needs to be declared in the header file.

For example, for the error above you should declare a type named bar_t, a struct called baz and a function named foo(). Additionally we can tell from looking at the above errors that function foo() has two parameters.

The first parameter is passed an argument of fizz and thus should have a type of struct baz. The second parameter is passed 2.5 and so could have one of two types, either float or double. You will need to look at the test code to determine which.

The names of the parameters are not determined by the test code and so are left up to you to decide, though in keeping with C programming practices they should be descriptive but not overly long.

Further, we can see that the the return type expected by the test code is of the type bar_t.

Putting this all together we end up with a function declaration that looks like the following:

// The parameter names are not very good here they should be more descriptive in a real exercise.
// We have decide on a double for the second parameter in this hypothetical example.
bar_t foo(struct baz b, double d);

You should continue to do this for any further similar errors. To check that you have correctly determined the required declaration, just run the tests again and analyse any errors similarly.

Additionally, remember to add any includes to the header file any headers that it itself requires.

### Include guards

Before you are finished with the header file, you should add include guards. Include guards are used to help prevent the file from being included multiple times by accident. If the file was included multiple times then the functions and other items would be declared twice; In C this is an error because the compiler thinks you are trying to declare another different function that has the same name.

To add include guards, add something similar to the following as the first two lines of the header:

#ifndef EXERCISE_NAME_H
#define EXERCISE_NAME_H

And on the very last line:

#endif

### Add the required definitions

Once the header file is complete you may still have build errors similar to the following:

Compiling tests.out
src/exercise_name.c:1:0: error: ISO C forbids an empty translation unit [-Werror=pedantic]
cc1: all warnings being treated as errors
makefile:24: recipe for target 'tests.out' failed
make: *** [tests.out] Error 1

This is because although you have declared all the items you need to, they have not yet been defined. To define the needed items you need to add their implementation to the exercise_name.c file. For the function foo() from the previous example, this would look similar to:

#include "exercise_name.h"

bar_t foo(struct baz b, double d)
{
// Your exercise code here
}

After having resolved these errors you should be ready to start making the tests pass!

## Getting Started

Make sure you have read the C page on the Exercism site. This covers the basic information on setting up the development environment expected by the exercises.

## Passing the Tests

Get the first test compiling, linking and passing by following the three rules of test-driven development.

The included makefile can be used to create and run the tests using the test task.

make test

Create just the functions you need to satisfy any compiler errors and get the test to fail. Then write just enough code to get the test to pass. Once you've done that, move onto the next test.

As you progress through the tests, take the time to refactor your implementation for readability and expressiveness and then go on to the next test.

Try to use standard C99 facilities in preference to writing your own low-level algorithms or facilities by hand.

## 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.

### test_meetup.c

#include "vendor/unity.h"
#include "../src/meetup.h"

void setUp(void)
{
}

void tearDown(void)
{
}

void test_monteenth_of_May_2013(void)
{
TEST_ASSERT_EQUAL_INT(13, meetup_day_of_month(2013, 5, "teenth", "Monday"));
}

void test_monteenth_of_August_2013(void)
{
TEST_IGNORE();               // delete this line to run test
TEST_ASSERT_EQUAL_INT(19, meetup_day_of_month(2013, 8, "teenth", "Monday"));
}

void test_monteenth_of_September_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(16, meetup_day_of_month(2013, 9, "teenth", "Monday"));
}

void test_tuesteenth_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19, meetup_day_of_month(2013, 3, "teenth", "Tuesday"));
}

void test_tuesteenth_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(16, meetup_day_of_month(2013, 4, "teenth", "Tuesday"));
}

void test_tuesteenth_of_August_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(13, meetup_day_of_month(2013, 8, "teenth", "Tuesday"));
}

void test_wednesteenth_of_January_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(16,
meetup_day_of_month(2013, 1, "teenth", "Wednesday"));
}

void test_wednesteenth_of_February_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(13,
meetup_day_of_month(2013, 2, "teenth", "Wednesday"));
}

void test_wednesteenth_of_June_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19,
meetup_day_of_month(2013, 6, "teenth", "Wednesday"));
}

void test_thursteenth_of_May_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(16,
meetup_day_of_month(2013, 5, "teenth", "Thursday"));
}

void test_thursteenth_of_June_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(13,
meetup_day_of_month(2013, 6, "teenth", "Thursday"));
}

void test_thursteenth_of_September_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19,
meetup_day_of_month(2013, 9, "teenth", "Thursday"));
}

void test_friteenth_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19, meetup_day_of_month(2013, 4, "teenth", "Friday"));
}

void test_friteenth_of_August_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19, meetup_day_of_month(2013, 4, "teenth", "Friday"));
}

void test_friteenth_of_September_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(13, meetup_day_of_month(2013, 9, "teenth", "Friday"));
}

void test_saturteenth_of_February_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(16,
meetup_day_of_month(2013, 2, "teenth", "Saturday"));
}

void test_saturteenth_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(13,
meetup_day_of_month(2013, 4, "teenth", "Saturday"));
}

void test_saturteenth_of_October_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19,
meetup_day_of_month(2013, 10, "teenth", "Saturday"));
}

void test_sunteenth_of_May_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19, meetup_day_of_month(2013, 5, "teenth", "Sunday"));
}

void test_sunteenth_of_June_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(16, meetup_day_of_month(2013, 6, "teenth", "Sunday"));
}

void test_sunteenth_of_October_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(13, meetup_day_of_month(2013, 10, "teenth", "Sunday"));
}

void test_first_Monday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(4, meetup_day_of_month(2013, 3, "first", "Monday"));
}

void test_first_Monday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(1, meetup_day_of_month(2013, 4, "first", "Monday"));
}

void test_first_Tuesday_of_May_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(7, meetup_day_of_month(2013, 5, "first", "Tuesday"));
}

void test_first_Tuesday_of_June_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(4, meetup_day_of_month(2013, 6, "first", "Tuesday"));
}

void test_first_Wednesday_of_July_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(3, meetup_day_of_month(2013, 7, "first", "Wednesday"));
}

void test_first_Wednesday_of_August_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(7, meetup_day_of_month(2013, 8, "first", "Wednesday"));
}

void test_first_Thursday_of_September_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(5, meetup_day_of_month(2013, 9, "first", "Thursday"));
}

void test_first_Thursday_of_October_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(3, meetup_day_of_month(2013, 10, "first", "Thursday"));
}

void test_first_Friday_of_November_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(1, meetup_day_of_month(2013, 11, "first", "Friday"));
}

void test_first_Friday_of_December_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(6, meetup_day_of_month(2013, 12, "first", "Friday"));
}

void test_first_Saturday_of_January_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(5, meetup_day_of_month(2013, 1, "first", "Saturday"));
}

void test_first_Saturday_of_February_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(2, meetup_day_of_month(2013, 2, "first", "Saturday"));
}

void test_first_Sunday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(3, meetup_day_of_month(2013, 3, "first", "Sunday"));
}

void test_first_Sunday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(7, meetup_day_of_month(2013, 4, "first", "Sunday"));
}

void test_second_Monday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(11, meetup_day_of_month(2013, 3, "second", "Monday"));
}

void test_second_Monday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(8, meetup_day_of_month(2013, 4, "second", "Monday"));
}

void test_second_Tuesday_of_May_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(14, meetup_day_of_month(2013, 5, "second", "Tuesday"));
}

void test_second_Tuesday_of_June_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(11, meetup_day_of_month(2013, 6, "second", "Tuesday"));
}

void test_second_Wednesday_of_July_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(10,
meetup_day_of_month(2013, 7, "second", "Wednesday"));
}

void test_second_Wednesday_of_August_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(14,
meetup_day_of_month(2013, 8, "second", "Wednesday"));
}

void test_second_Thursday_of_September_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(12,
meetup_day_of_month(2013, 9, "second", "Thursday"));
}

void test_second_Thursday_of_October_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(10,
meetup_day_of_month(2013, 10, "second", "Thursday"));
}

void test_second_Friday_of_November_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(8, meetup_day_of_month(2013, 11, "second", "Friday"));
}

void test_second_Friday_of_December_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(13, meetup_day_of_month(2013, 12, "second", "Friday"));
}

void test_second_Saturday_of_January_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(12,
meetup_day_of_month(2013, 1, "second", "Saturday"));
}

void test_second_Saturday_of_February_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(9, meetup_day_of_month(2013, 2, "second", "Saturday"));
}

void test_second_Sunday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(10, meetup_day_of_month(2013, 3, "second", "Sunday"));
}

void test_second_Sunday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(14, meetup_day_of_month(2013, 4, "second", "Sunday"));
}

void test_third_Monday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(18, meetup_day_of_month(2013, 3, "third", "Monday"));
}

void test_third_Monday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(15, meetup_day_of_month(2013, 4, "third", "Monday"));
}

void test_third_Tuesday_of_May_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(21, meetup_day_of_month(2013, 5, "third", "Tuesday"));
}

void test_third_Tuesday_of_June_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(18, meetup_day_of_month(2013, 6, "third", "Tuesday"));
}

void test_third_Wednesday_of_July_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(17,
meetup_day_of_month(2013, 7, "third", "Wednesday"));
}

void test_third_Wednesday_of_August_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(21,
meetup_day_of_month(2013, 8, "third", "Wednesday"));
}

void test_third_Thursday_of_September_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19, meetup_day_of_month(2013, 9, "third", "Thursday"));
}

void test_third_Thursday_of_October_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(17,
meetup_day_of_month(2013, 10, "third", "Thursday"));
}

void test_third_Friday_of_November_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(15, meetup_day_of_month(2013, 11, "third", "Friday"));
}

void test_third_Friday_of_December_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(20, meetup_day_of_month(2013, 12, "third", "Friday"));
}

void test_third_Saturday_of_January_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(19, meetup_day_of_month(2013, 1, "third", "Saturday"));
}

void test_third_Saturday_of_February_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(16, meetup_day_of_month(2013, 2, "third", "Saturday"));
}

void test_third_Sunday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(17, meetup_day_of_month(2013, 3, "third", "Sunday"));
}

void test_third_Sunday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(21, meetup_day_of_month(2013, 4, "third", "Sunday"));
}

void test_fourth_Monday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(25, meetup_day_of_month(2013, 3, "fourth", "Monday"));
}

void test_fourth_Monday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(22, meetup_day_of_month(2013, 4, "fourth", "Monday"));
}

void test_fourth_Tuesday_of_May_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(28, meetup_day_of_month(2013, 5, "fourth", "Tuesday"));
}

void test_fourth_Tuesday_of_June_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(25, meetup_day_of_month(2013, 6, "fourth", "Tuesday"));
}

void test_fourth_Wednesday_of_July_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(24,
meetup_day_of_month(2013, 7, "fourth", "Wednesday"));
}

void test_fourth_Wednesday_of_August_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(28,
meetup_day_of_month(2013, 8, "fourth", "Wednesday"));
}

void test_fourth_Thursday_of_September_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(26,
meetup_day_of_month(2013, 9, "fourth", "Thursday"));
}

void test_fourth_Thursday_of_October_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(24,
meetup_day_of_month(2013, 10, "fourth", "Thursday"));
}

void test_fourth_Friday_of_November_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(22, meetup_day_of_month(2013, 11, "fourth", "Friday"));
}

void test_fourth_Friday_of_December_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(27, meetup_day_of_month(2013, 12, "fourth", "Friday"));
}

void test_fourth_Saturday_of_January_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(26,
meetup_day_of_month(2013, 1, "fourth", "Saturday"));
}

void test_fourth_Saturday_of_February_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(23,
meetup_day_of_month(2013, 2, "fourth", "Saturday"));
}

void test_fourth_Sunday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(24, meetup_day_of_month(2013, 3, "fourth", "Sunday"));
}

void test_fourth_Sunday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(28, meetup_day_of_month(2013, 4, "fourth", "Sunday"));
}

void test_last_Monday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(25, meetup_day_of_month(2013, 3, "last", "Monday"));
}

void test_last_Monday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(29, meetup_day_of_month(2013, 4, "last", "Monday"));
}

void test_last_Tuesday_of_May_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(28, meetup_day_of_month(2013, 5, "last", "Tuesday"));
}

void test_last_Tuesday_of_June_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(25, meetup_day_of_month(2013, 6, "last", "Tuesday"));
}

void test_last_Wednesday_of_July_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(31, meetup_day_of_month(2013, 7, "last", "Wednesday"));
}

void test_last_Wednesday_of_August_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(28, meetup_day_of_month(2013, 8, "last", "Wednesday"));
}

void test_last_Thursday_of_September_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(26, meetup_day_of_month(2013, 9, "last", "Thursday"));
}

void test_last_Thursday_of_October_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(31, meetup_day_of_month(2013, 10, "last", "Thursday"));
}

void test_last_Friday_of_November_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(29, meetup_day_of_month(2013, 11, "last", "Friday"));
}

void test_last_Friday_of_December_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(27, meetup_day_of_month(2013, 12, "last", "Friday"));
}

void test_last_Saturday_of_January_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(26, meetup_day_of_month(2013, 1, "last", "Saturday"));
}

void test_last_Saturday_of_February_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(23, meetup_day_of_month(2013, 2, "last", "Saturday"));
}

void test_last_Sunday_of_March_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(31, meetup_day_of_month(2013, 3, "last", "Sunday"));
}

void test_last_Sunday_of_April_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(28, meetup_day_of_month(2013, 4, "last", "Sunday"));
}

void test_last_Wednesday_of_February_2012(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(29, meetup_day_of_month(2012, 2, "last", "Wednesday"));
}

void test_last_Wednesday_of_December_2014(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(31,
meetup_day_of_month(2014, 12, "last", "Wednesday"));
}

void test_last_Sunday_of_February_2015(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(22, meetup_day_of_month(2015, 2, "last", "Sunday"));
}

void test_first_Friday_of_December_2012(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(7, meetup_day_of_month(2012, 12, "first", "Friday"));
}

void test_fifth_Friday_of_December_2016(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(30, meetup_day_of_month(2016, 12, "fifth", "Friday"));
}

void test_fifth_Friday_of_February_2013(void)
{
TEST_IGNORE();
TEST_ASSERT_EQUAL_INT(0, meetup_day_of_month(2013, 02, "fifth", "Friday"));
}

int main(void)
{
UnityBegin("test/test_meetup.c");

RUN_TEST(test_monteenth_of_May_2013);
RUN_TEST(test_monteenth_of_August_2013);
RUN_TEST(test_monteenth_of_September_2013);
RUN_TEST(test_tuesteenth_of_March_2013);
RUN_TEST(test_tuesteenth_of_April_2013);
RUN_TEST(test_tuesteenth_of_August_2013);
RUN_TEST(test_wednesteenth_of_January_2013);
RUN_TEST(test_wednesteenth_of_February_2013);
RUN_TEST(test_wednesteenth_of_June_2013);
RUN_TEST(test_thursteenth_of_May_2013);
RUN_TEST(test_thursteenth_of_June_2013);
RUN_TEST(test_thursteenth_of_September_2013);
RUN_TEST(test_friteenth_of_April_2013);
RUN_TEST(test_friteenth_of_August_2013);
RUN_TEST(test_friteenth_of_September_2013);
RUN_TEST(test_saturteenth_of_February_2013);
RUN_TEST(test_saturteenth_of_April_2013);
RUN_TEST(test_saturteenth_of_October_2013);
RUN_TEST(test_sunteenth_of_May_2013);
RUN_TEST(test_sunteenth_of_June_2013);
RUN_TEST(test_sunteenth_of_October_2013);
RUN_TEST(test_first_Monday_of_March_2013);
RUN_TEST(test_first_Monday_of_April_2013);
RUN_TEST(test_first_Tuesday_of_May_2013);
RUN_TEST(test_first_Tuesday_of_June_2013);
RUN_TEST(test_first_Wednesday_of_July_2013);
RUN_TEST(test_first_Wednesday_of_August_2013);
RUN_TEST(test_first_Thursday_of_September_2013);
RUN_TEST(test_first_Thursday_of_October_2013);
RUN_TEST(test_first_Friday_of_November_2013);
RUN_TEST(test_first_Friday_of_December_2013);
RUN_TEST(test_first_Saturday_of_January_2013);
RUN_TEST(test_first_Saturday_of_February_2013);
RUN_TEST(test_first_Sunday_of_March_2013);
RUN_TEST(test_first_Sunday_of_April_2013);
RUN_TEST(test_second_Monday_of_March_2013);
RUN_TEST(test_second_Monday_of_April_2013);
RUN_TEST(test_second_Tuesday_of_May_2013);
RUN_TEST(test_second_Tuesday_of_June_2013);
RUN_TEST(test_second_Wednesday_of_July_2013);
RUN_TEST(test_second_Wednesday_of_August_2013);
RUN_TEST(test_second_Thursday_of_September_2013);
RUN_TEST(test_second_Thursday_of_October_2013);
RUN_TEST(test_second_Friday_of_November_2013);
RUN_TEST(test_second_Friday_of_December_2013);
RUN_TEST(test_second_Saturday_of_January_2013);
RUN_TEST(test_second_Saturday_of_February_2013);
RUN_TEST(test_second_Sunday_of_March_2013);
RUN_TEST(test_second_Sunday_of_April_2013);
RUN_TEST(test_third_Monday_of_March_2013);
RUN_TEST(test_third_Monday_of_April_2013);
RUN_TEST(test_third_Tuesday_of_May_2013);
RUN_TEST(test_third_Tuesday_of_June_2013);
RUN_TEST(test_third_Wednesday_of_July_2013);
RUN_TEST(test_third_Wednesday_of_August_2013);
RUN_TEST(test_third_Thursday_of_September_2013);
RUN_TEST(test_third_Thursday_of_October_2013);
RUN_TEST(test_third_Friday_of_November_2013);
RUN_TEST(test_third_Friday_of_December_2013);
RUN_TEST(test_third_Saturday_of_January_2013);
RUN_TEST(test_third_Saturday_of_February_2013);
RUN_TEST(test_third_Sunday_of_March_2013);
RUN_TEST(test_third_Sunday_of_April_2013);
RUN_TEST(test_fourth_Monday_of_March_2013);
RUN_TEST(test_fourth_Monday_of_April_2013);
RUN_TEST(test_fourth_Tuesday_of_May_2013);
RUN_TEST(test_fourth_Tuesday_of_June_2013);
RUN_TEST(test_fourth_Wednesday_of_July_2013);
RUN_TEST(test_fourth_Wednesday_of_August_2013);
RUN_TEST(test_fourth_Thursday_of_September_2013);
RUN_TEST(test_fourth_Thursday_of_October_2013);
RUN_TEST(test_fourth_Friday_of_November_2013);
RUN_TEST(test_fourth_Friday_of_December_2013);
RUN_TEST(test_fourth_Saturday_of_January_2013);
RUN_TEST(test_fourth_Saturday_of_February_2013);
RUN_TEST(test_fourth_Sunday_of_March_2013);
RUN_TEST(test_fourth_Sunday_of_April_2013);
RUN_TEST(test_last_Monday_of_March_2013);
RUN_TEST(test_last_Monday_of_April_2013);
RUN_TEST(test_last_Tuesday_of_May_2013);
RUN_TEST(test_last_Tuesday_of_June_2013);
RUN_TEST(test_last_Wednesday_of_July_2013);
RUN_TEST(test_last_Wednesday_of_August_2013);
RUN_TEST(test_last_Thursday_of_September_2013);
RUN_TEST(test_last_Thursday_of_October_2013);
RUN_TEST(test_last_Friday_of_November_2013);
RUN_TEST(test_last_Friday_of_December_2013);
RUN_TEST(test_last_Saturday_of_January_2013);
RUN_TEST(test_last_Saturday_of_February_2013);
RUN_TEST(test_last_Sunday_of_March_2013);
RUN_TEST(test_last_Sunday_of_April_2013);
RUN_TEST(test_last_Wednesday_of_February_2012);
RUN_TEST(test_last_Wednesday_of_December_2014);
RUN_TEST(test_last_Sunday_of_February_2015);
RUN_TEST(test_first_Friday_of_December_2012);
RUN_TEST(test_fifth_Friday_of_December_2016);
RUN_TEST(test_fifth_Friday_of_February_2013);

UnityEnd();
return 0;
}

### src/meetup.c

#include "meetup.h"
#include <string.h>

const char* days[] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};

#define MAXWEEKS 6
#define MAXDAYS 7
int curr_month[MAXWEEKS][MAXDAYS];

int is_leap(const int year);
int get_week_day_num(const char* day);
int get_week_day(const int day, const int month, int year);
int get_first_day(const int year, const int month);
void construct_month(const int year, const int month);
int parse_modif(const char *modif);

/*
Accepted modifiers:
"first", "second", "third", "fourth", "fifth",
"last" and "teenth" (meaning 13 <= "teenth" <= 19)

month is 1..12
*/
int meetup_day_of_month(const int year, const int month, const char *modif,
const char *day)
{
if ((month < 1) || (month > 12))
return 0;

int day_num = get_week_day_num(day);
if (day_num == -1)
return 0;

construct_month(year, month);

int i;
if (strcmp("teenth", modif) == 0) {
for (i = 0; i < MAXWEEKS; i++)
if (curr_month[i][day_num] > 12)
return curr_month[i][day_num];
return 0;
}

if (strcmp("last", modif) == 0) {
for (i = MAXWEEKS -1; i >= 0; i--)
if (curr_month[i][day_num] > 0)
return curr_month[i][day_num];
return 0;
}

int count = 0;
int target = parse_modif(modif);

for (i = 0; i < MAXWEEKS; i++) {
if (curr_month[i][day_num] > 0)
if (++count == target)
return curr_month[i][day_num];
}
return 0;
}

int is_leap(const int year)
{
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}

int get_week_day_num(const char* day)
{
int i;
for (i = 0; i < 7; i++) {
if (strcmp(days[i], day) == 0)
return i;
}
return -1;
}

/* https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week\
#Implementation-dependent_methods */
int get_week_day(int d, const int m, int y)
{
return (d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7;
}

int get_first_day(const int year, const int month)
{
return get_week_day(1, month, year);
}

void construct_month(const int year, const int month)
{
memset(curr_month, 0, sizeof(curr_month));
int months[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
if (is_leap(year))
months[1] = 29;

int week_day = get_first_day(year, month);
int week = 0;
int date;

for (date = 1; date <= months[month -1]; date++) {
curr_month[week][week_day] = date;
if (++week_day == MAXDAYS) {
week_day = 0;
week++;
}
}
}

int parse_modif(const char *modif)
{
return	(strcmp("first", modif)  == 0) ? 1 :
(strcmp("second", modif) == 0) ? 2 :
(strcmp("third", modif)  == 0) ? 3 :
(strcmp("fourth", modif) == 0) ? 4 :
(strcmp("fifth", modif)  == 0) ? 5 : -1;
}

### src/meetup.h

#ifndef MEETUP_H
#define MEETUP_H

int meetup_day_of_month(const int year, const int month, const char *modif,
const char *day);

#endif

## Community comments

Find this solution interesting? Ask the author a question to learn more.
Solution Author
commented over 2 years ago

somewhat lower level solution without "time.h"

### 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?