From 22a03014174794677cd2ff6a951176aef4b725b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Sat, 25 May 2024 22:31:09 -0700 Subject: [PATCH] Add gigasecond (#173) --- config.json | 8 + .../practice/gigasecond/.docs/instructions.md | 8 + .../practice/gigasecond/.docs/introduction.md | 24 ++ .../practice/gigasecond/.meta/config.json | 17 ++ .../practice/gigasecond/.meta/example.red | 11 + .../practice/gigasecond/.meta/tests.toml | 30 +++ .../practice/gigasecond/gigasecond-test.red | 64 ++++++ exercises/practice/gigasecond/gigasecond.red | 11 + exercises/practice/gigasecond/testlib.red | 217 ++++++++++++++++++ 9 files changed, 390 insertions(+) create mode 100644 exercises/practice/gigasecond/.docs/instructions.md create mode 100644 exercises/practice/gigasecond/.docs/introduction.md create mode 100644 exercises/practice/gigasecond/.meta/config.json create mode 100644 exercises/practice/gigasecond/.meta/example.red create mode 100644 exercises/practice/gigasecond/.meta/tests.toml create mode 100644 exercises/practice/gigasecond/gigasecond-test.red create mode 100644 exercises/practice/gigasecond/gigasecond.red create mode 100644 exercises/practice/gigasecond/testlib.red diff --git a/config.json b/config.json index fb9777f..995c9d0 100644 --- a/config.json +++ b/config.json @@ -90,6 +90,14 @@ "prerequisites": [], "difficulty": 2 }, + { + "slug": "gigasecond", + "name": "Gigasecond", + "uuid": "579eb0c9-4c56-4829-a97a-50a3c0ccee52", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "grains", "name": "Grains", diff --git a/exercises/practice/gigasecond/.docs/instructions.md b/exercises/practice/gigasecond/.docs/instructions.md new file mode 100644 index 0000000..1e20f00 --- /dev/null +++ b/exercises/practice/gigasecond/.docs/instructions.md @@ -0,0 +1,8 @@ +# Instructions + +Your task is to determine the date and time one gigasecond after a certain date. + +A gigasecond is one thousand million seconds. +That is a one with nine zeros after it. + +If you were born on _January 24th, 2015 at 22:00 (10:00:00pm)_, then you would be a gigasecond old on _October 2nd, 2046 at 23:46:40 (11:46:40pm)_. diff --git a/exercises/practice/gigasecond/.docs/introduction.md b/exercises/practice/gigasecond/.docs/introduction.md new file mode 100644 index 0000000..18a3dc2 --- /dev/null +++ b/exercises/practice/gigasecond/.docs/introduction.md @@ -0,0 +1,24 @@ +# Introduction + +The way we measure time is kind of messy. +We have 60 seconds in a minute, and 60 minutes in an hour. +This comes from ancient Babylon, where they used 60 as the basis for their number system. +We have 24 hours in a day, 7 days in a week, and how many days in a month? +Well, for days in a month it depends not only on which month it is, but also on what type of calendar is used in the country you live in. + +What if, instead, we only use seconds to express time intervals? +Then we can use metric system prefixes for writing large numbers of seconds in more easily comprehensible quantities. + +- A food recipe might explain that you need to let the brownies cook in the oven for two kiloseconds (that's two thousand seconds). +- Perhaps you and your family would travel to somewhere exotic for two megaseconds (that's two million seconds). +- And if you and your spouse were married for _a thousand million_ seconds, you would celebrate your one gigasecond anniversary. + +~~~~exercism/note +If we ever colonize Mars or some other planet, measuring time is going to get even messier. +If someone says "year" do they mean a year on Earth or a year on Mars? + +The idea for this exercise came from the science fiction novel ["A Deepness in the Sky"][vinge-novel] by author Vernor Vinge. +In it the author uses the metric system as the basis for time measurements. + +[vinge-novel]: https://www.tor.com/2017/08/03/science-fiction-with-something-for-everyone-a-deepness-in-the-sky-by-vernor-vinge/ +~~~~ diff --git a/exercises/practice/gigasecond/.meta/config.json b/exercises/practice/gigasecond/.meta/config.json new file mode 100644 index 0000000..1beac28 --- /dev/null +++ b/exercises/practice/gigasecond/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "gigasecond.red" + ], + "test": [ + "gigasecond-test.red" + ], + "example": [ + ".meta/example.red" + ] + }, + "blurb": "Given a moment, determine the moment that would be after a gigasecond has passed." +} diff --git a/exercises/practice/gigasecond/.meta/example.red b/exercises/practice/gigasecond/.meta/example.red new file mode 100644 index 0000000..6be8aa6 --- /dev/null +++ b/exercises/practice/gigasecond/.meta/example.red @@ -0,0 +1,11 @@ +Red [ + description: {"Gigasecond" exercise solution for exercism platform} + author: "BNAndras" +] + +add-gigasecond: function [ + moment +] [ + add moment to-time [0 0 1000000000] +] + diff --git a/exercises/practice/gigasecond/.meta/tests.toml b/exercises/practice/gigasecond/.meta/tests.toml new file mode 100644 index 0000000..6e00b76 --- /dev/null +++ b/exercises/practice/gigasecond/.meta/tests.toml @@ -0,0 +1,30 @@ +# 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. + +[92fbe71c-ea52-4fac-bd77-be38023cacf7] +description = "date only specification of time" + +[6d86dd16-6f7a-47be-9e58-bb9fb2ae1433] +description = "second test for date only specification of time" + +[77eb8502-2bca-4d92-89d9-7b39ace28dd5] +description = "third test for date only specification of time" + +[c9d89a7d-06f8-4e28-a305-64f1b2abc693] +description = "full time specified" + +[09d4e30e-728a-4b52-9005-be44a58d9eba] +description = "full time with day roll-over" + +[fcec307c-7529-49ab-b0fe-20309197618a] +description = "does not mutate the input" +include = false + diff --git a/exercises/practice/gigasecond/gigasecond-test.red b/exercises/practice/gigasecond/gigasecond-test.red new file mode 100644 index 0000000..b2a136a --- /dev/null +++ b/exercises/practice/gigasecond/gigasecond-test.red @@ -0,0 +1,64 @@ +Red [ + description: {Tests for "Gigasecond" Exercism exercise} + author: "loziniak" +] + +#include %testlib.red + +test-init/limit %gigasecond.red 1 +; test-init/limit %.meta/example.red 1 ; test example solutions + +canonical-cases: [#[ + description: "date only specification of time" + input: #[ + moment: 25-April-2011 + ] + expected: 1-January-2043/1:46:40 + function: "add-gigasecond" + uuid: "92fbe71c-ea52-4fac-bd77-be38023cacf7" +] #[ + description: "second test for date only specification of time" + input: #[ + moment: 13-June-1977 + ] + expected: 19-February-2009/1:46:40 + function: "add-gigasecond" + uuid: "6d86dd16-6f7a-47be-9e58-bb9fb2ae1433" +] #[ + description: "third test for date only specification of time" + input: #[ + moment: 19-July-1959 + ] + expected: 27-March-1991/1:46:40 + function: "add-gigasecond" + uuid: "77eb8502-2bca-4d92-89d9-7b39ace28dd5" +] #[ + description: "full time specified" + input: #[ + moment: 24-January-2015/22:00:00 + ] + expected: 2-October-2046/23:46:40 + function: "add-gigasecond" + uuid: "c9d89a7d-06f8-4e28-a305-64f1b2abc693" +] #[ + description: "full time with day roll-over" + input: #[ + moment: 24-January-2015/23:59:59 + ] + expected: 3-October-2046/01:46:39 + function: "add-gigasecond" + uuid: "09d4e30e-728a-4b52-9005-be44a58d9eba" +]] + + +foreach c-case canonical-cases [ + case-code: reduce [ + 'expect c-case/expected compose [ + (to word! c-case/function) (values-of c-case/input) + ] + ] + + test c-case/description case-code +] + +test-results/print diff --git a/exercises/practice/gigasecond/gigasecond.red b/exercises/practice/gigasecond/gigasecond.red new file mode 100644 index 0000000..7c243a9 --- /dev/null +++ b/exercises/practice/gigasecond/gigasecond.red @@ -0,0 +1,11 @@ +Red [ + description: {"Gigasecond" exercise solution for exercism platform} + author: "" ; you can write your name here, in quotes +] + +add-gigasecond: function [ + moment +] [ + cause-error 'user 'message "You need to implement the add-gigasecond function." +] + diff --git a/exercises/practice/gigasecond/testlib.red b/exercises/practice/gigasecond/testlib.red new file mode 100644 index 0000000..9b0b79e --- /dev/null +++ b/exercises/practice/gigasecond/testlib.red @@ -0,0 +1,217 @@ +Red [ + description: {Unit testing library} + author: "loziniak" +] + + +context [ + tested: ignore-after: test-file: results: output: none + + set 'test-init function [ + file [file!] + /limit + ia [integer!] + ] [ + self/tested: 0 + self/ignore-after: either limit [ia] [none] + self/test-file: file + self/results: copy [] + self/output: copy "" + ] + + sandbox!: context [ + + assert: function [ + code [block!] + /local result + ] [ + res: last results + + set/any 'result do code + either :result = true [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result + ] + + expect: function [ + expectation [any-type!] + code [block!] + /local result + ] [ + res: last results + res/expected: :expectation + + set/any 'result do code + res/actual: :result + + either :result = :expectation [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result + ] + + expect-error: function [ + type [word!] + code [block!] + /message + msg [string!] + /local result result-or-error + ] [ + returned-error?: no + set/any 'result-or-error try [ + set/any 'result do code + returned-error?: yes + :result + ] + + res: last results + res/actual: :result-or-error + res/expected: compose [type: (type)] + if message [append res/expected compose [id: 'message arg1: (msg)]] + + either all [ + error? :result-or-error + not returned-error? + result-or-error/type = type + any [ + not message + all [ + result-or-error/id = 'message + result-or-error/arg1 = msg + ] + ] + ] [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result-or-error + ] + ] + + set 'test function [ + summary [string!] + code [block!] + /extern + tested + ] [ + append results result: make map! compose/only [ + summary: (summary) ;@@ [string!] + test-code: (copy code) ;@@ [block!] + status: none ;@@ [word!] : 'pass | 'fail | 'error | 'ignored + ;-- expected (optional field) + ;-- actual (optional field) + ;-- output (optional field) + ] + + either any [ + none? ignore-after + tested < ignore-after + ] [ + clear output + old-functions: override-console + + exercise: make sandbox! load test-file + code: bind code exercise + uncaught?: yes + outcome: catch [ + outcome: try [ + catch/name [ + do code + ] 'expect-fail + none + ] + uncaught?: no + outcome + ] + + case [ + error? outcome [ + result/status: 'error + result/actual: outcome + ] + uncaught? [ + result/status: 'error + result/actual: make error! [type: 'throw id: 'throw arg1: outcome] + ] + ] + + restore-console old-functions + result/output: copy output + ] [ + result/status: 'ignored + ] + + tested: tested + 1 + ] + + set 'test-results function [ + /print + ] [ + either print [ + foreach result self/results [ + system/words/print rejoin [ + pad/with result/summary 40 #"." + "... " + switch result/status [ + pass ["✓"] + fail [rejoin [ + {FAILED.} + either find result 'expected [rejoin [ + { Expected: } result/expected + either find result 'actual [rejoin [ + {, but got } result/actual + ]] [] + ]] [] + newline + result/output + ]] + error [rejoin [ + newline + result/output + form result/actual + ]] + ignored ["(ignored)"] + ] + ] + ] + ] [ + self/results + ] + ] + + + override-console: function [] [ + old-functions: reduce [:prin :print :probe] + + system/words/prin: function [value [any-type!]] [ + append self/output form :value + return () + ] + system/words/print: function [value [any-type!]] [ + append self/output reduce [form :value #"^/"] + return () + ] + system/words/probe: function [value [any-type!]] [ + append self/output reduce [mold :value #"^/"] + return :value + ] + return old-functions + ] + + restore-console: function [old-functions [block!]] [ + set [prin print probe] old-functions + ] + +]