Skip to content

Commit ba6ad9a

Browse files
Add split-second-stopwatch exercise (#272)
1 parent 83dab98 commit ba6ad9a

File tree

8 files changed

+553
-0
lines changed

8 files changed

+553
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,14 @@
760760
"prerequisites": [],
761761
"difficulty": 5
762762
},
763+
{
764+
"slug": "split-second-stopwatch",
765+
"name": "Split-Second Stopwatch",
766+
"uuid": "1dfe7caf-9391-444c-94ef-7e22c84a2256",
767+
"practices": [],
768+
"prerequisites": [],
769+
"difficulty": 5
770+
},
763771
{
764772
"slug": "state-of-tic-tac-toe",
765773
"name": "State of Tic-Tac-Toe",
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Instructions
2+
3+
Your task is to build a stopwatch to keep precise track of lap times.
4+
5+
The stopwatch uses four commands (start, stop, lap, and reset) to keep track of:
6+
7+
1. The current lap's tracked time
8+
2. Previously recorded lap times
9+
10+
What commands can be used depends on which state the stopwatch is in:
11+
12+
1. Ready: initial state
13+
2. Running: tracking time
14+
3. Stopped: not tracking time
15+
16+
| Command | Begin state | End state | Effect |
17+
| ------- | ----------- | --------- | -------------------------------------------------------- |
18+
| Start | Ready | Running | Start tracking time |
19+
| Start | Stopped | Running | Resume tracking time |
20+
| Stop | Running | Stopped | Stop tracking time |
21+
| Lap | Running | Running | Add current lap to previous laps, then reset current lap |
22+
| Reset | Stopped | Ready | Reset current lap and clear previous laps |
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Introduction
2+
3+
You've always run for the thrill of it — no schedules, no timers, just the sound of your feet on the pavement.
4+
But now that you've joined a competitive running crew, things are getting serious.
5+
Training sessions are timed to the second, and every split second counts.
6+
To keep pace, you've picked up the _Split-Second Stopwatch_ — a sleek, high-tech gadget that's about to become your new best friend.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"split-second-stopwatch.v"
8+
],
9+
"test": [
10+
"run_test.v"
11+
],
12+
"example": [
13+
".meta/example.v"
14+
]
15+
},
16+
"blurb": "Keep track of time through a digital stopwatch.",
17+
"source": "Erik Schierboom",
18+
"source_url": "https://github.com/exercism/problem-specifications/pull/2547"
19+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
module main
2+
3+
import strconv
4+
5+
enum State {
6+
ready
7+
running
8+
stopped
9+
}
10+
11+
struct Stopwatch {
12+
mut:
13+
current_state State
14+
15+
current int
16+
previous []int
17+
}
18+
19+
fn Stopwatch.new() Stopwatch {
20+
return Stopwatch{
21+
current_state: .ready
22+
}
23+
}
24+
25+
fn (stopwatch Stopwatch) state() State {
26+
return stopwatch.current_state
27+
}
28+
29+
fn (stopwatch Stopwatch) current_lap() string {
30+
return serialize(stopwatch.current)
31+
}
32+
33+
fn (stopwatch Stopwatch) previous_laps() []string {
34+
return stopwatch.previous.map(serialize)
35+
}
36+
37+
fn (stopwatch Stopwatch) total() string {
38+
mut total := stopwatch.current
39+
for entry in stopwatch.previous {
40+
total += entry
41+
}
42+
return serialize(total)
43+
}
44+
45+
fn (mut stopwatch Stopwatch) start() ! {
46+
if stopwatch.current_state != .running {
47+
stopwatch.current_state = .running
48+
} else {
49+
return error('cannot start an already running stopwatch')
50+
}
51+
}
52+
53+
fn (mut stopwatch Stopwatch) stop() ! {
54+
if stopwatch.current_state == .running {
55+
stopwatch.current_state = .stopped
56+
} else {
57+
return error('cannot stop a stopwatch that is not running')
58+
}
59+
}
60+
61+
fn (mut stopwatch Stopwatch) reset() ! {
62+
if stopwatch.current_state == .stopped {
63+
stopwatch.current_state = .ready
64+
stopwatch.current = 0
65+
stopwatch.previous.clear()
66+
} else {
67+
return error('cannot reset a stopwatch that is not stopped')
68+
}
69+
}
70+
71+
fn (mut stopwatch Stopwatch) advance_time(by string) {
72+
if stopwatch.current_state == .running {
73+
stopwatch.current += deserialize(by)
74+
}
75+
}
76+
77+
fn (mut stopwatch Stopwatch) lap() ! {
78+
if stopwatch.current_state == .running {
79+
stopwatch.previous << stopwatch.current
80+
stopwatch.current = 0
81+
} else {
82+
return error('cannot lap a stopwatch that is not running')
83+
}
84+
}
85+
86+
fn serialize(time int) string {
87+
hours := time / 3600
88+
minutes := time % 3600 / 60
89+
seconds := time % 60
90+
return '${hours:02}:${minutes:02}:${seconds:02}'
91+
}
92+
93+
fn deserialize(time string) int {
94+
parts := time.split(':')
95+
hours := strconv.atoi(parts[0]) or { 0 }
96+
minutes := strconv.atoi(parts[1]) or { 0 }
97+
seconds := strconv.atoi(parts[2]) or { 0 }
98+
return 3600 * hours + 60 * minutes + seconds
99+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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+
[ddb238ea-99d4-4eaa-a81d-3c917a525a23]
6+
description = "new stopwatch starts in ready state"
7+
8+
[b19635d4-08ad-4ac3-b87f-aca10e844071]
9+
description = "new stopwatch's current lap has no elapsed time"
10+
11+
[492eb532-268d-43ea-8a19-2a032067d335]
12+
description = "new stopwatch's total has no elapsed time"
13+
14+
[8a892c1e-9ef7-4690-894e-e155a1fe4484]
15+
description = "new stopwatch does not have previous laps"
16+
17+
[5b2705b6-a584-4042-ba3a-4ab8d0ab0281]
18+
description = "start from ready state changes state to running"
19+
20+
[748235ce-1109-440b-9898-0a431ea179b6]
21+
description = "start does not change previous laps"
22+
23+
[491487b1-593d-423e-a075-aa78d449ff1f]
24+
description = "start initiates time tracking for current lap"
25+
26+
[a0a7ba2c-8db6-412c-b1b6-cb890e9b72ed]
27+
description = "start initiates time tracking for total"
28+
29+
[7f558a17-ef6d-4a5b-803a-f313af7c41d3]
30+
description = "start cannot be called from running state"
31+
32+
[32466eef-b2be-4d60-a927-e24fce52dab9]
33+
description = "stop from running state changes state to stopped"
34+
35+
[621eac4c-8f43-4d99-919c-4cad776d93df]
36+
description = "stop pauses time tracking for current lap"
37+
38+
[465bcc82-7643-41f2-97ff-5e817cef8db4]
39+
description = "stop pauses time tracking for total"
40+
41+
[b1ba7454-d627-41ee-a078-891b2ed266fc]
42+
description = "stop cannot be called from ready state"
43+
44+
[5c041078-0898-44dc-9d5b-8ebb5352626c]
45+
description = "stop cannot be called from stopped state"
46+
47+
[3f32171d-8fbf-46b6-bc2b-0810e1ec53b7]
48+
description = "start from stopped state changes state to running"
49+
50+
[626997cb-78d5-4fe8-b501-29fdef804799]
51+
description = "start from stopped state resumes time tracking for current lap"
52+
53+
[58487c53-ab26-471c-a171-807ef6363319]
54+
description = "start from stopped state resumes time tracking for total"
55+
56+
[091966e3-ed25-4397-908b-8bb0330118f8]
57+
description = "lap adds current lap to previous laps"
58+
59+
[1aa4c5ee-a7d5-4d59-9679-419deef3c88f]
60+
description = "lap resets current lap and resumes time tracking"
61+
62+
[4b46b92e-1b3f-46f6-97d2-0082caf56e80]
63+
description = "lap continues time tracking for total"
64+
65+
[ea75d36e-63eb-4f34-97ce-8c70e620bdba]
66+
description = "lap cannot be called from ready state"
67+
68+
[63731154-a23a-412d-a13f-c562f208eb1e]
69+
description = "lap cannot be called from stopped state"
70+
71+
[e585ee15-3b3f-4785-976b-dd96e7cc978b]
72+
description = "stop does not change previous laps"
73+
74+
[fc3645e2-86cf-4d11-97c6-489f031103f6]
75+
description = "reset from stopped state changes state to ready"
76+
77+
[20fbfbf7-68ad-4310-975a-f5f132886c4e]
78+
description = "reset resets current lap"
79+
80+
[00a8f7bb-dd5c-43e5-8705-3ef124007662]
81+
description = "reset clears previous laps"
82+
83+
[76cea936-6214-4e95-b6d1-4d4edcf90499]
84+
description = "reset cannot be called from ready state"
85+
86+
[ba4d8e69-f200-4721-b59e-90d8cf615153]
87+
description = "reset cannot be called from running state"
88+
89+
[0b01751a-cb57-493f-bb86-409de6e84306]
90+
description = "supports very long laps"

0 commit comments

Comments
 (0)