From 72e6c57aa43e29f7b9497e8e6e9e60bfbd8284d9 Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Mon, 1 Jul 2024 12:08:16 -0400 Subject: [PATCH] Add secret-handshake exercise --- config.json | 8 +++ .../secret-handshake/.docs/instructions.md | 48 +++++++++++++ .../secret-handshake/.docs/introduction.md | 7 ++ .../secret-handshake/.meta/config.json | 19 +++++ .../secret-handshake/.meta/proof.ci.wren | 16 +++++ .../secret-handshake/.meta/tests.toml | 43 ++++++++++++ exercises/practice/secret-handshake/LICENSE | 21 ++++++ .../practice/secret-handshake/package.wren | 14 ++++ .../secret-handshake.spec.wren | 70 +++++++++++++++++++ .../secret-handshake/secret-handshake.wren | 5 ++ 10 files changed, 251 insertions(+) create mode 100644 exercises/practice/secret-handshake/.docs/instructions.md create mode 100644 exercises/practice/secret-handshake/.docs/introduction.md create mode 100644 exercises/practice/secret-handshake/.meta/config.json create mode 100644 exercises/practice/secret-handshake/.meta/proof.ci.wren create mode 100644 exercises/practice/secret-handshake/.meta/tests.toml create mode 100644 exercises/practice/secret-handshake/LICENSE create mode 100644 exercises/practice/secret-handshake/package.wren create mode 100644 exercises/practice/secret-handshake/secret-handshake.spec.wren create mode 100644 exercises/practice/secret-handshake/secret-handshake.wren diff --git a/config.json b/config.json index 5970fff..0801fd9 100644 --- a/config.json +++ b/config.json @@ -454,6 +454,14 @@ "prerequisites": [], "difficulty": 3 }, + { + "slug": "secret-handshake", + "name": "Secret Handshake", + "uuid": "b86e8223-bc7e-4df8-9fa1-2751b611c90d", + "practices": [], + "prerequisites": [], + "difficulty": 3 + }, { "slug": "custom-set", "name": "Custom Set", diff --git a/exercises/practice/secret-handshake/.docs/instructions.md b/exercises/practice/secret-handshake/.docs/instructions.md new file mode 100644 index 0000000..d2120b9 --- /dev/null +++ b/exercises/practice/secret-handshake/.docs/instructions.md @@ -0,0 +1,48 @@ +# Instructions + +Your task is to convert a number between 1 and 31 to a sequence of actions in the secret handshake. + +The sequence of actions is chosen by looking at the rightmost five digits of the number once it's been converted to binary. +Start at the right-most digit and move left. + +The actions for each number place are: + +```plaintext +00001 = wink +00010 = double blink +00100 = close your eyes +01000 = jump +10000 = Reverse the order of the operations in the secret handshake. +``` + +Let's use the number `9` as an example: + +- 9 in binary is `1001`. +- The digit that is farthest to the right is 1, so the first action is `wink`. +- Going left, the next digit is 0, so there is no double-blink. +- Going left again, the next digit is 0, so you leave your eyes open. +- Going left again, the next digit is 1, so you jump. + +That was the last digit, so the final code is: + +```plaintext +wink, jump +``` + +Given the number 26, which is `11010` in binary, we get the following actions: + +- double blink +- jump +- reverse actions + +The secret handshake for 26 is therefore: + +```plaintext +jump, double blink +``` + +~~~~exercism/note +If you aren't sure what binary is or how it works, check out [this binary tutorial][intro-to-binary]. + +[intro-to-binary]: https://medium.com/basecs/bits-bytes-building-with-binary-13cb4289aafa +~~~~ diff --git a/exercises/practice/secret-handshake/.docs/introduction.md b/exercises/practice/secret-handshake/.docs/introduction.md new file mode 100644 index 0000000..176b92e --- /dev/null +++ b/exercises/practice/secret-handshake/.docs/introduction.md @@ -0,0 +1,7 @@ +# Introduction + +You are starting a secret coding club with some friends and friends-of-friends. +Not everyone knows each other, so you and your friends have decided to create a secret handshake that you can use to recognize that someone is a member. +You don't want anyone who isn't in the know to be able to crack the code. + +You've designed the code so that one person says a number between 1 and 31, and the other person turns it into a series of actions. diff --git a/exercises/practice/secret-handshake/.meta/config.json b/exercises/practice/secret-handshake/.meta/config.json new file mode 100644 index 0000000..42cedd9 --- /dev/null +++ b/exercises/practice/secret-handshake/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "glennj" + ], + "files": { + "solution": [ + "secret-handshake.wren" + ], + "test": [ + "secret-handshake.spec.wren" + ], + "example": [ + ".meta/proof.ci.wren" + ] + }, + "blurb": "Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.", + "source": "Bert, in Mary Poppins", + "source_url": "https://www.imdb.com/title/tt0058331/quotes/?item=qt0437047" +} diff --git a/exercises/practice/secret-handshake/.meta/proof.ci.wren b/exercises/practice/secret-handshake/.meta/proof.ci.wren new file mode 100644 index 0000000..4ca4e20 --- /dev/null +++ b/exercises/practice/secret-handshake/.meta/proof.ci.wren @@ -0,0 +1,16 @@ +class SecretHandshake { + static commands(code) { + var actions = ["wink", "double blink", "close your eyes", "jump"] + + var result = [] + for (i in 0...actions.count) { + if (isBitSet_(code, i)) result.add(actions[i]) + } + + return isBitSet_(code, actions.count) ? reverse_(result) : result + } + + static isBitSet_(n, i) { (n >> i) & 1 == 1 } + + static reverse_(list) { list.reduce([]) {|rev, elem| [elem] + rev} } +} diff --git a/exercises/practice/secret-handshake/.meta/tests.toml b/exercises/practice/secret-handshake/.meta/tests.toml new file mode 100644 index 0000000..f318e52 --- /dev/null +++ b/exercises/practice/secret-handshake/.meta/tests.toml @@ -0,0 +1,43 @@ +# 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. + +[b8496fbd-6778-468c-8054-648d03c4bb23] +description = "wink for 1" + +[83ec6c58-81a9-4fd1-bfaf-0160514fc0e3] +description = "double blink for 10" + +[0e20e466-3519-4134-8082-5639d85fef71] +description = "close your eyes for 100" + +[b339ddbb-88b7-4b7d-9b19-4134030d9ac0] +description = "jump for 1000" + +[40499fb4-e60c-43d7-8b98-0de3ca44e0eb] +description = "combine two actions" + +[9730cdd5-ef27-494b-afd3-5c91ad6c3d9d] +description = "reverse two actions" + +[0b828205-51ca-45cd-90d5-f2506013f25f] +description = "reversing one action gives the same action" + +[9949e2ac-6c9c-4330-b685-2089ab28b05f] +description = "reversing no actions still gives no actions" + +[23fdca98-676b-4848-970d-cfed7be39f81] +description = "all possible actions" + +[ae8fe006-d910-4d6f-be00-54b7c3799e79] +description = "reverse all possible actions" + +[3d36da37-b31f-4cdb-a396-d93a2ee1c4a5] +description = "do nothing for zero" diff --git a/exercises/practice/secret-handshake/LICENSE b/exercises/practice/secret-handshake/LICENSE new file mode 100644 index 0000000..c362f61 --- /dev/null +++ b/exercises/practice/secret-handshake/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Exercism + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/exercises/practice/secret-handshake/package.wren b/exercises/practice/secret-handshake/package.wren new file mode 100644 index 0000000..a5728c5 --- /dev/null +++ b/exercises/practice/secret-handshake/package.wren @@ -0,0 +1,14 @@ +import "wren-package" for WrenPackage, Dependency +import "os" for Process + +class Package is WrenPackage { + construct new() {} + name { "exercism/secret-handshake" } + dependencies { + return [ + Dependency.new("wren-testie", "0.3.0", "https://github.com/joshgoebel/wren-testie.git") + ] + } +} + +Package.new().default() diff --git a/exercises/practice/secret-handshake/secret-handshake.spec.wren b/exercises/practice/secret-handshake/secret-handshake.spec.wren new file mode 100644 index 0000000..530c2ca --- /dev/null +++ b/exercises/practice/secret-handshake/secret-handshake.spec.wren @@ -0,0 +1,70 @@ +import "./secret-handshake" for SecretHandshake +import "wren-testie/testie" for Testie, Expect + +Testie.test("SecretHandshake") { |do, skip| + do.test("wink for 1") { + var actual = SecretHandshake.commands(1) + var expected = ["wink"] + Expect.value(actual).toEqual(expected) + } + + skip.test("double blink for 10") { + var actual = SecretHandshake.commands(2) + var expected = ["double blink"] + Expect.value(actual).toEqual(expected) + } + + skip.test("close your eyes for 100") { + var actual = SecretHandshake.commands(4) + var expected = ["close your eyes"] + Expect.value(actual).toEqual(expected) + } + + skip.test("jump for 1000") { + var actual = SecretHandshake.commands(8) + var expected = ["jump"] + Expect.value(actual).toEqual(expected) + } + + skip.test("combine two actions") { + var actual = SecretHandshake.commands(3) + var expected = ["wink", "double blink"] + Expect.value(actual).toEqual(expected) + } + + skip.test("reverse two actions") { + var actual = SecretHandshake.commands(19) + var expected = ["double blink", "wink"] + Expect.value(actual).toEqual(expected) + } + + skip.test("reversing one action gives the same action") { + var actual = SecretHandshake.commands(24) + var expected = ["jump"] + Expect.value(actual).toEqual(expected) + } + + skip.test("reversing no actions still gives no actions") { + var actual = SecretHandshake.commands(16) + var expected = [] + Expect.value(actual).toEqual(expected) + } + + skip.test("all possible actions") { + var actual = SecretHandshake.commands(15) + var expected = ["wink", "double blink", "close your eyes", "jump"] + Expect.value(actual).toEqual(expected) + } + + skip.test("reverse all possible actions") { + var actual = SecretHandshake.commands(31) + var expected = ["jump", "close your eyes", "double blink", "wink"] + Expect.value(actual).toEqual(expected) + } + + skip.test("do nothing for zero") { + var actual = SecretHandshake.commands(0) + var expected = [] + Expect.value(actual).toEqual(expected) + } +} diff --git a/exercises/practice/secret-handshake/secret-handshake.wren b/exercises/practice/secret-handshake/secret-handshake.wren new file mode 100644 index 0000000..9ced3b7 --- /dev/null +++ b/exercises/practice/secret-handshake/secret-handshake.wren @@ -0,0 +1,5 @@ +class SecretHandshake { + static commands(code) { + Fiber.abort("Remove this statement and implement this function") + } +}