Skip to content

Commit

Permalink
Add meetup exercise (#151)
Browse files Browse the repository at this point in the history
* Add meetup exercise

* Use isodate 0.5.1 instead of 0.5.0 to get weekday and dayOfMonth for free
  • Loading branch information
ageron authored Oct 19, 2024
1 parent d53f7d1 commit c4256ae
Show file tree
Hide file tree
Showing 9 changed files with 1,521 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,14 @@
"prerequisites": [],
"difficulty": 4
},
{
"slug": "meetup",
"name": "Meetup",
"uuid": "0ef0cb6e-fe81-4988-bc13-26caac30c4d8",
"practices": [],
"prerequisites": [],
"difficulty": 4
},
{
"slug": "perfect-numbers",
"name": "Perfect Numbers",
Expand Down
34 changes: 34 additions & 0 deletions exercises/practice/meetup/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Instructions

Your task is to find the exact date of a meetup, given a month, year, weekday and week.

There are five week values to consider: `first`, `second`, `third`, `fourth`, `last`, `teenth`.

For example, you might be asked to find the date for the meetup on the first Monday in January 2018 (January 1, 2018).

Similarly, you might be asked to find:

- the third Tuesday of August 2019 (August 20, 2019)
- the teenth Wednesday of May 2020 (May 13, 2020)
- the fourth Sunday of July 2021 (July 25, 2021)
- the last Thursday of November 2022 (November 24, 2022)
- the teenth Saturday of August 1953 (August 15, 1953)

## Teenth

The teenth week refers to the seven days in a month that end in '-teenth' (13th, 14th, 15th, 16th, 17th, 18th and 19th).

If asked to find the teenth Saturday of August, 1953, we check its calendar:

```plaintext
August 1953
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
```

From this we find that the teenth Saturday is August 15, 1953.
29 changes: 29 additions & 0 deletions exercises/practice/meetup/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Introduction

Every month, your partner meets up with their best friend.
Both of them have very busy schedules, making it challenging to find a suitable date!
Given your own busy schedule, your partner always double-checks potential meetup dates with you:

- "Can I meet up on the first Friday of next month?"
- "What about the third Wednesday?"
- "Maybe the last Sunday?"

In this month's call, your partner asked you this question:

- "I'd like to meet up on the teenth Thursday; is that okay?"

Confused, you ask what a "teenth" day is.
Your partner explains that a teenth day, a concept they made up, refers to the days in a month that end in '-teenth':

- 13th (thirteenth)
- 14th (fourteenth)
- 15th (fifteenth)
- 16th (sixteenth)
- 17th (seventeenth)
- 18th (eighteenth)
- 19th (nineteenth)

As there are also seven weekdays, it is guaranteed that each day of the week has _exactly one_ teenth day each month.

Now that you understand the concept of a teenth day, you check your calendar.
You don't have anything planned on the teenth Thursday, so you happily confirm the date with your partner.
48 changes: 48 additions & 0 deletions exercises/practice/meetup/.meta/Example.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module [meetup]

import isodate.Date

Week : [First, Second, Third, Fourth, Last, Teenth]
DayOfWeek : [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]

meetup : { year : I64, month : U8, week : Week, dayOfWeek : DayOfWeek } -> Result Str [InvalidMonth, InvalidYear]
meetup = \{ year, month, week, dayOfWeek } ->
if month == 0 || month > 12 then
Err InvalidMonth
else

firstDay = Date.fromYmd year month 1
firstWeekday = Date.weekday firstDay.year firstDay.month firstDay.dayOfMonth
firstTime = (7 + dayOfWeekNumber dayOfWeek - firstWeekday) % 7 + 1
dayOfMonth =
when week is
First -> firstTime
Second -> firstTime + 7
Third -> firstTime + 14
Fourth -> firstTime + 21
Last ->
if firstTime + 28 > Date.daysInMonth year month then
firstTime + 21
else
firstTime + 28

Teenth ->
if firstTime == 6 then 13 else firstTime + 14
Ok "$(year |> padNumber 4)-$(month |> padNumber 2)-$(dayOfMonth |> padNumber 2)"

padNumber : Num *, U64 -> Str
padNumber = \number, pad ->
numberStr = number |> Num.toStr
numZeros = pad |> Num.subSaturated (numberStr |> Str.toUtf8 |> List.len)
"$(Str.repeat "0" numZeros)$(numberStr)"

dayOfWeekNumber : DayOfWeek -> U8
dayOfWeekNumber = \dayOfWeek ->
when dayOfWeek is
Sunday -> 0
Monday -> 1
Tuesday -> 2
Wednesday -> 3
Thursday -> 4
Friday -> 5
Saturday -> 6
18 changes: 18 additions & 0 deletions exercises/practice/meetup/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"authors": [
"ageron"
],
"files": {
"solution": [
"Meetup.roc"
],
"test": [
"meetup-test.roc"
],
"example": [
".meta/Example.roc"
]
},
"blurb": "Calculate the date of meetups.",
"source": "Jeremy Hinegardner mentioned a Boulder meetup that happens on the Wednesteenth of every month"
}
19 changes: 19 additions & 0 deletions exercises/practice/meetup/.meta/template.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{%- import "generator_macros.j2" as macros with context -%}
{{ macros.canonical_ref() }}
{{ macros.header(imports=["isodate"]) }}

import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_camel }}]

{% for case in cases -%}
# {{ case["description"] }}
expect
result = {{ case["property"] | to_camel }} {
year: {{ case["input"]["year"] | to_roc }},
month: {{ case["input"]["month"] | to_roc }},
week: {{ case["input"]["week"] | to_pascal }},
dayOfWeek: {{ case["input"]["dayofweek"] | to_pascal }},
}
expected = Ok {{ case["expected"] | to_roc }}
result == expected

{% endfor %}
Loading

0 comments on commit c4256ae

Please sign in to comment.