aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2020-07-08 18:17:06 +0200
committerFederico Igne <git@federicoigne.com>2021-11-03 18:55:00 +0000
commit1bbdf8a1d5490737388d435831639938cec439e0 (patch)
treea7f06ab016d7cd759cdf0022b1c222e9d437209c
parent12c8aedd5dfae75ec6bde982968bc77b70550374 (diff)
downloadexercism-1bbdf8a1d5490737388d435831639938cec439e0.tar.gz
exercism-1bbdf8a1d5490737388d435831639938cec439e0.zip
[rust] Clock
-rw-r--r--clock/.exercism/metadata.json1
-rw-r--r--clock/.gitignore8
-rw-r--r--clock/Cargo.toml6
-rw-r--r--clock/README.md102
-rw-r--r--clock/src/lib.rs44
-rw-r--r--clock/tests/clock.rs294
6 files changed, 455 insertions, 0 deletions
diff --git a/clock/.exercism/metadata.json b/clock/.exercism/metadata.json
new file mode 100644
index 0000000..cbe366b
--- /dev/null
+++ b/clock/.exercism/metadata.json
@@ -0,0 +1 @@
{"track":"rust","exercise":"clock","id":"f95dd1061dd34278af4d6838330bd546","url":"https://exercism.io/my/solutions/f95dd1061dd34278af4d6838330bd546","handle":"dyamon","is_requester":true,"auto_approve":false} \ No newline at end of file
diff --git a/clock/.gitignore b/clock/.gitignore
new file mode 100644
index 0000000..db7f315
--- /dev/null
+++ b/clock/.gitignore
@@ -0,0 +1,8 @@
1# Generated by Cargo
2# will have compiled files and executables
3/target/
4**/*.rs.bk
5
6# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
8Cargo.lock
diff --git a/clock/Cargo.toml b/clock/Cargo.toml
new file mode 100644
index 0000000..376e7f1
--- /dev/null
+++ b/clock/Cargo.toml
@@ -0,0 +1,6 @@
1[package]
2edition = "2018"
3name = "clock"
4version = "2.4.0"
5
6[dependencies]
diff --git a/clock/README.md b/clock/README.md
new file mode 100644
index 0000000..8348e33
--- /dev/null
+++ b/clock/README.md
@@ -0,0 +1,102 @@
1# Clock
2
3Implement a clock that handles times without dates.
4
5You should be able to add and subtract minutes to it.
6
7Two clocks that represent the same time should be equal to each other.
8
9## Rust Traits for `.to_string()`
10
11Did you implement `.to_string()` for the `Clock` struct?
12
13If so, try implementing the
14[Display trait](https://doc.rust-lang.org/std/fmt/trait.Display.html) for `Clock` instead.
15
16Traits allow for a common way to implement functionality for various types.
17
18For additional learning, consider how you might implement `String::from` for the `Clock` type.
19You don't have to actually implement this—it's redundant with `Display`, which is generally the
20better choice when the destination type is `String`—but it's useful to have a few type-conversion
21traits in your toolkit.
22
23
24## Rust Installation
25
26Refer to the [exercism help page][help-page] for Rust installation and learning
27resources.
28
29## Writing the Code
30
31Execute the tests with:
32
33```bash
34$ cargo test
35```
36
37All but the first test have been ignored. After you get the first test to
38pass, open the tests source file which is located in the `tests` directory
39and remove the `#[ignore]` flag from the next test and get the tests to pass
40again. Each separate test is a function with `#[test]` flag above it.
41Continue, until you pass every test.
42
43If you wish to run all ignored tests without editing the tests source file, use:
44
45```bash
46$ cargo test -- --ignored
47```
48
49To run a specific test, for example `some_test`, you can use:
50
51```bash
52$ cargo test some_test
53```
54
55If the specific test is ignored use:
56
57```bash
58$ cargo test some_test -- --ignored
59```
60
61To learn more about Rust tests refer to the [online test documentation][rust-tests]
62
63Make sure to read the [Modules][modules] chapter if you
64haven't already, it will help you with organizing your files.
65
66## Further improvements
67
68After you have solved the exercise, please consider using the additional utilities, described in the [installation guide](https://exercism.io/tracks/rust/installation), to further refine your final solution.
69
70To format your solution, inside the solution directory use
71
72```bash
73cargo fmt
74```
75
76To see, if your solution contains some common ineffective use cases, inside the solution directory use
77
78```bash
79cargo clippy --all-targets
80```
81
82## Submitting the solution
83
84Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer.
85
86## Feedback, Issues, Pull Requests
87
88The [exercism/rust](https://github.com/exercism/rust) repository on GitHub is the home for all of the Rust exercises. If you have feedback about an exercise, or want to help implement new exercises, head over there and create an issue. Members of the rust track team are happy to help!
89
90If you want to know more about Exercism, take a look at the [contribution guide](https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md).
91
92[help-page]: https://exercism.io/tracks/rust/learning
93[modules]: https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html
94[cargo]: https://doc.rust-lang.org/book/ch14-00-more-about-cargo.html
95[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html
96
97## Source
98
99Pairing session with Erin Drummond [https://twitter.com/ebdrummond](https://twitter.com/ebdrummond)
100
101## Submitting Incomplete Solutions
102It's possible to submit an incomplete solution so you can see how others have completed the exercise.
diff --git a/clock/src/lib.rs b/clock/src/lib.rs
new file mode 100644
index 0000000..3ae8a62
--- /dev/null
+++ b/clock/src/lib.rs
@@ -0,0 +1,44 @@
1use std::fmt;
2use std::ops::Add;
3
4#[derive(Debug, PartialEq, Clone, Copy)]
5pub struct Clock {
6 hours: i32,
7 minutes: i32,
8}
9
10impl fmt::Display for Clock {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 write!(f, "{:02}:{:02}", self.hours, self.minutes)
13 }
14}
15
16impl Add<i32> for Clock {
17 type Output = Self;
18
19 fn add(self, minutes: i32) -> Self {
20 Self::new(self.hours, self.minutes + minutes)
21 }
22}
23
24/* impl From<Clock> for String {
25 * fn from(c: Clock) -> String {
26 * format!("{}",c)
27 * }
28 * }
29 */
30
31impl Clock {
32 pub fn new(hours: i32, minutes: i32) -> Self {
33 let hours = hours + minutes / 60 - if minutes % 60 < 0 { 1 } else { 0 };
34 let hours = hours % 24;
35 let hours = hours + if hours < 0 { 24 } else { 0 };
36 let minutes = minutes % 60;
37 let minutes = minutes + if minutes < 0 { 60 } else { 0 };
38 Clock { hours, minutes }
39 }
40
41 pub fn add_minutes(self, minutes: i32) -> Self {
42 self + minutes
43 }
44}
diff --git a/clock/tests/clock.rs b/clock/tests/clock.rs
new file mode 100644
index 0000000..04f5241
--- /dev/null
+++ b/clock/tests/clock.rs
@@ -0,0 +1,294 @@
1use clock::Clock;
2
3//
4// Clock Creation
5//
6
7#[test]
8fn test_on_the_hour() {
9 assert_eq!(Clock::new(8, 0).to_string(), "08:00");
10}
11
12#[test]
13fn test_past_the_hour() {
14 assert_eq!(Clock::new(11, 9).to_string(), "11:09");
15}
16
17#[test]
18fn test_midnight_is_zero_hours() {
19 assert_eq!(Clock::new(24, 0).to_string(), "00:00");
20}
21
22#[test]
23fn test_hour_rolls_over() {
24 assert_eq!(Clock::new(25, 0).to_string(), "01:00");
25}
26
27#[test]
28fn test_hour_rolls_over_continuously() {
29 assert_eq!(Clock::new(100, 0).to_string(), "04:00");
30}
31
32#[test]
33fn test_sixty_minutes_is_next_hour() {
34 assert_eq!(Clock::new(1, 60).to_string(), "02:00");
35}
36
37#[test]
38fn test_minutes_roll_over() {
39 assert_eq!(Clock::new(0, 160).to_string(), "02:40");
40}
41
42#[test]
43fn test_minutes_roll_over_continuously() {
44 assert_eq!(Clock::new(0, 1723).to_string(), "04:43");
45}
46
47#[test]
48fn test_hours_and_minutes_roll_over() {
49 assert_eq!(Clock::new(25, 160).to_string(), "03:40");
50}
51
52#[test]
53fn test_hours_and_minutes_roll_over_continuously() {
54 assert_eq!(Clock::new(201, 3001).to_string(), "11:01");
55}
56
57#[test]
58fn test_hours_and_minutes_roll_over_to_exactly_midnight() {
59 assert_eq!(Clock::new(72, 8640).to_string(), "00:00");
60}
61
62#[test]
63fn test_negative_hour() {
64 assert_eq!(Clock::new(-1, 15).to_string(), "23:15");
65}
66
67#[test]
68fn test_negative_hour_roll_over() {
69 assert_eq!(Clock::new(-25, 00).to_string(), "23:00");
70}
71
72#[test]
73fn test_negative_hour_roll_over_continuously() {
74 assert_eq!(Clock::new(-91, 00).to_string(), "05:00");
75}
76
77#[test]
78fn test_negative_minutes() {
79 assert_eq!(Clock::new(1, -40).to_string(), "00:20");
80}
81
82#[test]
83fn test_negative_minutes_roll_over() {
84 assert_eq!(Clock::new(1, -160).to_string(), "22:20");
85}
86
87#[test]
88fn test_negative_minutes_roll_over_continuously() {
89 assert_eq!(Clock::new(1, -4820).to_string(), "16:40");
90}
91
92#[test]
93fn test_negative_sixty_minutes_is_prev_hour() {
94 assert_eq!(Clock::new(2, -60).to_string(), "01:00");
95}
96
97#[test]
98fn test_negative_hour_and_minutes_both_roll_over() {
99 assert_eq!(Clock::new(-25, -160).to_string(), "20:20");
100}
101
102#[test]
103fn test_negative_hour_and_minutes_both_roll_over_continuously() {
104 assert_eq!(Clock::new(-121, -5810).to_string(), "22:10");
105}
106
107#[test]
108fn test_zero_hour_and_negative_minutes() {
109 assert_eq!(Clock::new(0, -22).to_string(), "23:38");
110}
111
112//
113// Clock Math
114//
115
116#[test]
117fn test_add_minutes() {
118 let clock = Clock::new(10, 0).add_minutes(3);
119 assert_eq!(clock.to_string(), "10:03");
120}
121
122#[test]
123fn test_add_no_minutes() {
124 let clock = Clock::new(6, 41).add_minutes(0);
125 assert_eq!(clock.to_string(), "06:41");
126}
127
128#[test]
129fn test_add_to_next_hour() {
130 let clock = Clock::new(0, 45).add_minutes(40);
131 assert_eq!(clock.to_string(), "01:25");
132}
133
134#[test]
135fn test_add_more_than_one_hour() {
136 let clock = Clock::new(10, 0).add_minutes(61);
137 assert_eq!(clock.to_string(), "11:01");
138}
139
140#[test]
141fn test_add_more_than_two_hours_with_carry() {
142 let clock = Clock::new(0, 45).add_minutes(160);
143 assert_eq!(clock.to_string(), "03:25");
144}
145
146#[test]
147fn test_add_across_midnight() {
148 let clock = Clock::new(23, 59).add_minutes(2);
149 assert_eq!(clock.to_string(), "00:01");
150}
151
152#[test]
153fn test_add_more_than_one_day() {
154 let clock = Clock::new(5, 32).add_minutes(1500);
155 assert_eq!(clock.to_string(), "06:32");
156}
157
158#[test]
159fn test_add_more_than_two_days() {
160 let clock = Clock::new(1, 1).add_minutes(3500);
161 assert_eq!(clock.to_string(), "11:21");
162}
163
164#[test]
165fn test_subtract_minutes() {
166 let clock = Clock::new(10, 3).add_minutes(-3);
167 assert_eq!(clock.to_string(), "10:00");
168}
169
170#[test]
171fn test_subtract_to_previous_hour() {
172 let clock = Clock::new(10, 3).add_minutes(-30);
173 assert_eq!(clock.to_string(), "09:33");
174}
175
176#[test]
177fn test_subtract_more_than_an_hour() {
178 let clock = Clock::new(10, 3).add_minutes(-70);
179 assert_eq!(clock.to_string(), "08:53");
180}
181
182#[test]
183fn test_subtract_across_midnight() {
184 let clock = Clock::new(0, 3).add_minutes(-4);
185 assert_eq!(clock.to_string(), "23:59");
186}
187
188#[test]
189fn test_subtract_more_than_two_hours() {
190 let clock = Clock::new(0, 0).add_minutes(-160);
191 assert_eq!(clock.to_string(), "21:20");
192}
193
194#[test]
195fn test_subtract_more_than_two_hours_with_borrow() {
196 let clock = Clock::new(6, 15).add_minutes(-160);
197 assert_eq!(clock.to_string(), "03:35");
198}
199
200#[test]
201fn test_subtract_more_than_one_day() {
202 let clock = Clock::new(5, 32).add_minutes(-1500);
203 assert_eq!(clock.to_string(), "04:32");
204}
205
206#[test]
207fn test_subtract_mores_than_two_days() {
208 let clock = Clock::new(2, 20).add_minutes(-3000);
209 assert_eq!(clock.to_string(), "00:20");
210}
211
212//
213// Test Equality
214//
215
216#[test]
217fn test_compare_clocks_for_equality() {
218 assert_eq!(Clock::new(15, 37), Clock::new(15, 37));
219}
220
221#[test]
222fn test_compare_clocks_a_minute_apart() {
223 assert_ne!(Clock::new(15, 36), Clock::new(15, 37));
224}
225
226#[test]
227fn test_compare_clocks_an_hour_apart() {
228 assert_ne!(Clock::new(14, 37), Clock::new(15, 37));
229}
230
231#[test]
232fn test_compare_clocks_with_hour_overflow() {
233 assert_eq!(Clock::new(10, 37), Clock::new(34, 37));
234}
235
236#[test]
237fn test_compare_clocks_with_hour_overflow_by_several_days() {
238 assert_eq!(Clock::new(3, 11), Clock::new(99, 11));
239}
240
241#[test]
242fn test_compare_clocks_with_negative_hour() {
243 assert_eq!(Clock::new(22, 40), Clock::new(-2, 40));
244}
245
246#[test]
247fn test_compare_clocks_with_negative_hour_that_wraps() {
248 assert_eq!(Clock::new(17, 3), Clock::new(-31, 3));
249}
250
251#[test]
252fn test_compare_clocks_with_negative_hour_that_wraps_multiple_times() {
253 assert_eq!(Clock::new(13, 49), Clock::new(-83, 49));
254}
255
256#[test]
257fn test_compare_clocks_with_minutes_overflow() {
258 assert_eq!(Clock::new(0, 1), Clock::new(0, 1441));
259}
260
261#[test]
262fn test_compare_clocks_with_minutes_overflow_by_several_days() {
263 assert_eq!(Clock::new(2, 2), Clock::new(2, 4322));
264}
265
266#[test]
267fn test_compare_clocks_with_negative_minute() {
268 assert_eq!(Clock::new(2, 40), Clock::new(3, -20))
269}
270
271#[test]
272fn test_compare_clocks_with_negative_minute_that_wraps() {
273 assert_eq!(Clock::new(4, 10), Clock::new(5, -1490))
274}
275
276#[test]
277fn test_compare_clocks_with_negative_minute_that_wraps_multiple() {
278 assert_eq!(Clock::new(6, 15), Clock::new(6, -4305))
279}
280
281#[test]
282fn test_compare_clocks_with_negative_hours_and_minutes() {
283 assert_eq!(Clock::new(7, 32), Clock::new(-12, -268))
284}
285
286#[test]
287fn test_compare_clocks_with_negative_hours_and_minutes_that_wrap() {
288 assert_eq!(Clock::new(18, 7), Clock::new(-54, -11_513))
289}
290
291#[test]
292fn test_compare_full_clock_and_zeroed_clock() {
293 assert_eq!(Clock::new(24, 0), Clock::new(0, 0))
294}