# elvanja's solution

## to Meetup in the Elixir Track

Published at Jul 13 2018 · 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.

## Running tests

Execute the tests with:

``````\$ elixir meetup_test.exs
``````

### Pending tests

In the test suites, all but the first test have been skipped.

Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol.

For example:

``````# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end
``````

Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the test suite.

``````# ExUnit.configure exclude: :pending, trace: true
``````

For more detailed information about the Elixir track, please see the help page.

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

### meetup_test.exs

``````if !System.get_env("EXERCISM_TEST_EXAMPLES") do
end

ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true)

defmodule MeetupTest do
use ExUnit.Case

# @tag :pending
test "monteenth of may 2013" do
assert Meetup.meetup(2013, 5, :monday, :teenth) == {2013, 5, 13}
end

@tag :pending
test "monteenth of august 2013" do
assert Meetup.meetup(2013, 8, :monday, :teenth) == {2013, 8, 19}
end

@tag :pending
test "monteenth of september 2013" do
assert Meetup.meetup(2013, 9, :monday, :teenth) == {2013, 9, 16}
end

@tag :pending
test "tuesteenth of march 2013" do
assert Meetup.meetup(2013, 3, :tuesday, :teenth) == {2013, 3, 19}
end

@tag :pending
test "tuesteenth of april 2013" do
assert Meetup.meetup(2013, 4, :tuesday, :teenth) == {2013, 4, 16}
end

@tag :pending
test "tuesteenth of august 2013" do
assert Meetup.meetup(2013, 8, :tuesday, :teenth) == {2013, 8, 13}
end

@tag :pending
test "wednesteenth of january 2013" do
assert Meetup.meetup(2013, 1, :wednesday, :teenth) == {2013, 1, 16}
end

@tag :pending
test "wednesteenth of february 2013" do
assert Meetup.meetup(2013, 2, :wednesday, :teenth) == {2013, 2, 13}
end

@tag :pending
test "wednesteenth of june 2013" do
assert Meetup.meetup(2013, 6, :wednesday, :teenth) == {2013, 6, 19}
end

@tag :pending
test "thursteenth of may 2013" do
assert Meetup.meetup(2013, 5, :thursday, :teenth) == {2013, 5, 16}
end

@tag :pending
test "thursteenth of june 2013" do
assert Meetup.meetup(2013, 6, :thursday, :teenth) == {2013, 6, 13}
end

@tag :pending
test "thursteenth of september 2013" do
assert Meetup.meetup(2013, 9, :thursday, :teenth) == {2013, 9, 19}
end

@tag :pending
test "friteenth of april 2013" do
assert Meetup.meetup(2013, 4, :friday, :teenth) == {2013, 4, 19}
end

@tag :pending
test "friteenth of august 2013" do
assert Meetup.meetup(2013, 8, :friday, :teenth) == {2013, 8, 16}
end

@tag :pending
test "friteenth of september 2013" do
assert Meetup.meetup(2013, 9, :friday, :teenth) == {2013, 9, 13}
end

@tag :pending
test "saturteenth of february 2013" do
assert Meetup.meetup(2013, 2, :saturday, :teenth) == {2013, 2, 16}
end

@tag :pending
test "saturteenth of april 2013" do
assert Meetup.meetup(2013, 4, :saturday, :teenth) == {2013, 4, 13}
end

@tag :pending
test "saturteenth of october 2013" do
assert Meetup.meetup(2013, 10, :saturday, :teenth) == {2013, 10, 19}
end

@tag :pending
test "sunteenth of may 2013" do
assert Meetup.meetup(2013, 5, :sunday, :teenth) == {2013, 5, 19}
end

@tag :pending
test "sunteenth of june 2013" do
assert Meetup.meetup(2013, 6, :sunday, :teenth) == {2013, 6, 16}
end

@tag :pending
test "sunteenth of october 2013" do
assert Meetup.meetup(2013, 10, :sunday, :teenth) == {2013, 10, 13}
end

@tag :pending
test "first monday of march 2013" do
assert Meetup.meetup(2013, 3, :monday, :first) == {2013, 3, 4}
end

@tag :pending
test "first monday of april 2013" do
assert Meetup.meetup(2013, 4, :monday, :first) == {2013, 4, 1}
end

@tag :pending
test "first tuesday of may 2013" do
assert Meetup.meetup(2013, 5, :tuesday, :first) == {2013, 5, 7}
end

@tag :pending
test "first tuesday of june 2013" do
assert Meetup.meetup(2013, 6, :tuesday, :first) == {2013, 6, 4}
end

@tag :pending
test "first wednesday of july 2013" do
assert Meetup.meetup(2013, 7, :wednesday, :first) == {2013, 7, 3}
end

@tag :pending
test "first wednesday of august 2013" do
assert Meetup.meetup(2013, 8, :wednesday, :first) == {2013, 8, 7}
end

@tag :pending
test "first thursday of september 2013" do
assert Meetup.meetup(2013, 9, :thursday, :first) == {2013, 9, 5}
end

@tag :pending
test "first thursday of october 2013" do
assert Meetup.meetup(2013, 10, :thursday, :first) == {2013, 10, 3}
end

@tag :pending
test "first friday of november 2013" do
assert Meetup.meetup(2013, 11, :friday, :first) == {2013, 11, 1}
end

@tag :pending
test "first friday of december 2013" do
assert Meetup.meetup(2013, 12, :friday, :first) == {2013, 12, 6}
end

@tag :pending
test "first saturday of january 2013" do
assert Meetup.meetup(2013, 1, :saturday, :first) == {2013, 1, 5}
end

@tag :pending
test "first saturday of february 2013" do
assert Meetup.meetup(2013, 2, :saturday, :first) == {2013, 2, 2}
end

@tag :pending
test "first sunday of march 2013" do
assert Meetup.meetup(2013, 3, :sunday, :first) == {2013, 3, 3}
end

@tag :pending
test "first sunday of april 2013" do
assert Meetup.meetup(2013, 4, :sunday, :first) == {2013, 4, 7}
end

@tag :pending
test "second monday of march 2013" do
assert Meetup.meetup(2013, 3, :monday, :second) == {2013, 3, 11}
end

@tag :pending
test "second monday of april 2013" do
assert Meetup.meetup(2013, 4, :monday, :second) == {2013, 4, 8}
end

@tag :pending
test "second tuesday of may 2013" do
assert Meetup.meetup(2013, 5, :tuesday, :second) == {2013, 5, 14}
end

@tag :pending
test "second tuesday of june 2013" do
assert Meetup.meetup(2013, 6, :tuesday, :second) == {2013, 6, 11}
end

@tag :pending
test "second wednesday of july 2013" do
assert Meetup.meetup(2013, 7, :wednesday, :second) == {2013, 7, 10}
end

@tag :pending
test "second wednesday of august 2013" do
assert Meetup.meetup(2013, 8, :wednesday, :second) == {2013, 8, 14}
end

@tag :pending
test "second thursday of september 2013" do
assert Meetup.meetup(2013, 9, :thursday, :second) == {2013, 9, 12}
end

@tag :pending
test "second thursday of october 2013" do
assert Meetup.meetup(2013, 10, :thursday, :second) == {2013, 10, 10}
end

@tag :pending
test "second friday of november 2013" do
assert Meetup.meetup(2013, 11, :friday, :second) == {2013, 11, 8}
end

@tag :pending
test "second friday of december 2013" do
assert Meetup.meetup(2013, 12, :friday, :second) == {2013, 12, 13}
end

@tag :pending
test "second saturday of january 2013" do
assert Meetup.meetup(2013, 1, :saturday, :second) == {2013, 1, 12}
end

@tag :pending
test "second saturday of february 2013" do
assert Meetup.meetup(2013, 2, :saturday, :second) == {2013, 2, 9}
end

@tag :pending
test "second sunday of march 2013" do
assert Meetup.meetup(2013, 3, :sunday, :second) == {2013, 3, 10}
end

@tag :pending
test "second sunday of april 2013" do
assert Meetup.meetup(2013, 4, :sunday, :second) == {2013, 4, 14}
end

@tag :pending
test "third monday of march 2013" do
assert Meetup.meetup(2013, 3, :monday, :third) == {2013, 3, 18}
end

@tag :pending
test "third monday of april 2013" do
assert Meetup.meetup(2013, 4, :monday, :third) == {2013, 4, 15}
end

@tag :pending
test "third tuesday of may 2013" do
assert Meetup.meetup(2013, 5, :tuesday, :third) == {2013, 5, 21}
end

@tag :pending
test "third tuesday of june 2013" do
assert Meetup.meetup(2013, 6, :tuesday, :third) == {2013, 6, 18}
end

@tag :pending
test "third wednesday of july 2013" do
assert Meetup.meetup(2013, 7, :wednesday, :third) == {2013, 7, 17}
end

@tag :pending
test "third wednesday of august 2013" do
assert Meetup.meetup(2013, 8, :wednesday, :third) == {2013, 8, 21}
end

@tag :pending
test "third thursday of september 2013" do
assert Meetup.meetup(2013, 9, :thursday, :third) == {2013, 9, 19}
end

@tag :pending
test "third thursday of october 2013" do
assert Meetup.meetup(2013, 10, :thursday, :third) == {2013, 10, 17}
end

@tag :pending
test "third friday of november 2013" do
assert Meetup.meetup(2013, 11, :friday, :third) == {2013, 11, 15}
end

@tag :pending
test "third friday of december 2013" do
assert Meetup.meetup(2013, 12, :friday, :third) == {2013, 12, 20}
end

@tag :pending
test "third saturday of january 2013" do
assert Meetup.meetup(2013, 1, :saturday, :third) == {2013, 1, 19}
end

@tag :pending
test "third saturday of february 2013" do
assert Meetup.meetup(2013, 2, :saturday, :third) == {2013, 2, 16}
end

@tag :pending
test "third sunday of march 2013" do
assert Meetup.meetup(2013, 3, :sunday, :third) == {2013, 3, 17}
end

@tag :pending
test "third sunday of april 2013" do
assert Meetup.meetup(2013, 4, :sunday, :third) == {2013, 4, 21}
end

@tag :pending
test "fourth monday of march 2013" do
assert Meetup.meetup(2013, 3, :monday, :fourth) == {2013, 3, 25}
end

@tag :pending
test "fourth monday of april 2013" do
assert Meetup.meetup(2013, 4, :monday, :fourth) == {2013, 4, 22}
end

@tag :pending
test "fourth tuesday of may 2013" do
assert Meetup.meetup(2013, 5, :tuesday, :fourth) == {2013, 5, 28}
end

@tag :pending
test "fourth tuesday of june 2013" do
assert Meetup.meetup(2013, 6, :tuesday, :fourth) == {2013, 6, 25}
end

@tag :pending
test "fourth wednesday of july 2013" do
assert Meetup.meetup(2013, 7, :wednesday, :fourth) == {2013, 7, 24}
end

@tag :pending
test "fourth wednesday of august 2013" do
assert Meetup.meetup(2013, 8, :wednesday, :fourth) == {2013, 8, 28}
end

@tag :pending
test "fourth thursday of september 2013" do
assert Meetup.meetup(2013, 9, :thursday, :fourth) == {2013, 9, 26}
end

@tag :pending
test "fourth thursday of october 2013" do
assert Meetup.meetup(2013, 10, :thursday, :fourth) == {2013, 10, 24}
end

@tag :pending
test "fourth friday of november 2013" do
assert Meetup.meetup(2013, 11, :friday, :fourth) == {2013, 11, 22}
end

@tag :pending
test "fourth friday of december 2013" do
assert Meetup.meetup(2013, 12, :friday, :fourth) == {2013, 12, 27}
end

@tag :pending
test "fourth saturday of january 2013" do
assert Meetup.meetup(2013, 1, :saturday, :fourth) == {2013, 1, 26}
end

@tag :pending
test "fourth saturday of february 2013" do
assert Meetup.meetup(2013, 2, :saturday, :fourth) == {2013, 2, 23}
end

@tag :pending
test "fourth sunday of march 2013" do
assert Meetup.meetup(2013, 3, :sunday, :fourth) == {2013, 3, 24}
end

@tag :pending
test "fourth sunday of april 2013" do
assert Meetup.meetup(2013, 4, :sunday, :fourth) == {2013, 4, 28}
end

@tag :pending
test "last monday of march 2013" do
assert Meetup.meetup(2013, 3, :monday, :last) == {2013, 3, 25}
end

@tag :pending
test "last monday of april 2013" do
assert Meetup.meetup(2013, 4, :monday, :last) == {2013, 4, 29}
end

@tag :pending
test "last tuesday of may 2013" do
assert Meetup.meetup(2013, 5, :tuesday, :last) == {2013, 5, 28}
end

@tag :pending
test "last tuesday of june 2013" do
assert Meetup.meetup(2013, 6, :tuesday, :last) == {2013, 6, 25}
end

@tag :pending
test "last wednesday of july 2013" do
assert Meetup.meetup(2013, 7, :wednesday, :last) == {2013, 7, 31}
end

@tag :pending
test "last wednesday of august 2013" do
assert Meetup.meetup(2013, 8, :wednesday, :last) == {2013, 8, 28}
end

@tag :pending
test "last thursday of september 2013" do
assert Meetup.meetup(2013, 9, :thursday, :last) == {2013, 9, 26}
end

@tag :pending
test "last thursday of october 2013" do
assert Meetup.meetup(2013, 10, :thursday, :last) == {2013, 10, 31}
end

@tag :pending
test "last friday of november 2013" do
assert Meetup.meetup(2013, 11, :friday, :last) == {2013, 11, 29}
end

@tag :pending
test "last friday of december 2013" do
assert Meetup.meetup(2013, 12, :friday, :last) == {2013, 12, 27}
end

@tag :pending
test "last saturday of january 2013" do
assert Meetup.meetup(2013, 1, :saturday, :last) == {2013, 1, 26}
end

@tag :pending
test "last saturday of february 2013" do
assert Meetup.meetup(2013, 2, :saturday, :last) == {2013, 2, 23}
end

@tag :pending
test "last sunday of march 2013" do
assert Meetup.meetup(2013, 3, :sunday, :last) == {2013, 3, 31}
end

@tag :pending
test "last sunday of april 2013" do
assert Meetup.meetup(2013, 4, :sunday, :last) == {2013, 4, 28}
end
end``````
``````defmodule Meetup do
@moduledoc """
Calculate meetup dates.
"""

@type weekday ::
:monday | :tuesday | :wednesday
| :thursday | :friday | :saturday | :sunday

@type schedule :: :first | :second | :third | :fourth | :last | :teenth

#TODO see if there is a way to map from type, e.g. Meetup.weekday |> Enum.with_index(1) |> Enum.into(%{})
@weekdays %{:monday => 1, :tuesday => 2, :wednesday => 3, :thursday => 4, :friday => 5, :saturday => 6, :sunday => 7}

@doc """
Calculate a meetup date.

The schedule is in which week (1..4, last or "teenth") the meetup date should
fall.
"""
@spec meetup(pos_integer, pos_integer, weekday, schedule) :: :calendar.date
def meetup(year, month, weekday, schedule) do
matching_weekdates = 1..:calendar.last_day_of_the_month(year, month) |> Enum.map(&({year, month, &1})) |> Enum.filter(&(matches_weekday?(&1, weekday)))
filter_by_schedule(matching_weekdates, schedule)
end

defp matches_weekday?(date, weekday) do
:calendar.day_of_the_week(date) == @weekdays[weekday]
end

defp filter_by_schedule(dates, schedule) do
#TODO see if there is a way to use this map as a constant, like @weekdays, problem due to unknown methods at constant declaration time
schedule_filter = %{:first => &first/1, :second => &second/1, :third => &third/1, :fourth => &fourth/1, :last => &last/1, :teenth => &teenth/1}[schedule]
schedule_filter |> apply([dates])
end

defp first(dates) do
dates |> hd
end

defp second(dates) do
dates |> Enum.at(1)
end

defp third(dates) do
dates |> Enum.at(2)
end

defp fourth(dates) do
dates |> Enum.at(3)
end

defp last(dates) do
dates |> Enum.reverse |> hd
end

defp teenth(dates) do
dates |> Enum.find(fn({_, _, day}) ->
day >= 13 && day <= 19
end)
end
end``````