From af9641f4e90f689de31ab403ae887a537a86cb48 Mon Sep 17 00:00:00 2001 From: Danylo Negrienko Date: Mon, 11 Mar 2024 08:03:00 -0400 Subject: [PATCH] secret_handshake --- elixir/secret-handshake/.exercism/config.json | 27 +++++++ .../secret-handshake/.exercism/metadata.json | 1 + elixir/secret-handshake/.formatter.exs | 4 + elixir/secret-handshake/.gitignore | 24 ++++++ elixir/secret-handshake/HELP.md | 75 +++++++++++++++++ elixir/secret-handshake/HINTS.md | 9 +++ elixir/secret-handshake/README.md | 81 +++++++++++++++++++ .../secret-handshake/lib/secret_handshake.ex | 35 ++++++++ elixir/secret-handshake/mix.exs | 28 +++++++ .../test/secret_handshake_test.exs | 65 +++++++++++++++ elixir/secret-handshake/test/test_helper.exs | 2 + 11 files changed, 351 insertions(+) create mode 100644 elixir/secret-handshake/.exercism/config.json create mode 100644 elixir/secret-handshake/.exercism/metadata.json create mode 100644 elixir/secret-handshake/.formatter.exs create mode 100644 elixir/secret-handshake/.gitignore create mode 100644 elixir/secret-handshake/HELP.md create mode 100644 elixir/secret-handshake/HINTS.md create mode 100644 elixir/secret-handshake/README.md create mode 100644 elixir/secret-handshake/lib/secret_handshake.ex create mode 100644 elixir/secret-handshake/mix.exs create mode 100644 elixir/secret-handshake/test/secret_handshake_test.exs create mode 100644 elixir/secret-handshake/test/test_helper.exs diff --git a/elixir/secret-handshake/.exercism/config.json b/elixir/secret-handshake/.exercism/config.json new file mode 100644 index 0000000..2289505 --- /dev/null +++ b/elixir/secret-handshake/.exercism/config.json @@ -0,0 +1,27 @@ +{ + "authors": [ + "DoggettCK" + ], + "contributors": [ + "angelikatyborska", + "Cohen-Carlisle", + "devonestes", + "mlopes", + "neenjaw", + "sotojuan" + ], + "files": { + "solution": [ + "lib/secret_handshake.ex" + ], + "test": [ + "test/secret_handshake_test.exs" + ], + "example": [ + ".meta/example.ex" + ] + }, + "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/elixir/secret-handshake/.exercism/metadata.json b/elixir/secret-handshake/.exercism/metadata.json new file mode 100644 index 0000000..09ae32b --- /dev/null +++ b/elixir/secret-handshake/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"elixir","exercise":"secret-handshake","id":"a6cee5c3d5854a26823d4e65de58e330","url":"https://exercism.org/tracks/elixir/exercises/secret-handshake","handle":"negrienko","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/elixir/secret-handshake/.formatter.exs b/elixir/secret-handshake/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/elixir/secret-handshake/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/elixir/secret-handshake/.gitignore b/elixir/secret-handshake/.gitignore new file mode 100644 index 0000000..5528e77 --- /dev/null +++ b/elixir/secret-handshake/.gitignore @@ -0,0 +1,24 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +secret_handshake-*.tar + diff --git a/elixir/secret-handshake/HELP.md b/elixir/secret-handshake/HELP.md new file mode 100644 index 0000000..b975b8d --- /dev/null +++ b/elixir/secret-handshake/HELP.md @@ -0,0 +1,75 @@ +# Help + +## Running the tests + +From the terminal, change to the base directory of the exercise then execute the tests with: + +```bash +$ mix test +``` + +This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs` + +Documentation: + +* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html) +* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html) + +## Pending tests + +In test suites of practice exercises, all but the first test have been tagged to be skipped. + +Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol. + +For example: + +```elixir +# @tag :pending +test "shouting" do + assert Bob.hey("WATCH OUT!") == "Whoa, chill out!" +end +``` + +If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command: + +```bash +$ mix test --include pending +``` + +Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`. + +```elixir +# ExUnit.configure(exclude: :pending, trace: true) +``` + +## Useful `mix test` options + +* `test/.exs:LINENUM` - runs only a single test, the test from `.exs` whose definition is on line `LINENUM` +* `--failed` - runs only tests that failed the last time they ran +* `--max-failures` - the suite stops evaluating tests when this number of test failures +is reached +* `--seed 0` - disables randomization so the tests in a single file will always be ran +in the same order they were defined in + +## Submitting your solution + +You can submit your solution using the `exercism submit lib/secret_handshake.ex` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir) +- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found. \ No newline at end of file diff --git a/elixir/secret-handshake/HINTS.md b/elixir/secret-handshake/HINTS.md new file mode 100644 index 0000000..445888f --- /dev/null +++ b/elixir/secret-handshake/HINTS.md @@ -0,0 +1,9 @@ +# Hints + +## General + +- Use `Bitwise` (or div/rem). +- If you use `Bitwise`, an easy way to see if a particular bit is set is to compare +the binary AND (`&&&`) of a set of bits with the particular bit pattern you +want to check, and determine if the result is the same as the pattern you're +checking. \ No newline at end of file diff --git a/elixir/secret-handshake/README.md b/elixir/secret-handshake/README.md new file mode 100644 index 0000000..31ad56b --- /dev/null +++ b/elixir/secret-handshake/README.md @@ -0,0 +1,81 @@ +# Secret Handshake + +Welcome to Secret Handshake on Exercism's Elixir Track. +If you need help running the tests or submitting your code, check out `HELP.md`. +If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :) + +## 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. + +## 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 +~~~~ + +## Source + +### Created by + +- @DoggettCK + +### Contributed to by + +- @angelikatyborska +- @Cohen-Carlisle +- @devonestes +- @mlopes +- @neenjaw +- @sotojuan + +### Based on + +Bert, in Mary Poppins - https://www.imdb.com/title/tt0058331/quotes/?item=qt0437047 \ No newline at end of file diff --git a/elixir/secret-handshake/lib/secret_handshake.ex b/elixir/secret-handshake/lib/secret_handshake.ex new file mode 100644 index 0000000..f5d802f --- /dev/null +++ b/elixir/secret-handshake/lib/secret_handshake.ex @@ -0,0 +1,35 @@ +defmodule SecretHandshake do + @doc """ + Determine the actions of a secret handshake based on the binary + representation of the given `code`. + + If the following bits are set, include the corresponding action in your list + of commands, in order from lowest to highest. + + 1 1 = wink + 2 10 = double blink + 4 100 = close your eyes + 8 1000 = jump + + 16 10000 = Reverse the order of the operations in the secret handshake + """ + + @coms %{ + 1 => "wink", + 2 => "double blink", + 4 => "close your eyes", + 8 => "jump", + 16 => "reverse" + } + + @spec commands(code :: integer) :: list(String.t()) + def commands(code) do + @coms + |> Map.keys() + |> Enum.reduce([], &if(Bitwise.band(code, &1) == &1, do: [@coms[&1] | &2], else: &2)) + |> case do + ["reverse" | tail] -> tail + reversed_list -> Enum.reverse(reversed_list) + end + end +end diff --git a/elixir/secret-handshake/mix.exs b/elixir/secret-handshake/mix.exs new file mode 100644 index 0000000..ec009a9 --- /dev/null +++ b/elixir/secret-handshake/mix.exs @@ -0,0 +1,28 @@ +defmodule SecretHandshake.MixProject do + use Mix.Project + + def project do + [ + app: :secret_handshake, + version: "0.1.0", + # elixir: "~> 1.8", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/elixir/secret-handshake/test/secret_handshake_test.exs b/elixir/secret-handshake/test/secret_handshake_test.exs new file mode 100644 index 0000000..e3c9ba3 --- /dev/null +++ b/elixir/secret-handshake/test/secret_handshake_test.exs @@ -0,0 +1,65 @@ +defmodule SecretHandshakeTest do + use ExUnit.Case + + describe "Create a handshake for a number" do + #@tag :pending + test "wink for 1" do + assert SecretHandshake.commands(1) == ["wink"] + end + + #@tag :pending + test "double blink for 10" do + assert SecretHandshake.commands(2) == ["double blink"] + end + + #@tag :pending + test "close your eyes for 100" do + assert SecretHandshake.commands(4) == ["close your eyes"] + end + + #@tag :pending + test "jump for 1000" do + assert SecretHandshake.commands(8) == ["jump"] + end + + #@tag :pending + test "combine two actions" do + assert SecretHandshake.commands(3) == ["wink", "double blink"] + end + + #@tag :pending + test "reverse two actions" do + assert SecretHandshake.commands(19) == ["double blink", "wink"] + end + + #@tag :pending + test "reversing one action gives the same action" do + assert SecretHandshake.commands(24) == ["jump"] + end + + #@tag :pending + test "reversing no actions still gives no actions" do + assert SecretHandshake.commands(16) == [] + end + + #@tag :pending + test "all possible actions" do + assert SecretHandshake.commands(15) == ["wink", "double blink", "close your eyes", "jump"] + end + + #@tag :pending + test "reverse all possible actions" do + assert SecretHandshake.commands(31) == ["jump", "close your eyes", "double blink", "wink"] + end + + #@tag :pending + test "do nothing for zero" do + assert SecretHandshake.commands(0) == [] + end + + #@tag :pending + test "do nothing if lower 5 bits not set" do + assert SecretHandshake.commands(32) == [] + end + end +end diff --git a/elixir/secret-handshake/test/test_helper.exs b/elixir/secret-handshake/test/test_helper.exs new file mode 100644 index 0000000..35fc5bf --- /dev/null +++ b/elixir/secret-handshake/test/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.start() +ExUnit.configure(exclude: :pending, trace: true)