Skip to content

Commit b54ffcc

Browse files
Add swift-scheduling exercise (#2397)
1 parent 9a2287b commit b54ffcc

13 files changed

+693
-0
lines changed

config.json

+14
Original file line numberDiff line numberDiff line change
@@ -2759,6 +2759,20 @@
27592759
"numbers"
27602760
],
27612761
"difficulty": 6
2762+
},
2763+
{
2764+
"slug": "swift-scheduling",
2765+
"name": "Swift Scheduling",
2766+
"uuid": "c323aceb-70ae-4e2b-bdef-03ffcdd40a92",
2767+
"practices": [
2768+
"datetimes",
2769+
"string-formatting"
2770+
],
2771+
"prerequisites": [
2772+
"datetimes",
2773+
"string-formatting"
2774+
],
2775+
"difficulty": 6
27622776
}
27632777
],
27642778
"foregone": [

exercises/Exercises.sln

+18
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SplitSecondStopwatch", "pra
363363
EndProject
364364
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BafflingBirthdays", "practice\baffling-birthdays\BafflingBirthdays.csproj", "{1BA5F72A-ED8E-48A8-8FD6-0F567BDCBD9E}"
365365
EndProject
366+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "swift-scheduling", "swift-scheduling", "{FA726133-BC1C-D753-28C5-C9ACB44C0776}"
367+
EndProject
368+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftScheduling", "practice\swift-scheduling\SwiftScheduling.csproj", "{9A073412-4B64-48EB-A346-A56DE6847CCC}"
369+
EndProject
366370
Global
367371
GlobalSection(SolutionConfigurationPlatforms) = preSolution
368372
Debug|Any CPU = Debug|Any CPU
@@ -2509,6 +2513,18 @@ Global
25092513
{1BA5F72A-ED8E-48A8-8FD6-0F567BDCBD9E}.Release|x64.Build.0 = Release|Any CPU
25102514
{1BA5F72A-ED8E-48A8-8FD6-0F567BDCBD9E}.Release|x86.ActiveCfg = Release|Any CPU
25112515
{1BA5F72A-ED8E-48A8-8FD6-0F567BDCBD9E}.Release|x86.Build.0 = Release|Any CPU
2516+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
2517+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
2518+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Debug|x64.ActiveCfg = Debug|Any CPU
2519+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Debug|x64.Build.0 = Debug|Any CPU
2520+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Debug|x86.ActiveCfg = Debug|Any CPU
2521+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Debug|x86.Build.0 = Debug|Any CPU
2522+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
2523+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Release|Any CPU.Build.0 = Release|Any CPU
2524+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Release|x64.ActiveCfg = Release|Any CPU
2525+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Release|x64.Build.0 = Release|Any CPU
2526+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Release|x86.ActiveCfg = Release|Any CPU
2527+
{9A073412-4B64-48EB-A346-A56DE6847CCC}.Release|x86.Build.0 = Release|Any CPU
25122528
EndGlobalSection
25132529
GlobalSection(SolutionProperties) = preSolution
25142530
HideSolutionNode = FALSE
@@ -2692,6 +2708,8 @@ Global
26922708
{E81F1BA3-1F99-4DCB-B875-78D1F4750BD5} = {E276EF69-669A-43E0-88AC-8ABB17A9C026}
26932709
{0A6CD51A-2120-4A72-A17B-08CCC2E6D365} = {E276EF69-669A-43E0-88AC-8ABB17A9C026}
26942710
{1BA5F72A-ED8E-48A8-8FD6-0F567BDCBD9E} = {E276EF69-669A-43E0-88AC-8ABB17A9C026}
2711+
{FA726133-BC1C-D753-28C5-C9ACB44C0776} = {E276EF69-669A-43E0-88AC-8ABB17A9C026}
2712+
{9A073412-4B64-48EB-A346-A56DE6847CCC} = {FA726133-BC1C-D753-28C5-C9ACB44C0776}
26952713
EndGlobalSection
26962714
GlobalSection(ExtensibilityGlobals) = postSolution
26972715
SolutionGuid = {AB4EA6C9-5461-4024-BDC7-2AE0C3A85CD1}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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 13:00 | Today at 17:00 |
24+
| `"ASAP"` | After or at 13:00 | Tomorrow at 13: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+
~~~~exercism/note
43+
A workday is a Monday, Tuesday, Wednesday, Thursday, or Friday.
44+
45+
A year has four quarters, each with three months:
46+
1. January/February/March
47+
2. April/May/June
48+
3. July/August/September
49+
4. October/November/December.
50+
~~~~
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.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
###############################
2+
# Core EditorConfig Options #
3+
###############################
4+
5+
; This file is for unifying the coding style for different editors and IDEs.
6+
; More information at:
7+
; https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference?view=vs-2017
8+
; https://docs.microsoft.com/en-us/visualstudio/ide/create-portable-custom-editor-options?view=vs-2017
9+
10+
root = true
11+
12+
[*]
13+
indent_style = space
14+
15+
[SwiftScheduling.cs]
16+
indent_size = 4
17+
18+
###############################
19+
# .NET Coding Conventions #
20+
###############################
21+
22+
# Organize usings
23+
dotnet_sort_system_directives_first = true
24+
dotnet_separate_import_directive_groups = true
25+
26+
# this. preferences
27+
dotnet_style_qualification_for_field = false:suggestion
28+
dotnet_style_qualification_for_property = false:suggestion
29+
dotnet_style_qualification_for_method = false:suggestion
30+
dotnet_style_qualification_for_event = false:suggestion
31+
32+
# Language keywords vs BCL types preferences
33+
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
34+
dotnet_style_predefined_type_for_member_access = true:suggestion
35+
36+
# Parentheses preferences
37+
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
38+
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
39+
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
40+
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
41+
42+
# Modifier preferences
43+
dotnet_style_require_accessibility_modifiers = always:suggestion
44+
dotnet_style_readonly_field = true:suggestion
45+
46+
# Expression-level preferences
47+
dotnet_style_object_initializer = true:suggestion
48+
dotnet_style_collection_initializer = true:suggestion
49+
dotnet_style_explicit_tuple_names = true:suggestion
50+
dotnet_style_prefer_inferred_tuple_names = true:suggestion
51+
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
52+
dotnet_style_prefer_auto_properties = true:suggestion
53+
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
54+
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
55+
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
56+
dotnet_style_coalesce_expression = true:suggestion
57+
dotnet_style_null_propagation = true:suggestion
58+
59+
###############################
60+
# Naming Conventions #
61+
###############################
62+
63+
# Style Definitions
64+
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
65+
66+
# Use PascalCase for constant fields
67+
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
68+
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
69+
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
70+
dotnet_naming_symbols.constant_fields.applicable_kinds = field
71+
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
72+
dotnet_naming_symbols.constant_fields.required_modifiers = const
73+
74+
###############################
75+
# C# Code Style Rules #
76+
###############################
77+
78+
# var preferences
79+
csharp_style_var_for_built_in_types = true:none
80+
csharp_style_var_when_type_is_apparent = true:none
81+
csharp_style_var_elsewhere = true:none
82+
83+
# Expression-bodied members
84+
csharp_style_expression_bodied_methods = true:suggestion
85+
csharp_style_expression_bodied_constructors = true:suggestion
86+
csharp_style_expression_bodied_operators = true:suggestion
87+
csharp_style_expression_bodied_properties = true:suggestion
88+
csharp_style_expression_bodied_indexers = true:suggestion
89+
csharp_style_expression_bodied_accessors = true:suggestion
90+
91+
# Pattern-matching preferences
92+
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
93+
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
94+
95+
# Null-checking preferences
96+
csharp_style_throw_expression = true:suggestion
97+
csharp_style_conditional_delegate_call = true:suggestion
98+
99+
# Modifier preferences
100+
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
101+
102+
# Expression-level preferences
103+
csharp_prefer_braces = true:none
104+
csharp_prefer_simple_default_expression = true:suggestion
105+
csharp_style_deconstructed_variable_declaration = true:suggestion
106+
csharp_style_pattern_local_over_anonymous_function = true:suggestion
107+
csharp_style_inlined_variable_declaration = true:suggestion
108+
109+
###############################
110+
# C# Formatting Rules #
111+
###############################
112+
113+
# New line preferences
114+
csharp_new_line_before_open_brace = all
115+
csharp_new_line_before_else = true
116+
csharp_new_line_before_catch = true
117+
csharp_new_line_before_finally = true
118+
csharp_new_line_before_members_in_object_initializers = false
119+
csharp_new_line_before_members_in_anonymous_types = false
120+
csharp_new_line_between_query_expression_clauses = true
121+
122+
# Indentation preferences
123+
csharp_indent_case_contents = true
124+
csharp_indent_switch_labels = true
125+
csharp_indent_labels = flush_left
126+
127+
# Space preferences
128+
csharp_space_after_cast = false
129+
csharp_space_after_keywords_in_control_flow_statements = true
130+
csharp_space_between_method_declaration_parameter_list_parentheses = false
131+
csharp_space_between_method_call_parameter_list_parentheses = false
132+
csharp_space_before_colon_in_inheritance_clause = true
133+
csharp_space_after_colon_in_inheritance_clause = true
134+
csharp_space_around_binary_operators = before_and_after
135+
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
136+
csharp_space_between_method_call_name_and_opening_parenthesis = false
137+
csharp_space_between_method_call_empty_parameter_list_parentheses = false
138+
139+
# Wrapping preferences
140+
csharp_preserve_single_line_blocks = true
141+
csharp_preserve_single_line_statements = true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
public static class SwiftScheduling
2+
{
3+
public static DateTime DeliveryDate(DateTime meetingStart, string description) =>
4+
description switch
5+
{
6+
"NOW" => meetingStart.AddHours(2),
7+
"ASAP" when meetingStart.Hour <= 12 => meetingStart.AtHour(17),
8+
"ASAP" => meetingStart.AddDays(1).AtHour(13),
9+
"EOW" => meetingStart.DayOfWeek switch
10+
{
11+
DayOfWeek.Thursday or DayOfWeek.Friday => meetingStart.AddDays(7 - (int)meetingStart.DayOfWeek).AtHour(20),
12+
_ => meetingStart.AddDays(DayOfWeek.Friday - meetingStart.DayOfWeek).AtHour(17),
13+
},
14+
_ when description.EndsWith('M') => int.Parse(description[..^1]) switch
15+
{
16+
var month when month > meetingStart.Month => meetingStart.NthMonth(month).FirstWorkDay().AtHour(8),
17+
var month => meetingStart.AddYears(1).NthMonth(month).FirstWorkDay().AtHour(8)
18+
},
19+
_ when description.StartsWith('Q') => int.Parse(description[1..]) switch
20+
{
21+
var quarter when quarter * 3 > meetingStart.Month => meetingStart.NthQuarter(quarter).LastWorkDay().AtHour(8),
22+
var quarter => meetingStart.AddYears(1).NthQuarter(quarter).LastWorkDay().AtHour(8)
23+
},
24+
_ => throw new ArgumentException("Invalid date"),
25+
};
26+
27+
private static DateTime NthMonth(this DateTime date, int n) => new(date.Year, n, 1);
28+
29+
private static DateTime NthQuarter(this DateTime date, int n) => new(date.Year, n * 3, 1);
30+
31+
private static IEnumerable<DateTime> WorkDays(this DateTime date) =>
32+
Enumerable.Range(1, DateTime.DaysInMonth(date.Year, date.Month))
33+
.Select(day => new DateTime(date.Year, date.Month, day))
34+
.Where(d => d.DayOfWeek is not DayOfWeek.Saturday and not DayOfWeek.Sunday);
35+
36+
private static DateTime FirstWorkDay(this DateTime date) => date.WorkDays().First();
37+
38+
private static DateTime LastWorkDay(this DateTime date) => date.WorkDays().Last();
39+
40+
private static DateTime AtHour(this DateTime date, int hour) => date.Date.AddHours(hour);
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{{func to_datetime
2+
d = date.parse $0
3+
if d.hour + d.minute + d.second == 0
4+
$"new DateTime({d.year}, {d.month}, {d.day})"
5+
else
6+
$"new DateTime({d.year}, {d.month}, {d.day}, {d.hour}, {d.minute}, {d.second})"
7+
end
8+
end}}
9+
10+
public class {{ testClass }}
11+
{
12+
{{- for test in tests }}
13+
[Fact{{ if !for.first }}(Skip = "Remove this Skip property to run this test"){{ end }}]
14+
public void {{ test.testMethod | string.replace "4_m" "Four_m" | string.replace "2_m" "Two_m" | string.replace "11_m" "Eleven_m" }}()
15+
{
16+
var meetingStart = {{ test.input.meetingStart | to_datetime }};
17+
var expected = {{ test.expected | to_datetime }};
18+
Assert.Equal(expected, {{ testedClass }}.{{ test.testedMethod }}(meetingStart, {{ test.input.description | string.literal }}), TimeSpan.FromSeconds(1));
19+
}
20+
{{ end -}}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"erikschierboom"
4+
],
5+
"files": {
6+
"solution": [
7+
"SwiftScheduling.cs"
8+
],
9+
"test": [
10+
"SwiftSchedulingTests.cs"
11+
],
12+
"example": [
13+
".meta/Example.cs"
14+
]
15+
},
16+
"blurb": "Convert delivery date descriptions to actual delivery dates.",
17+
"source": "Erik Schierboom",
18+
"source_url": "https://github.com/exercism/problem-specifications/pull/2536"
19+
}

0 commit comments

Comments
 (0)