Segredos

Segredos

Exercício de aprendizagem

Introdução

Operações bit a bit

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

Operações básicas

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.

and

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
or

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
Exclusive-or (xor)

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
Complement

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
Deslocamento de bits

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

Instruções

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.

1. Deslocar os bits de volta

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

2. Definir alguns bits

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

3. Inverter bits específicos

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

4. Limpar bits específicos

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

5. Desencriptar uma mensagem

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:

  1. Define os bits a partir do ano em que o teu amigo nasceu (1996)
  2. Inverte o resultado com o ano em que se conheceram (2009)
  3. Desloca os bits de volta pelo número de aulas que têm juntos (5)
  4. Limpa o primeiro e o quinto bit.
decrypt 380182 --> 11840

Implementa a função decrypt recorrendo a todas as funções que implementaste nas tarefas anteriores.

Editar via GitHub A ligação abre numa nova janela ou separador
Elm Exercism

Estás pronto para começar Segredos?

Inscreve-te no Exercism para aprenderes e dominares Elm com 28 conceitos110 exercícios, e mentoria humana real, tudo grátis.