diff --git a/config.json b/config.json index 76e98f6..b142827 100644 --- a/config.json +++ b/config.json @@ -405,6 +405,14 @@ "prerequisites": [], "difficulty": 5 }, + { + "slug": "clock", + "name": "Clock", + "uuid": "a293accd-1504-42dc-8a09-1a6a5833afd8", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "matching-brackets", "name": "Matching Brackets", diff --git a/exercises/practice/clock/.docs/instructions.md b/exercises/practice/clock/.docs/instructions.md new file mode 100644 index 0000000..a1efc78 --- /dev/null +++ b/exercises/practice/clock/.docs/instructions.md @@ -0,0 +1,7 @@ +# Instructions + +Implement a clock that handles times without dates. + +You should be able to add and subtract minutes to it. + +Two clocks that represent the same time should be equal to each other. diff --git a/exercises/practice/clock/.meta/config.json b/exercises/practice/clock/.meta/config.json new file mode 100644 index 0000000..3ff1263 --- /dev/null +++ b/exercises/practice/clock/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras", + "drkameleon" + ], + "files": { + "solution": [ + "src/clock.art" + ], + "test": [ + "tests/test-clock.art" + ], + "example": [ + ".meta/src/example.art" + ] + }, + "blurb": "Implement a clock that handles times without dates.", + "source": "Pairing session with Erin Drummond" +} diff --git a/exercises/practice/clock/.meta/src/example.art b/exercises/practice/clock/.meta/src/example.art new file mode 100644 index 0000000..ba4086a --- /dev/null +++ b/exercises/practice/clock/.meta/src/example.art @@ -0,0 +1,27 @@ +define :clock [ + init: method [hour :quantity minute :quantity][ + this\minutes: in`min mod scalar ((in`min hour) + minute) scalar (in`min 1`day) + ] + + increment: method [time :quantity] [ + add 'this\minutes time + ] + + decrement: method [time :quantity] [ + sub 'this\minutes time + ] + + equal?: method [that] [ + equal? to :string this to :string that + ] + + string: method [] [ + working: this\minutes + while [working < 0] [ + add 'working in`min 1`day + ] + total: mod scalar working scalar (in`min 1`day) + [h, m]: divmod total scalar (in`min 1`hour) + ~"|pad.with:'0' to :string h 2|:|pad.with:'0' to :string m 2|" + ] +] diff --git a/exercises/practice/clock/.meta/tests.toml b/exercises/practice/clock/.meta/tests.toml new file mode 100644 index 0000000..712c87b --- /dev/null +++ b/exercises/practice/clock/.meta/tests.toml @@ -0,0 +1,166 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[a577bacc-106b-496e-9792-b3083ea8705e] +description = "Create a new clock with an initial time -> on the hour" + +[b5d0c360-3b88-489b-8e84-68a1c7a4fa23] +description = "Create a new clock with an initial time -> past the hour" + +[473223f4-65f3-46ff-a9f7-7663c7e59440] +description = "Create a new clock with an initial time -> midnight is zero hours" + +[ca95d24a-5924-447d-9a96-b91c8334725c] +description = "Create a new clock with an initial time -> hour rolls over" + +[f3826de0-0925-4d69-8ac8-89aea7e52b78] +description = "Create a new clock with an initial time -> hour rolls over continuously" + +[a02f7edf-dfd4-4b11-b21a-86de3cc6a95c] +description = "Create a new clock with an initial time -> sixty minutes is next hour" + +[8f520df6-b816-444d-b90f-8a477789beb5] +description = "Create a new clock with an initial time -> minutes roll over" + +[c75c091b-47ac-4655-8d40-643767fc4eed] +description = "Create a new clock with an initial time -> minutes roll over continuously" + +[06343ecb-cf39-419d-a3f5-dcbae0cc4c57] +description = "Create a new clock with an initial time -> hour and minutes roll over" + +[be60810e-f5d9-4b58-9351-a9d1e90e660c] +description = "Create a new clock with an initial time -> hour and minutes roll over continuously" + +[1689107b-0b5c-4bea-aad3-65ec9859368a] +description = "Create a new clock with an initial time -> hour and minutes roll over to exactly midnight" + +[d3088ee8-91b7-4446-9e9d-5e2ad6219d91] +description = "Create a new clock with an initial time -> negative hour" + +[77ef6921-f120-4d29-bade-80d54aa43b54] +description = "Create a new clock with an initial time -> negative hour rolls over" + +[359294b5-972f-4546-bb9a-a85559065234] +description = "Create a new clock with an initial time -> negative hour rolls over continuously" + +[509db8b7-ac19-47cc-bd3a-a9d2f30b03c0] +description = "Create a new clock with an initial time -> negative minutes" + +[5d6bb225-130f-4084-84fd-9e0df8996f2a] +description = "Create a new clock with an initial time -> negative minutes roll over" + +[d483ceef-b520-4f0c-b94a-8d2d58cf0484] +description = "Create a new clock with an initial time -> negative minutes roll over continuously" + +[1cd19447-19c6-44bf-9d04-9f8305ccb9ea] +description = "Create a new clock with an initial time -> negative sixty minutes is previous hour" + +[9d3053aa-4f47-4afc-bd45-d67a72cef4dc] +description = "Create a new clock with an initial time -> negative hour and minutes both roll over" + +[51d41fcf-491e-4ca0-9cae-2aa4f0163ad4] +description = "Create a new clock with an initial time -> negative hour and minutes both roll over continuously" + +[d098e723-ad29-4ef9-997a-2693c4c9d89a] +description = "Add minutes -> add minutes" + +[b6ec8f38-e53e-4b22-92a7-60dab1f485f4] +description = "Add minutes -> add no minutes" + +[efd349dd-0785-453e-9ff8-d7452a8e7269] +description = "Add minutes -> add to next hour" + +[749890f7-aba9-4702-acce-87becf4ef9fe] +description = "Add minutes -> add more than one hour" + +[da63e4c1-1584-46e3-8d18-c9dc802c1713] +description = "Add minutes -> add more than two hours with carry" + +[be167a32-3d33-4cec-a8bc-accd47ddbb71] +description = "Add minutes -> add across midnight" + +[6672541e-cdae-46e4-8be7-a820cc3be2a8] +description = "Add minutes -> add more than one day (1500 min = 25 hrs)" + +[1918050d-c79b-4cb7-b707-b607e2745c7e] +description = "Add minutes -> add more than two days" + +[37336cac-5ede-43a5-9026-d426cbe40354] +description = "Subtract minutes -> subtract minutes" + +[0aafa4d0-3b5f-4b12-b3af-e3a9e09c047b] +description = "Subtract minutes -> subtract to previous hour" + +[9b4e809c-612f-4b15-aae0-1df0acb801b9] +description = "Subtract minutes -> subtract more than an hour" + +[8b04bb6a-3d33-4e6c-8de9-f5de6d2c70d6] +description = "Subtract minutes -> subtract across midnight" + +[07c3bbf7-ce4d-4658-86e8-4a77b7a5ccd9] +description = "Subtract minutes -> subtract more than two hours" + +[90ac8a1b-761c-4342-9c9c-cdc3ed5db097] +description = "Subtract minutes -> subtract more than two hours with borrow" + +[2149f985-7136-44ad-9b29-ec023a97a2b7] +description = "Subtract minutes -> subtract more than one day (1500 min = 25 hrs)" + +[ba11dbf0-ac27-4acb-ada9-3b853ec08c97] +description = "Subtract minutes -> subtract more than two days" + +[f2fdad51-499f-4c9b-a791-b28c9282e311] +description = "Compare two clocks for equality -> clocks with same time" + +[5d409d4b-f862-4960-901e-ec430160b768] +description = "Compare two clocks for equality -> clocks a minute apart" + +[a6045fcf-2b52-4a47-8bb2-ef10a064cba5] +description = "Compare two clocks for equality -> clocks an hour apart" + +[66b12758-0be5-448b-a13c-6a44bce83527] +description = "Compare two clocks for equality -> clocks with hour overflow" + +[2b19960c-212e-4a71-9aac-c581592f8111] +description = "Compare two clocks for equality -> clocks with hour overflow by several days" + +[6f8c6541-afac-4a92-b0c2-b10d4e50269f] +description = "Compare two clocks for equality -> clocks with negative hour" + +[bb9d5a68-e324-4bf5-a75e-0e9b1f97a90d] +description = "Compare two clocks for equality -> clocks with negative hour that wraps" + +[56c0326d-565b-4d19-a26f-63b3205778b7] +description = "Compare two clocks for equality -> clocks with negative hour that wraps multiple times" + +[c90b9de8-ddff-4ffe-9858-da44a40fdbc2] +description = "Compare two clocks for equality -> clocks with minute overflow" + +[533a3dc5-59a7-491b-b728-a7a34fe325de] +description = "Compare two clocks for equality -> clocks with minute overflow by several days" + +[fff49e15-f7b7-4692-a204-0f6052d62636] +description = "Compare two clocks for equality -> clocks with negative minute" + +[605c65bb-21bd-43eb-8f04-878edf508366] +description = "Compare two clocks for equality -> clocks with negative minute that wraps" + +[b87e64ed-212a-4335-91fd-56da8421d077] +description = "Compare two clocks for equality -> clocks with negative minute that wraps multiple times" + +[822fbf26-1f3b-4b13-b9bf-c914816b53dd] +description = "Compare two clocks for equality -> clocks with negative hours and minutes" + +[e787bccd-cf58-4a1d-841c-ff80eaaccfaa] +description = "Compare two clocks for equality -> clocks with negative hours and minutes that wrap" + +[96969ca8-875a-48a1-86ae-257a528c44f5] +description = "Compare two clocks for equality -> full clock and zeroed clock" diff --git a/exercises/practice/clock/src/clock.art b/exercises/practice/clock/src/clock.art new file mode 100644 index 0000000..6f208b1 --- /dev/null +++ b/exercises/practice/clock/src/clock.art @@ -0,0 +1,21 @@ +define :clock [ + init: method [hour :quantity minute :quantity][ + panic "Please implement the initialize method" + ] + + increment: method [time :quantity] [ + panic "Please implement the increment method" + ] + + decrement: method [time :quantity] [ + panic "Please implement the decrement method" + ] + + equal?: method [that] [ + panic "Please implement the equal? magic method" + ] + + string: method [] [ + panic "Please implement the string? magic method" + ] +] diff --git a/exercises/practice/clock/tester.art b/exercises/practice/clock/tester.art new file mode 100644 index 0000000..80f4a8f --- /dev/null +++ b/exercises/practice/clock/tester.art @@ -0,0 +1,3 @@ +import {unitt}! + +runTests.failFast findTests "tests" diff --git a/exercises/practice/clock/tests/test-clock.art b/exercises/practice/clock/tests/test-clock.art new file mode 100644 index 0000000..affbe04 --- /dev/null +++ b/exercises/practice/clock/tests/test-clock.art @@ -0,0 +1,337 @@ +import {unitt}! +import {src/clock}! + +suite "Clock" [ + suite "Create a new clock with an initial time" [ + test "on the hour" [ + result: to :string to :clock [8`hr 0`min] + assert -> "08:00" = result + ] + + test.skip "past the hour" [ + result: to :string to :clock [11`hr 9`min] + assert -> "11:09" = result + ] + + test.skip "midnight is zero hours" [ + result: to :string to :clock [24`hr 0`min] + assert -> "00:00" = result + ] + + test.skip "hour rolls over" [ + result: to :string to :clock [25`hr 0`min] + assert -> "01:00" = result + ] + + test.skip "hour rolls over continuously" [ + result: to :string to :clock [100`hr 0`min] + assert -> "04:00" = result + ] + + test.skip "sixty minutes is next hour" [ + result: to :string to :clock [1`hr 60`min] + assert -> "02:00" = result + ] + + test.skip "minutes roll over" [ + result: to :string to :clock [0`hr 160`min] + assert -> "02:40" = result + ] + + test.skip "minutes roll over continuously" [ + result: to :string to :clock [0`hr 1723`min] + assert -> "04:43" = result + ] + + test.skip "hour and minutes roll over" [ + result: to :string to :clock [25`hr 160`min] + assert -> "03:40" = result + ] + + test.skip "hour and minutes roll over continuously" [ + result: to :string to :clock [201`hr 3001`min] + assert -> "11:01" = result + ] + + test.skip "hour and minutes roll over to exactly midnight" [ + result: to :string to :clock [72`hr 8640`min] + assert -> "00:00" = result + ] + + test.skip "negative hour" [ + result: to :string to :clock @[neg 1`hr 15`min] + assert -> "23:15" = result + ] + + test.skip "negative hour rolls over" [ + result: to :string to :clock @[neg 25`hr 0`min] + assert -> "23:00" = result + ] + + test.skip "negative hour rolls over continuously" [ + result: to :string to :clock @[neg 91`hr 0`min] + assert -> "05:00" = result + ] + + test.skip "negative minutes" [ + result: to :string to :clock @[1`hr neg 40`min] + assert -> "00:20" = result + ] + + test.skip "negative minutes roll over" [ + result: to :string to :clock @[1`hr neg 160`min] + assert -> "22:20" = result + ] + + test.skip "negative minutes roll over continuously" [ + result: to :string to :clock @[1`hr neg 4820`min] + assert -> "16:40" = result + ] + + test.skip "negative sixty minutes is previous hour" [ + result: to :string to :clock @[2`hr neg 60`min] + assert -> "01:00" = result + ] + + test.skip "negative hour and minutes roll over" [ + result: to :string to :clock @[neg 25`hr neg 160`min] + assert -> "20:20" = result + ] + + test.skip "negative hour and minutes roll over continuously" [ + result: to :string to :clock @[neg 121`hr neg 5810`min] + assert -> "22:10" = result + ] + ] + + suite "Add minutes" [ + test.skip "add minutes" [ + c: to :clock [10`hr 0`min] + do [c\increment 3`min] + result: to :string c + assert -> "10:03" = result + ] + + test.skip "add no minutes" [ + c: to :clock [6`hr 41`min] + do [c\increment 0`min] + result: to :string c + assert -> "06:41" = result + ] + + test.skip "add to next hour" [ + c: to :clock [0`hr 45`min] + do [c\increment 40`min] + result: to :string c + assert -> "01:25" = result + ] + + test.skip "add more than one hour" [ + c: to :clock [10`hr 0`min] + do [c\increment 61`min] + result: to :string c + assert -> "11:01" = result + ] + + test.skip "add more than two hours with carry" [ + c: to :clock [0`hr 45`min] + do [c\increment 160`min] + result: to :string c + assert -> "03:25" = result + ] + + test.skip "add across midnight" [ + c: to :clock [23`hr 59`min] + do [c\increment 2`min] + result: to :string c + assert -> "00:01" = result + ] + + test.skip "add more than one day (1500 min = 25 hrs)" [ + c: to :clock [5`hr 32`min] + do [c\increment 1500`min] + result: to :string c + assert -> "06:32" = result + ] + + test.skip "add more than two days" [ + c: to :clock [1`hr 1`min] + do [c\increment 3500`min] + result: to :string c + assert -> "11:21" = result + ] + ] + + + suite "Subtract minutes" [ + test.skip "subtract minutes" [ + c: to :clock [10`hr 3`min] + do [c\decrement 3`min] + result: to :string c + assert -> "10:00" = result + ] + + test.skip "subtract to previous hour" [ + c: to :clock [10`hr 3`min] + do [c\decrement 30`min] + result: to :string c + assert -> "09:33" = result + ] + + test.skip "subtract more than an hour" [ + c: to :clock [10`hr 3`min] + do [c\decrement 70`min] + result: to :string c + assert -> "08:53" = result + ] + + test.skip "subtract across midnight" [ + c: to :clock [0`hr 3`min] + do [c\decrement 4`min] + result: to :string c + assert -> "23:59" = result + ] + + test.skip "subtract more than two hours" [ + c: to :clock [0`hr 0`min] + do [c\decrement 160`min] + result: to :string c + assert -> "21:20" = result + ] + + test.skip "subtract more than two hours with borrow" [ + c: to :clock [6`hr 15`min] + do [c\decrement 160`min] + result: to :string c + assert -> "03:35" = result + ] + + test.skip "subtract more than one day (1500 min = 25 hrs)" [ + c: to :clock [5`hr 32`min] + do [c\decrement 1500`min] + result: to :string c + assert -> "04:32" = result + ] + + test.skip "subtract more than two days" [ + c: to :clock [2`hr 20`min] + do [c\decrement 3000`min] + result: to :string c + assert -> "00:20" = result + ] + ] + + suite "Compare two clocks for equality" [ + test.skip "clocks with same time" [ + c1: to :clock [15`hr 37`min] + c2: to :clock [15`hr 37`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks a minute apart" [ + c1: to :clock [15`hr 36`min] + c2: to :clock [15`hr 37`min] + result: c1 = c2 + assert -> false = result + ] + + test.skip "clocks an hour apart" [ + c1: to :clock [14`hr 37`min] + c2: to :clock [15`hr 37`min] + result: c1 = c2 + assert -> false = result + ] + + test.skip "clocks with hour overflow" [ + c1: to :clock [10`hr 37`min] + c2: to :clock [34`hr 37`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with hour overflow by several days" [ + c1: to :clock [3`hr 11`min] + c2: to :clock [99`hr 11`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with negative hour" [ + c1: to :clock [22`hr 40`min] + c2: to :clock @[neg 2`hr 40`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with negative hour that wraps" [ + c1: to :clock [17`hr 3`min] + c2: to :clock @[neg 31`hr 3`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with negative hour that wraps multiple times" [ + c1: to :clock [13`hr 49`min] + c2: to :clock @[neg 83`hr 49`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with minute overflow" [ + c1: to :clock [0`hr 1`min] + c2: to :clock [0`hr 1441`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with minute overflow by several days" [ + c1: to :clock [2`hr 2`min] + c2: to :clock [2`hr 4322`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with negative minute" [ + c1: to :clock [2`hr 40`min] + c2: to :clock [3`hr neg 20`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with negative minute that wraps" [ + c1: to :clock [4`hr 10`min] + c2: to :clock [5`hr neg 1490`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with negative minute that wraps multiple times" [ + c1: to :clock [6`hr 15`min] + c2: to :clock [6`hr neg 4305`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with negative hours and minutes" [ + c1: to :clock [7`hr 32`min] + c2: to :clock @[neg 12`hr neg 268`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "clocks with negative hours and minutes that wrap" [ + c1: to :clock [18`hr 7`min] + c2: to :clock @[neg 54`hr neg 11513`min] + result: c1 = c2 + assert -> true = result + ] + + test.skip "full clock and zeroed clock" [ + c1: to :clock [24`hr 0`min] + c2: to :clock [0`hr 0`min] + result: c1 = c2 + assert -> true = result + ] + ] +]