Skip to content

Commit 4758e9a

Browse files
authored
[Swift Scheduling]: Added Files for New Practice Exercise (exercism#3876)
* Added files for new practice execise swift-scheduling. * removed source url from meta config. * Added example solution and stub file. * Corrected stub file. * Added new leapyear test case and regenerated test cases and tests toml. * Updated config json to add exercise to track. * Rewrote example solution so CI would pass for python 3.7 - 3.9.
1 parent cfbeb02 commit 4758e9a

File tree

9 files changed

+325
-0
lines changed

9 files changed

+325
-0
lines changed

config.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,23 @@
13271327
],
13281328
"difficulty": 4
13291329
},
1330+
{
1331+
"slug": "swift-scheduling",
1332+
"name": "Swift Scheduling",
1333+
"uuid": "ebddfc37-a3fc-4524-bd62-9c70f979713c",
1334+
"practices": [],
1335+
"prerequisites": ["basics",
1336+
"bools",
1337+
"conditionals",
1338+
"lists",
1339+
"list-methods",
1340+
"loops",
1341+
"numbers",
1342+
"strings",
1343+
"string-methods"
1344+
],
1345+
"difficulty": 4
1346+
},
13301347
{
13311348
"slug": "minesweeper",
13321349
"name": "Minesweeper",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Instructions
2+
3+
Your task is to convert delivery date descriptions to _actual_ delivery dates, based on when the meeting started.
4+
5+
There are two types of delivery date descriptions:
6+
7+
1. Fixed: a predefined set of words.
8+
2. Variable: words that have a variable component, but follow a predefined set of patterns.
9+
10+
## Fixed delivery date descriptions
11+
12+
There are three fixed delivery date descriptions:
13+
14+
- `"NOW"`
15+
- `"ASAP"` (As Soon As Possible)
16+
- `"EOW"` (End Of Week)
17+
18+
The following table shows how to translate them:
19+
20+
| Description | Meeting start | Delivery date |
21+
| ----------- | ----------------------------- | ----------------------------------- |
22+
| `"NOW"` | - | Two hours after the meeting started |
23+
| `"ASAP"` | Before 12:00 | Today at 17:00 |
24+
| `"ASAP"` | After 12:00 | Tomorrow at 12:00 |
25+
| `"EOW"` | Monday, Tuesday, or Wednesday | Friday at 17:00 |
26+
| `"EOW"` | Thursday or Friday | Sunday at 20:00 |
27+
28+
## Variable delivery date descriptions
29+
30+
There are two variable delivery date description patterns:
31+
32+
- `"<N>M"` (N-th month)
33+
- `"Q<N>"` (N-th quarter)
34+
35+
| Description | Meeting start | Delivery date |
36+
| ----------- | -------------------------- | ----------------------------------------------------------- |
37+
| `"<N>M"` | Before N-th month | At 8:00 on the _first_ workday¹ of this year's N-th month |
38+
| `"<N>M"` | After or in N-th month | At 8:00 on the _first_ workday¹ of next year's N-th month |
39+
| `"Q<N>"` | Before or in N-th quarter² | At 8:00 on the _last_ workday¹ of this year's N-th quarter² |
40+
| `"Q<N>"` | After N-th quarter² | At 8:00 on the _last_ workday¹ of next year's N-th quarter² |
41+
42+
¹ A workday is a Monday, Tuesday, Wednesday, Thursday, or Friday.
43+
² A year has four quarters, each with three months: January/February/March, April/May/June, July/August/September, and October/November/December.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Introduction
2+
3+
This week, it is your turn to take notes in the department's planning meeting.
4+
In this meeting, your boss will set delivery dates for all open work items.
5+
Annoyingly, instead of specifying the _actual_ delivery dates, your boss will only _describe them_ in an abbreviated format.
6+
As many of your colleagues won't be familiar with this corporate lingo, you'll need to convert these delivery date descriptions to actual delivery dates.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"authors": [
3+
"erikschierboom",
4+
"bethanyg"
5+
],
6+
"contributors": [],
7+
"files": {
8+
"solution": [
9+
"swift_scheduling.py"
10+
],
11+
"test": [
12+
"swift_scheduling_test.py"
13+
],
14+
"example": [
15+
".meta/example.py"
16+
]
17+
},
18+
"blurb": "Convert delivery date descriptions to actual delivery dates.",
19+
"source": "Original exercise idea from Eric Schierboom."
20+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from datetime import datetime, timedelta
2+
3+
4+
def delivery_date(start, description):
5+
start_date = datetime.fromisoformat(start)
6+
7+
8+
if description == 'NOW':
9+
due_date = start_date + timedelta(hours=2)
10+
11+
if description == 'ASAP':
12+
if str(start_date.time()) < '13:00:00':
13+
due_date = start_date.replace(hour=17, minute=0)
14+
else:
15+
due_date = (
16+
start_date.replace(hour=13, minute=0) +
17+
timedelta(days=1)
18+
)
19+
20+
if description =='EOW':
21+
if start_date.isoweekday() < 4:
22+
due_date = (
23+
start_date.replace(hour=17, minute=0) +
24+
timedelta(days=5 - start_date.isoweekday())
25+
)
26+
else:
27+
due_date = (
28+
start_date.replace(hour=20, minute=0) +
29+
timedelta(days=7 - start_date.isoweekday())
30+
)
31+
32+
if description.endswith('M'):
33+
month = int(description[:-1])
34+
target = datetime(start_date.year, month, 1, 8, 0, 0)
35+
36+
if start_date.month >= target.month:
37+
target = target.replace(year=target.year + 1)
38+
if target.isoweekday() not in (6,7) and target.day in range(1, 8):
39+
due_date = target
40+
else:
41+
if target.isoweekday() == 6: due_date = target + timedelta(days = 2)
42+
if target.isoweekday() == 7: due_date = target + timedelta(days = 1)
43+
44+
if description.startswith('Q'):
45+
target = int(description[1:])
46+
current = ((start_date.month + 2) // 3)
47+
month = {"Q1":4,"Q2": 7,"Q3": 10,"Q4": 1}[description]
48+
rollover = 1 if (current > target or target == 4) else 0
49+
50+
due_date = start_date.replace(
51+
start_date.year + rollover, month, 1, 8, 0, 0
52+
) - timedelta(days=1)
53+
54+
if due_date.isoweekday() == 6: due_date -= timedelta(days=1)
55+
if due_date.isoweekday() == 7: due_date -= timedelta(days=2)
56+
57+
return due_date.isoformat()
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{%- import "generator_macros.j2" as macros with context -%}
2+
{{ macros.canonical_ref() }}
3+
4+
{{ macros.header(imports=imports, ignore=ignore) }}
5+
6+
7+
{% macro test_case(case) -%}
8+
{%- set input = case["input"] -%}
9+
def test_{{ case["description"] | to_snake }}(self):
10+
self.assertEqual(
11+
{{ case["property"] | to_snake }}{{ case["input"]["meetingStart"], case["input"]["description"] }},
12+
"{{ case["expected"] }}"
13+
)
14+
{%- endmacro %}
15+
16+
17+
class {{ exercise | camel_case }}Test(unittest.TestCase):
18+
{% for case in cases %}
19+
{{ test_case(case) }}
20+
{% endfor %}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# This is an auto-generated file. Regular comments will be removed when this
2+
# file is regenerated. Regenerating will not touch any manually added keys,
3+
# so comments can be added in a "comment" key.
4+
5+
[1d0e6e72-f370-408c-bc64-5dafa9c6da73]
6+
description = "NOW translates to two hours later"
7+
8+
[93325e7b-677d-4d96-b017-2582af879dc2]
9+
description = "ASAP before one in the afternoon translates to today at five in the afternoon"
10+
11+
[cb4252a3-c4c1-41f6-8b8c-e7269733cef8]
12+
description = "ASAP at one in the afternoon translates to tomorrow at one in the afternoon"
13+
14+
[6fddc1ea-2fe9-4c60-81f7-9220d2f45537]
15+
description = "ASAP after one in the afternoon translates to tomorrow at one in the afternoon"
16+
17+
[25f46bf9-6d2a-4e95-8edd-f62dd6bc8a6e]
18+
description = "EOW on Monday translates to Friday at five in the afternoon"
19+
20+
[0b375df5-d198-489e-acee-fd538a768616]
21+
description = "EOW on Tuesday translates to Friday at five in the afternoon"
22+
23+
[4afbb881-0b5c-46be-94e1-992cdc2a8ca4]
24+
description = "EOW on Wednesday translates to Friday at five in the afternoon"
25+
26+
[e1341c2b-5e1b-4702-a95c-a01e8e96e510]
27+
description = "EOW on Thursday translates to Sunday at eight in the evening"
28+
29+
[bbffccf7-97f7-4244-888d-bdd64348fa2e]
30+
description = "EOW on Friday translates to Sunday at eight in the evening"
31+
32+
[d651fcf4-290e-407c-8107-36b9076f39b2]
33+
description = "EOW translates to leap day"
34+
35+
[439bf09f-3a0e-44e7-bad5-b7b6d0c4505a]
36+
description = "2M before the second month of this year translates to the first workday of the second month of this year"
37+
38+
[86d82e83-c481-4fb4-9264-625de7521340]
39+
description = "11M in the eleventh month translates to the first workday of the eleventh month of next year"
40+
41+
[0d0b8f6a-1915-46f5-a630-1ff06af9da08]
42+
description = "4M in the ninth month translates to the first workday of the fourth month of next year"
43+
44+
[06d401e3-8461-438f-afae-8d26aa0289e0]
45+
description = "Q1 in the first quarter translates to the last workday of the first quarter of this year"
46+
47+
[eebd5f32-b16d-4ecd-91a0-584b0364b7ed]
48+
description = "Q4 in the second quarter translates to the last workday of the fourth quarter of this year"
49+
50+
[c920886c-44ad-4d34-a156-dc4176186581]
51+
description = "Q3 in the fourth quarter translates to the last workday of the third quarter of next year"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def delivery_date(start, description):
2+
pass
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# These tests are auto-generated with test data from:
2+
# https://github.com/exercism/problem-specifications/tree/main/exercises/swift-scheduling/canonical-data.json
3+
# File last updated on 2025-03-03
4+
5+
import unittest
6+
7+
from swift_scheduling import (
8+
delivery_date,
9+
)
10+
11+
12+
class SwiftSchedulingTest(unittest.TestCase):
13+
def test_now_translates_to_two_hours_later(self):
14+
self.assertEqual(
15+
delivery_date("2012-02-13T09:00:00", "NOW"), "2012-02-13T11:00:00"
16+
)
17+
18+
def test_asap_before_one_in_the_afternoon_translates_to_today_at_five_in_the_afternoon(
19+
self,
20+
):
21+
self.assertEqual(
22+
delivery_date("1999-06-03T09:45:00", "ASAP"), "1999-06-03T17:00:00"
23+
)
24+
25+
def test_asap_at_one_in_the_afternoon_translates_to_tomorrow_at_one_in_the_afternoon(
26+
self,
27+
):
28+
self.assertEqual(
29+
delivery_date("2008-12-21T13:00:00", "ASAP"), "2008-12-22T13:00:00"
30+
)
31+
32+
def test_asap_after_one_in_the_afternoon_translates_to_tomorrow_at_one_in_the_afternoon(
33+
self,
34+
):
35+
self.assertEqual(
36+
delivery_date("2008-12-21T14:50:00", "ASAP"), "2008-12-22T13:00:00"
37+
)
38+
39+
def test_eow_on_monday_translates_to_friday_at_five_in_the_afternoon(self):
40+
self.assertEqual(
41+
delivery_date("2025-02-03T16:00:00", "EOW"), "2025-02-07T17:00:00"
42+
)
43+
44+
def test_eow_on_tuesday_translates_to_friday_at_five_in_the_afternoon(self):
45+
self.assertEqual(
46+
delivery_date("1997-04-29T10:50:00", "EOW"), "1997-05-02T17:00:00"
47+
)
48+
49+
def test_eow_on_wednesday_translates_to_friday_at_five_in_the_afternoon(self):
50+
self.assertEqual(
51+
delivery_date("2005-09-14T11:00:00", "EOW"), "2005-09-16T17:00:00"
52+
)
53+
54+
def test_eow_on_thursday_translates_to_sunday_at_eight_in_the_evening(self):
55+
self.assertEqual(
56+
delivery_date("2011-05-19T08:30:00", "EOW"), "2011-05-22T20:00:00"
57+
)
58+
59+
def test_eow_on_friday_translates_to_sunday_at_eight_in_the_evening(self):
60+
self.assertEqual(
61+
delivery_date("2022-08-05T14:00:00", "EOW"), "2022-08-07T20:00:00"
62+
)
63+
64+
def test_eow_translates_to_leap_day(self):
65+
self.assertEqual(
66+
delivery_date("2008-02-25T10:30:00", "EOW"), "2008-02-29T17:00:00"
67+
)
68+
69+
def test_2_m_before_the_second_month_of_this_year_translates_to_the_first_workday_of_the_second_month_of_this_year(
70+
self,
71+
):
72+
self.assertEqual(
73+
delivery_date("2007-01-02T14:15:00", "2M"), "2007-02-01T08:00:00"
74+
)
75+
76+
def test_11_m_in_the_eleventh_month_translates_to_the_first_workday_of_the_eleventh_month_of_next_year(
77+
self,
78+
):
79+
self.assertEqual(
80+
delivery_date("2013-11-21T15:30:00", "11M"), "2014-11-03T08:00:00"
81+
)
82+
83+
def test_4_m_in_the_ninth_month_translates_to_the_first_workday_of_the_fourth_month_of_next_year(
84+
self,
85+
):
86+
self.assertEqual(
87+
delivery_date("2019-11-18T15:15:00", "4M"), "2020-04-01T08:00:00"
88+
)
89+
90+
def test_q1_in_the_first_quarter_translates_to_the_last_workday_of_the_first_quarter_of_this_year(
91+
self,
92+
):
93+
self.assertEqual(
94+
delivery_date("2003-01-01T10:45:00", "Q1"), "2003-03-31T08:00:00"
95+
)
96+
97+
def test_q4_in_the_second_quarter_translates_to_the_last_workday_of_the_fourth_quarter_of_this_year(
98+
self,
99+
):
100+
self.assertEqual(
101+
delivery_date("2001-04-09T09:00:00", "Q4"), "2001-12-31T08:00:00"
102+
)
103+
104+
def test_q3_in_the_fourth_quarter_translates_to_the_last_workday_of_the_third_quarter_of_next_year(
105+
self,
106+
):
107+
self.assertEqual(
108+
delivery_date("2022-10-06T11:00:00", "Q3"), "2023-09-29T08:00:00"
109+
)

0 commit comments

Comments
 (0)