As operações bit a bit permitem-nos manipular algarismos individuais dentro de números binários.
O Elm disponibiliza vários operadores bit a bit no seu módulo Bitwise
Modificar bits individuais de um número chama-se mascaramento.
Uma máscara é um número em que bits específicos foram definidos de uma determinada forma para manipular outro número com operadores bit a bit como and, or e xor.
O and combina dois números mantendo apenas os bits que são 1 em ambos.
Isto é útil para verificar se um determinado bit está definido.
Por exemplo, para verificar se o 4.º bit de um número está definido como 1, faz and com uma máscara 01000 (8 em decimal) e vê se o resultado é diferente de zero:
Bitwise.and 13 8 --> 8
-- 13 = 01101
-- 8 = 01000
-- and = 01000 = 8
O or combina dois números definindo cada bit como 1 se for 1 num dos números, ou em ambos.
Isto é útil para definir um bit específico como 1.
Por exemplo, para definir o 2.º bit em 10101, faz or com a máscara 00010:
Bitwise.or 21 2 --> 23
-- 21 = 10101
-- 2 = 00010
-- or = 10111 = 23
O xor combina dois números definindo cada bit como 1 se for 1 num número mas 0 no outro.
Isto é útil para inverter um bit para o seu valor oposto:
Bitwise.xor 20 5 --> 17
-- 20 = 10100
-- 5 = 00101
-- xor = 10001 = 17
O complement inverte cada bit de um número (0 passa a 1, 1 passa a 0).
Repara que isto fará com que números positivos passem a negativos, e números negativos passem a positivos.
Isto acontece porque os números negativos, em binário, são representados com 1 na posição mais à esquerda.
Bitwise.complement 21 --> -22
-- 21 = 00000000000000000000000000010101
-- complement = 11111111111111111111111111101010 = -22
Os operadores seguintes deslocam bits para a esquerda ou para a direita um número de posições especificado, multiplicando ou dividindo efetivamente por potências de 2.
shiftLeftBy desloca bits para a esquerda, preenchendo com 0 a partir do lado direito.
Por exemplo, para deslocar 21 três casas para a esquerda:
Bitwise.shiftLeftBy 3 21 --> 168
-- 21 = 10101
-- shiftLeftBy 3 = 10101000 = 168
Isto é o mesmo que dizer 21 * 2^3 = 21 * 2 * 2 * 2 = 168
shiftRightBy: desloca bits para a direita:
Bitwise.shiftRightBy 2 21 --> 5
-- 21 = 10101
-- shiftRightBy 2 = 00101 = 5
Deslocar duas casas para a direita é o mesmo que uma divisão inteira por 4.
Repara que esta função duplica o valor que estiver no bit mais à esquerda. Assim, os números negativos continuam negativos:
Bitwise.shiftRightBy 3 -21 --> -3
-- -21 = 111...101011
-- shiftRightBy 3 = 111...11101 = -3
Se quiseres deslocar para a direita e preencher com zeros, usa o shiftRightZfBy:
Bitwise.shiftRightZfBy 3 -21 --> 536870909
-- -21 = 111...101011
-- shiftRightZfBy 3 = 00111...11101 = 536870909
O teu amigo acabou de te enviar uma mensagem com um segredo importante. Para que não fosse fácil para os outros lê-la, a mensagem foi encriptada através de uma série de manipulações de bits. Vais precisar de escrever as funções que ajudam a desencriptar a mensagem.
O primeiro passo para desencriptar a mensagem é desfazer o deslocamento feito no processo de encriptação, deslocando os bits de volta para a direita.
Haverá passos seguintes no processo de desencriptação que assumem que os 0s são inseridos a partir do lado esquerdo.
Implementa a função shiftBack, que recebe um número de posições a deslocar e um valor, e efetua o deslocamento.
shiftBack 2 42 --> 10
De seguida, há alguns bits que precisam de ser definidos como 1.
Implementa a função setBits, que recebe uma máscara e um valor e devolve o resultado de definir como 1 os bits do valor.
Um bit do valor deve ser definido como 1 onde o bit da máscara também for 1.
Todos os outros bits devem permanecer inalterados.
setBits 66 212 --> 64
Alguns bits são invertidos durante a encriptação. Será preciso invertê-los de volta para desencriptar a mensagem.
Implementa a função flipBits, que recebe uma máscara e um valor.
A máscara indica quais os bits do valor a inverter.
Se o bit for 1 na máscara, o bit é invertido no valor.
Todos os outros bits permanecem inalterados.
flipBits 23 157 --> 138
Há também determinados bits que desencriptam sempre para 0.
Implementa a função clearBits, que recebe uma máscara e um valor.
Os bits do value devem ser definidos como 0 onde o bit da máscara for 1.
Todos os outros bits devem permanecer inalterados.
clearBits 2 15 --> 13
Agora que tens todas as funções de que precisas, podes descodificar a mensagem do teu amigo.
Implementa a função decrypt, que realiza as seguintes operações:
decrypt 380182 --> 11840
Implementa a função decrypt recorrendo a todas as funções que implementaste nas tarefas anteriores.
Inscreve-te no Exercism para aprenderes e dominares Elm com 28 conceitos110 exercícios, e mentoria humana real, tudo grátis.