Bitwise operations allow us to manipulate individual digits within binary numbers.
Elm provides several bitwise operators in its Bitwise module
Modifying individual bits of a number is called masking.
A mask is a number where specific bits have been set in a particular way to manipulate another number using bitwise operators such as and, or, and xor.
and combines two numbers by keeping only the bits that are 1 in both.
This is useful for checking to see if an individual bit is set.
For example, to check if the 4th bit of a number is set to 1, and it with a mask of 01000 (8 in decimal) and see if the result is non-zero:
Bitwise.and 13 8 --> 8
-- 13 = 01101
-- 8 = 01000
-- and = 01000 = 8
or combines two numbers by setting each bit to 1 if it is 1 in either or both numbers.
This is useful for setting a specific bit to 1.
For example, to set the 2nd bit in 10101, or it with the mask 00010:
Bitwise.or 21 2 --> 23
-- 21 = 10101
-- 2 = 00010
-- or = 10111 = 23
xor combines two numbers by setting each bit to 1 if it is 1 in one number but 0 in the other.
This is useful for flipping a bit to its opposite value:
Bitwise.xor 20 5 --> 17
-- 20 = 10100
-- 5 = 00101
-- xor = 10001 = 17
complement inverts each bit of a number (0 becomes 1, 1 becomes 0).
Note that this will result in positive numbers becoming negative, and negative numbers becoming positive.
This is because negative numbers in binary are represented with 1 in the left-most position.
Bitwise.complement 21 --> -22
-- 21 = 00000000000000000000000000010101
-- complement = 11111111111111111111111111101010 = -22
The following operators move bits left or right by a specified number of positions, effectively multiplying or dividing by powers of 2.
shiftLeftBy moves bits to the left, filling in with 0 from the right-hand side.
For example, to shift 21 left by 3 places:
Bitwise.shiftLeftBy 3 21 --> 168
-- 21 = 10101
-- shiftLeftBy 3 = 10101000 = 168
This is the same as saying 21 * 2^3 = 21 * 2 * 2 * 2 = 168
shiftRightBy: Moves bits to the right:
Bitwise.shiftRightBy 2 21 --> 5
-- 21 = 10101
-- shiftRightBy 2 = 00101 = 5
Shifting to the right by 2 places is the same as integer division by 4.
Note that this function duplicates whatever value is in the leftmost bit. So, negative numbers will stay negative:
Bitwise.shiftRightBy 3 -21 --> -3
-- -21 = 111...101011
-- shiftRightBy 3 = 111...11101 = -3
If you want to shift right and fill in with zeros, use shiftRightZfBy:
Bitwise.shiftRightZfBy 3 -21 --> 536870909
-- -21 = 111...101011
-- shiftRightZfBy 3 = 00111...11101 = 536870909
Your friend has just sent you a message with an important secret. Not wanting to make it easy for others to read it, the message was encrypted by performing a series of bit manipulations. You will need to write the functions to help decrypt the message.
The first step in decrypting the message is to undo the shifting from the encryption process by shifting the bits back to the right.
There will be further steps in the decryption process that assume 0s are inserted from the left hand side.
Implement the shiftBack function that takes a number of places to shift by and a value and performs the shift.
shiftBack 2 42 --> 10
Next, there are some bits that need to be set to 1.
Implement the setBits function that takes a mask and value and returns the result of setting the bits in value to 1.
A bit from value should be set to 1 where the bit in the mask is also 1.
All other bits should be kept unchanged.
setBits 66 212 --> 64
Some bits are flipped during encryption. They will need to be flipped back to decrypt the message.
Implement the flipBits function that takes a mask and a value.
The mask indicates which bits in the value to flip.
If the bit is 1 in mask, the bit is flipped in the value.
All other bits are kept unchanged.
flipBits 23 157 --> 138
There are also certain bits that always decrypt to 0.
Implement the clearBits function that takes a mask and a value.
The bits in the value should be set to 0 where the bit in the mask is 1.
All other bits should be kept unchanged.
clearBits 2 15 --> 13
Now that you have all the functions you need, you can decode your friend's message.
Implement the decrypt function that performs the following operations:
decrypt 380182 --> 11840
Please implement decrypt with all the functions you implemented in the previous tasks.
Sign up to Exercism to learn and master Elm with 28 concepts110 exercises, and real human mentoring, all for free.