diff --git a/config.json b/config.json index b5cbc7f3..fd9f9d17 100644 --- a/config.json +++ b/config.json @@ -468,6 +468,14 @@ "practices": [], "prerequisites": [], "difficulty": 3 + }, + { + "slug": "secret-handshake", + "name": "Secret Handshake", + "uuid": "5f61e03e-f3b7-4d65-b73a-66383cfb6de2", + "practices": [], + "prerequisites": [], + "difficulty": 2 } ] }, diff --git a/exercises/practice/secret-handshake/.docs/instructions.md b/exercises/practice/secret-handshake/.docs/instructions.md new file mode 100644 index 00000000..d2120b9b --- /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 00000000..176b92e8 --- /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 00000000..51021b63 --- /dev/null +++ b/exercises/practice/secret-handshake/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "secret-handshake.8th" + ], + "test": [ + "test.8th" + ], + "example": [ + ".meta/example.8th" + ] + }, + "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/example.8th b/exercises/practice/secret-handshake/.meta/example.8th new file mode 100644 index 00000000..21394d03 --- /dev/null +++ b/exercises/practice/secret-handshake/.meta/example.8th @@ -0,0 +1,13 @@ +: bit-set? \ n n -- T + 1 swap n:shl n:band >bool +; + +: commands \ n -- a + >r a:new + r@ 0 bit-set? if "wink" a:push then + r@ 1 bit-set? if "double blink" a:push then + r@ 2 bit-set? if "close your eyes" a:push then + r@ 3 bit-set? if "jump" a:push then + r@ 4 bit-set? if a:rev then + rdrop +; diff --git a/exercises/practice/secret-handshake/.meta/tests.toml b/exercises/practice/secret-handshake/.meta/tests.toml new file mode 100644 index 00000000..f318e528 --- /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/libs/exercism/test b/exercises/practice/secret-handshake/libs/exercism/test new file mode 100644 index 00000000..1d08eb25 --- /dev/null +++ b/exercises/practice/secret-handshake/libs/exercism/test @@ -0,0 +1,173 @@ +needs console/loaded + +\ ----------------------------------------------------------------- + +ns: test + +-1 var, test-count +var tests-passed +var tests-failed +var tests-skipped +true var, run-test + +\ Some utility words + + +: test-passed \ s x x -- \\ test name, expected value, actual value + 2drop + 1 tests-passed n:+! + con:green con:onBlack . space " ... OK" . con:white con:onBlack cr +; + +: test-skipped \ s -- + 1 tests-skipped n:+! + con:cyan con:onBlack . space " ... SKIPPED" . con:white con:onBlack cr +; + +: test-failed \ s x x -- \\ test name, expected value, actual value + 1 tests-failed n:+! + rot + con:red con:onBlack . space " ... FAIL" . con:white con:onBlack cr + " Actual: «" . . "»" . cr + " Expected: «" . . "»" . cr cr +; + +: isword? \ x -- x f + dup >kind ns:w n:= +; + +: run-test? \ -- T + run-test @ if true else "RUN_ALL_TESTS" getenv n:>bool then +; + +\ Num passed + num skipped + num failed should == num tests +: all-tests-run? \ -- T + tests-passed @ tests-skipped @ tests-failed @ n:+ n:+ + test-count @ n:= +; + +\ returns true if x is a date, false otherwise +: date? \ x -- x T + dup >kind ns:d n:= +; + +\ adapted from 8th forum -- https://8th-dev.com/forum/index.php/topic,2745.0.html +: eq? \ x x -- T + \ are the items the same kind? + 2dup >kind swap >kind n:= + !if 2drop false ;then + + \ same kind: try different comparators + number? if n:= ;then + string? if s:= ;then + array? if ' eq? a:= 2nip ;then + map? if ' eq? m:= 2nip ;then + date? if d:= ;then + + \ otherwise fall back to 'lazy evaluation' + l: = +; + +: eps_eq? \ n x x -- T + \ are the items the same kind? + 2dup >kind swap >kind n:= + !if 2drop false ;then + number? !if 2drop false ;then + rot n:~= +; + +: check-depth \ ... n -- ... + dup>r + n:1+ depth n:= + !if + con:red con:onBlack + "PANIC: expected stack depth to be " . r> . cr + "Stack is:" . cr + .s cr + 255 die + then + rdrop +; + +\ ----------------------------------------------------------------- + +\ status report at end of run +( all-tests-run? + !if con:red con:onBlack "... FAIL - not all tests completed" . con:white con:onBlack cr then +) onexit + +\ Print a summary of the tests run +( con:white con:onBlack + test-count @ . space "tests planned - " . + tests-passed @ . space "passed - " . + tests-skipped @ . space "skipped - " . + tests-failed @ . space "failed" . cr +) onexit + +\ ----------------------------------------------------------------- +\ The public-facing words +\ ----------------------------------------------------------------- + +: equal? \ s x w -- | s w x -- + run-test? !if 2drop test-skipped ;; then + isword? !if swap then + w:exec + 3 check-depth + 2dup \ so test-failed can show actual and expected + eq? if test-passed else test-failed then +; + +: approx_equal? \ s x w n -- | s w x n -- + run-test? !if 3drop test-skipped ;; then + -rot isword? !if swap then + w:exec + 4 check-depth + 3dup \ so test-failed can show actual and expected + eps_eq? + if rot drop test-passed else rot drop test-failed then +; + +: true? \ s w -- + run-test? !if drop test-skipped ;; then + w:exec + 2 check-depth + true swap dup \ so test-failed can show actual and expected + if test-passed else test-failed then +; + +: false? \ s w -- + run-test? !if drop test-skipped ;; then + w:exec + 2 check-depth + false swap dup \ so test-failed can show actual and expected + !if test-passed else test-failed then +; + +: null? \ s w -- + run-test? !if drop test-skipped ;; then + w:exec + 2 check-depth + null swap dup \ so test-failed can show actual and expected + G:null? nip if test-passed else test-failed then +; + +: SKIP-REST-OF-TESTS false run-test ! ; + +: tests \ n -- + test-count ! +; + +\ Set the exit status: +\ 0 = all OK +\ 1 = not all tests were run (some error occurred) +\ 2 = some tests failed +: end-of-tests \ -- + all-tests-run? + if + tests-failed @ 0 n:= if 0 else 2 then + else + 1 + then + die +; + diff --git a/exercises/practice/secret-handshake/secret-handshake.8th b/exercises/practice/secret-handshake/secret-handshake.8th new file mode 100644 index 00000000..d2ce2b29 --- /dev/null +++ b/exercises/practice/secret-handshake/secret-handshake.8th @@ -0,0 +1,3 @@ +: commands \ n -- a + +; diff --git a/exercises/practice/secret-handshake/test.8th b/exercises/practice/secret-handshake/test.8th new file mode 100644 index 00000000..95c1b13d --- /dev/null +++ b/exercises/practice/secret-handshake/test.8th @@ -0,0 +1,64 @@ +"secret-handshake.8th" f:include +needs exercism/test +with: test +11 tests + +"wink for 1" + ( 1 commands ) + ["wink"] + equal? + +SKIP-REST-OF-TESTS + +"double blink for 10" + ( 2 commands ) + ["double blink"] + equal? + +"close your eyes for 100" + ( 4 commands ) + ["close your eyes"] + equal? + +"jump for 1000" + ( 8 commands ) + ["jump"] + equal? + +"combine two actions" + ( 3 commands ) + ["wink", "double blink"] + equal? + +"reverse two actions" + ( 19 commands ) + ["double blink", "wink"] + equal? + +"reversing one action gives the same action" + ( 24 commands ) + ["jump"] + equal? + +"reversing no actions still gives no actions" + ( 16 commands ) + [] + equal? + +"all possible actions" + ( 15 commands ) + ["wink", "double blink", "close your eyes", "jump"] + equal? + +"reverse all possible actions" + ( 31 commands ) + ["jump", "close your eyes", "double blink", "wink"] + equal? + +"do nothing for zero" + ( 0 commands ) + [] + equal? + +end-of-tests +;with