tio407

tio407

Bitwise operator in Elixir - need help understanding it

I’m failing to grasp what the Bitwise module is doing. The documentation doesn’t have much (see for yourself). I have a decent understanding of binary already. Not sure what the &&& is doing though.

Any explanation to help me understand the following code (just a practice problem off Exercism) would be immensely helpful. I have 2 weeks to get off the ground and start an Elixir project at work so trying to learn as much as I can.

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 = wink
  10 = double blink
  100 = close your eyes
  1000 = jump

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

  use Bitwise

  @spec commands(code :: integer) :: list(String.t())
  def commands(code) do
    []
    |> handshake(code &&& 0b00001)
    |> handshake(code &&& 0b00010)
    |> handshake(code &&& 0b00100)
    |> handshake(code &&& 0b01000)
    |> handshake(code &&& 0b10000)
  end

  def handshake(list, 0b00001), do: list ++ ["wink"]
  def handshake(list, 0b00010), do: list ++ ["double blink"]
  def handshake(list, 0b00100), do: list ++ ["close your eyes"]
  def handshake(list, 0b01000), do: list ++ ["jump"]
  def handshake(list, 0b10000), do: Enum.reverse(list)
  def handshake(list, _), do: list
end

Most Liked

cmkarlsson

cmkarlsson

I find it easier to show it using bits

5 = 0b0101
6 = 0b0110

The Bitwise.band (&&&) is a bitwise and, meaning only if the bit is set on both sides it is kept.

5 = 0b0101
6 = 0b0110
# The position with both bit sets (1) results in the position being set (1).
4 = 0b0100 = 0b0110 &&& 0b0101

The ||| is the bitwise or where you get a 1 if there is a bit set in the same position on either or both side.
The ^^^is the xor (exclusive or) where you get a 1 only if the bit is set on either side. `

A simple demonstration:

iex(30)> [ 0 ^^^ 1, 1 ^^^ 0, 0 ^^^ 0, 1 ^^^ 1 ]
[1, 1, 0, 0]
iex(31)> [ 0 &&& 1, 1 &&& 0, 0 &&& 0, 1 &&& 1 ]
[0, 0, 0, 1]
iex(32)> [ 0 ||| 1, 1 ||| 0, 0 ||| 0, 1 ||| 1 ]
[1, 1, 0, 1]
13
Post #2
kokolegorille

kokolegorille

You can get binary representation of an integer with Integer.to_string x, 2
&&& is and operation, which copy a bit if it exists in both bit representation of numbers

As an example, 5 &&& 6 returns 4, as expected.

iex> Integer.to_string 5, 2
"101"
iex> Integer.to_string 6, 2
"110"
iex> Integer.to_string 4, 2
"100"
iex> use Bitwise
Bitwise
iex> 5 &&& 6
4

BTW if You have a binary like this

0b01101

it will returns a list like that

["wink", "close your eyes", "jump"]
cmkarlsson

cmkarlsson

If a bit is set, it is 1. Otherwise 0.

In this case 1, 10, 100, 1000, 10000 are not decimal numbers. They are the bit position. If a bit is set you should include the specific action.

0b00001 = 'wink'
0b00010 = 'double blink'
0b00100 = 'close your eyes'
0b01000 = 'jump'
0b10000 = 'reverse'

This is a common way to deal with flags in a binary format.

Above you have 5 bits (0-31).

Lets take decimal number 10. This is 0b01010. The bits at position 2 and 4 are set. Which means double-wink and jump

So. you start by checking if the wink bit is set, and then go through all the other commands

I’ll do this imperatively.

## This is not good elixir! Don't do this
commands = []
commands = if (10 &&& 0b00001) == 1, do: commands ++ ["wink"], else: commands
commands = if (10 &&& 0b00010) == 2, do: commands ++ ["double blink"], else: commands
commands = if (10 &&& 0b00100) == 4, do: commands ++ [ "close your eyes"], else: commands
commands = if (10 &&& 0b01000) == 8, do: commands ++ ["jump"], else: commands
commands = if (10 &&& 0b10000) == 16, do: Enum.reverse(commands), else: commands

Basicially we check each individual bit to see if it is set with the Bitwise.&&& operator. If it is set we add the command the the command list or reverse it in case the most significant bit it set.

Your initial solution uses elixir pipes and function pattern matching to do the same thing.

Last Post!

belgoros

belgoros

Yep, seeing it all together clarifies the solution. Thank you!
As for re-submitting a new version, you can always do it by running
exercism submit lib/secret_handshake.ex from your terminal (excersism CLI should be installed first).

Where Next?

Popular in Questions Top

joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 44778 311
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New

We're in Beta

About us Mission Statement