Exercism.io Secret handshake exercise?

I am doing some exercises while learning Elixir using Exercism.io.
Now, my objective is to do all exercises, extras included. This should give me a good grasp of the power of the language.

However I am having trouble. I don’t quite understand what some exercises want me to do, but I refuse to skip them either. One of these exercises is the following:

Introduction

There are 10 types of people in the world: Those who understand binary, and those who don’t.

You and your fellow cohort of those in the “know” when it comes to binary decide to come up with a secret “handshake”.

1 = wink
10 = double blink
100 = close your eyes
1000 = jump


10000 = Reverse the order of the operations in the secret handshake.

Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.

Here’s a couple of examples:

Given the input 3, the function would return the array [“wink”, “double blink”] because 3 is 11 in binary.

Given the input 19, the function would return the array [“double blink”, “wink”] because 19 is 10011 in binary. Notice that the addition of 16 (10000 in binary) has caused the array to be reversed.

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.

Example:

Flags: 0b11011 Check: 0b11010

Flags &&& Check: 0b11010 (All checked bits are set)

Another:

Flags: 0b11011 Check: 0b10110

Flags &&& Check: 0b10010 (Third bit not set)

Question

Could someone help me understand why 11 translates to ["wink", "double blink"] instead of translating to ["wink", "wink"] ? ( it has two 1, right ? )

I know I am missing something rather basic but I just can see what.

11 in “binary” is three.
1 (binary = one) is wink, 01 (binary = two) is double blink.
One and two (blink and double blink) is three (binary = 11).

I hope this i nearly correct. I didn’t do those exercices, but this should be the the answer, if i understand the question right…

Yes, its binary/base2.

In the example look at the position of the one, not it’s existence. 11 is not two ones. It is the far right 1, and the second farthest right 1. You do something for every 1 in the binary, depending on it’s position. So you should never have anything doubled.

As far as I can tell

Given a decimal number, convert it

should be “integer 0 <= n <= 31”

should return the array

should be “list”

iex(1)> import Bitwise 
Bitwise
iex(2)> wink = 0b1
1
iex(3)> blink = 0b10
2
iex(4)> close = 0b100
4
iex(5)> jump = 0b1000
8
iex(6)> reverse = 0b10000
1
iex(7)> 
nil
iex(8)> 
nil
iex(9)> (0b11 &&& wink) > 0
true
iex(10)> (0b11 &&& blink) > 0
true
iex(11)> (0b11 &&& close) > 0
false
iex(12)>

Integer? yes. Positive? Yes. Less than 32? No, since modulo arithmetic applies and is even tested AFAIR.

Yes, but the word array comes from a canonical description of the exercise, identical over all languages on exercism that implement this exercise.

My nose got out of joint at “decimal” which I interpret as a numeric value with a fractional portion.

In C it’s easy enough to simply look at everything as a bit pattern for better or worse. But I think a more constrained description would have been helpful.

Well, a decimal number is a number to the base of 10, as opposed to a binary or hexadecimal number which are to the base 2 or 16 respectively. But yes, wording is sub par in that description. I’ll try to find my beginners hat and revise it this week.

since modulo arithmetic applies and is even tested AFAIR.

Was there an allusion to how values greater than 31 are treated? What if I want ["wink","jump","wink"]? Frankly this is where I find these type of questions frustrating as the context seems to be oblivious to a lot of the unstated assumptions/constraints.

1 Like

None of the actions can happen twice. An action either happens or happens not, and they either happen from highest to lowest or from lowest to highest.

Those are the type of constraints that I like to see explicitly stated, otherwise more time is spent on trying to figure out what the intended problem is rather than solving the problem.

(I realize I’m in no position to complain given this is a volunteer effort - I just find the same to apply in other avenues.)

Sometimes the assignments are purposely vague, it’s a bit in the spirit of the customer that only ever tells what he really needs a week after the deadline :wink:

But yes, I liked this under the old exercism, but the new should clean up with those. This exercises are scary and not in the warm and welcoming spirit the new exercism should have.

Doesn’t even come close:

“We want this.”
“Why do you think you need that?”

… which sooner or later leads to the discovery that the actual problem needs a completely different solution.

If you are lucky and work for an employer that actually asks back… Congratulations. I’ve seen it differently a lot of times even though, I am in the lucky situation, that I’m developing on a core product that is mostly experimental, and as such requirements are discovered by myself and formalized by the team before they get implemented in future sprints.

I also feel like that, but for the sake of learning the language I try to power through as much as possible.

@NobbZ Wonderful insight, however this is not Exercism.io’s purpose. It’s purpose is not to simulate pesky clients it is to give you objective exercises so you can learn the language.

@peerreynders So, this is confusing to me.
I fail to see how doing 0b11011 &&& 0b10110 which results in 18, is supposed to tell me that the 3rd bit is not set and how that affects the exercise.

Yes, we are on par with that. At least now after the relaunch. But as I said, there is a lot to do after the relaunch to identify exercises that do not suite the new product and community goals anymore. Even more work is to be done to rephrase them or to decide to remove them completely.

I hope I find some time later today, after the kids are in bed, to at least skim some exercises to find some examples of “pesky clients” and then draft a first issue that I can post on github to actually raise the attention of Katrina Owen to the problem and get some discussion around the topic started.

The way the information is presented in the example makes no sense to me. “Recycling” the bits and pieces that are there leads me to this “best guess”:

iex(1)> import Bitwise
Bitwise
iex(2)> flags = 0b11011
27
iex(3)> check = 0b11010
26
iex(4)> (flags &&& check) == check # true - because all the necessary bits are set
true
iex(5)> flags = 0b11011
27
iex(6)> check = 0b10110
22
iex(7)> (flags &&& check) == check # false - because third bit is not set
false
iex(8)> 

So Exercism.io is a community driven effort ( by the Elixir community ? )
If so perhaps I could help as well? There is always strength in numbers.

This is another one that is quite fun with binary pattern matching :slight_smile:

defmodule Secret do
  def handshake(number) when is_integer(number) do
    handshake(<< number :: size(5) >>)
  end

  @code ["jump", "close your eyes", "double blink", "wink"]
  def handshake(<< reverse :: size(1), jump :: size(1), close :: size(1), double :: size(1), wink :: size(1) >>) do
    shake =
      [jump, close, double, wink]
      |> Enum.zip(@code)
      |> Enum.reduce([], fn
          {0, _}, acc -> acc
          {1, item}, acc -> [item | acc]
        end)

    # Since Enum.reduce/3 returns the list in reverse order,
    # we only reverse if the reverse bit is not set :-)
    if reverse == 1, do: shake, else: Enum.reverse(shake)
  end
end

iex> Secret.handshake 3
["wink", "double blink"]
hex> Secret.handshake 0b00111
["close your eyes", "double blink", "wink"]
iex> Secret.handshake 0b10111
["wink", "double blink", "close your eyes"]
1 Like

It’s fully open source.

Check out GitHub.com/exercism