Percursos
/
Crystal
Crystal
/
Exercícios
/
Foto Fusionista
Foto Fusionista

Foto Fusionista

Exercício de aprendizagem

Introdução

O binário, o octal e o hexadecimal (também conhecido como hex) são sistemas de numeração diferentes, com bases diferentes. O binário é base 2, o octal é base 8 e o hexadecimal é base 16. Em Crystal, os números inteiros normais são base 10. O binário, o octal e o hexadecimal são todos representações de números inteiros. Isto significa que representam números positivos e negativos (incluindo o zero) sem frações nem casas decimais, e suportam todas as operações que podemos fazer com números inteiros.

Binário

O binário é um sistema de numeração de base 2, que usa apenas os algarismos 0 e 1. Representa habitualmente os estados 0 («desligado») e 1 («ligado») do fluxo elétrico através de transístores e interruptores nos computadores, bem como as cargas positivas e negativas nos suportes de armazenamento magnético. O binário pode representar todos os números inteiros que se usam na base 10.

Um excerto do sistema de base 2 é o seguinte, embora continue infinitamente e não pare em 128:

128 64 32 16 8 4 2 1
2 ** 7 2 ** 6 2 ** 5 2 ** 4 2 ** 3 2 ** 2 2 ** 1 2 ** 0

Por isso, se quisermos representar o número 6, em binário seria: 110

Valor posicional 4 2 1
Número binário 1 1 0

E a operação seria: 4 + 2 + 0 = 6

Outro exemplo: 19

Valor posicional 16 8 4 2 1
Número binário 1 0 0 1 1

O número binário seria: 10011 E a operação seria: 16 + 0 + 0 + 2 + 1 = 19

O binário em Crystal

Em Crystal, podemos representar literais binários com o prefixo 0b. Se escrevermos 0b10011, o Crystal interpreta-o como um número binário e converte-o para a base 10.

0b10011
# => 19

typeof(0b10011)
# => Int32

Se escreveres um número com o prefixo 0b que não esteja no sistema binário, o Crystal gera um erro de compilação.

0b10211
# => Error: unexpected token: "211"

Operações com números binários

Como os números binários são inteiros, podemos realizar neles todas as operações que podemos fazer com números inteiros.

0b10011 + 0b10011
# => 38

0b10011 * 0b10011
# => 361

0b10011 / 3
# => 6.333333333333333

Conversão de e para a representação binária

O Crystal converte automaticamente um literal binário num Int32. Para converter um Int32 numa representação binária, usa o método <int>.to_s(base) com o argumento base definido como 2. O método devolve uma representação em string do número binário:

19.to_s(2)
# => "10011"

Para converter uma representação em string de um binário num número inteiro, podemos usar o método <int>.to_i(base), passando a base (2) como argumento:

"10011".to_i(2)
# => 19

Indicar a base errada (ou uma representação binária inválida) gera um ArgumentError:

"011021".to_i(2)
# => Invalid Int32: "011021" (ArgumentError)

Métodos binários

Há certos métodos que podem ser usados em números inteiros para obter informações sobre a representação binária do número.

O <int>.bit_length devolve o número de bits necessários para representar o número:

19.bit_length
# => 5

O <int>.bit(index) devolve o bit no índice indicado, começando pela direita (bit menos significativo):

19.bit(0)
# => 1

0b10011.bit(1)
# => 1

Octal

O octal é um sistema de numeração de base 8. Usa os algarismos 0, 1, 2, 3, 4, 5, 6 e 7.

Em Crystal, podemos representar números octais com o prefixo 0o. Tal como no binário, o Crystal converte automaticamente uma representação octal num Int32.

0o123
# => 83

Se colocares o prefixo 0o num número que não pertença ao sistema octal, o Crystal gera um erro de compilação.

Conversão de e para a representação octal

Tal como no binário, podemos usar o método <int>.to_s(base) para converter um Int32 numa representação octal. E podemos usar o método <int>.to_i(base) para converter uma representação octal num Int32.

83.to_s(8)
# => "123"

"123".to_i(8)
# => 83

Tal como no binário, indicar a base errada gera um ArgumentError.

Hexadecimal

O hexadecimal é um sistema de numeração de base 16. Usa os algarismos 0 a 9 e as letras A, B, C, D, E e F. A é 10, B é 11, C é 12, D é 13, E é 14 e F é 15.

Podemos representar números hexadecimais em Crystal com o prefixo 0x. Tal como no binário e no octal, o Crystal converte automaticamente os literais hexadecimais em Int32.

#=> 0x123
291

Se colocares o prefixo 0x num número que não seja hexadecimal, o Crystal gera um erro de compilação.

Conversão de e para a representação hexadecimal

Tal como no binário, podemos usar o método <int>.to_s(base) para converter um Int32 numa representação hexadecimal. E podemos usar o método <int>.to_i(base) para converter uma representação hexadecimal num Int32.

291.to_s(16)
# => "123"

"123".to_i(16)
# => 291

Tal como no binário e no octal, indicar a base errada gera um ArgumentError.

Precisão

Quando convertemos um número numa representação em string, podemos especificar a precisão do número. Ou seja, a quantidade mínima de algarismos usada para representar o número. Se o número tiver menos algarismos do que a precisão, são acrescentados zeros à esquerda da representação em string. Isto faz-se passando o argumento precision ao método <int>.to_s(<base>, precision: <value>).

291.to_s(16, precision: 5)
# => "00123"

543.to_s(precision: 2)
# => "543"

Instruções

O teu amigo cansou-se de pagar por software de edição de fotografias e decidiu escrever o seu próprio. O teu amigo decidiu chamar ao novo software Foto Fusionist.

O Foto Fusionist é um software de edição de fotografias que consegue fazer muitas coisas, mas até agora só implementaste algumas delas. No entanto, o teu amigo está muito contente com o progresso e pediu-te para implementares mais algumas funcionalidades.

1. Converter a representação binária num inteiro

Para a primeira funcionalidade, o teu amigo quer conseguir converter a representação binária de um número num inteiro. Isto é feito porque o software vai poder ler a representação binária de um canal de cor e convertê-la num inteiro.

Implementa o método FotoFusionist.binary_to_int, que recebe um argumento binary do tipo String. O método deve devolver o inteiro representado pelo número binário.

FotoFusionist.binary_to_int("10011")
# => 19

2. Obter o bit menos significativo de um inteiro

A segunda funcionalidade que o teu amigo quer é conseguir obter o bit menos significativo de um inteiro. O bit menos significativo é o bit que está mais à direita. Chama-se bit menos significativo porque é o que tem o valor mais baixo.

O bit menos significativo é necessário para avaliar se uma imagem pode ser otimizada reduzindo o número de bits usados para representar o canal de cor.

Implementa o método FotoFusionist.least_significant_bit, que recebe um argumento number do tipo Int32. O método deve devolver o bit menos significativo do número.

FotoFusionist.least_significant_bit(0b10011)
# => 1

FotoFusionist.least_significant_bit(0b10010)
# => 0

3. Obter o valor hexadecimal de um canal de cor

A terceira funcionalidade que o teu amigo quer é conseguir obter o valor hexadecimal de um canal de cor. O valor hexadecimal é necessário para converter o canal de cor numa representação hexadecimal, e a representação hexadecimal dada tem de ser composta por dois algarismos.

Implementa o método FotoFusionist.hex_value, que recebe um argumento number do tipo Int32. O método deve devolver o valor hexadecimal do número como uma String.

FotoFusionist.hex_value(19)
# => "13"

4. Obter o valor hexadecimal de uma cor RGB

A quarta funcionalidade que o teu amigo quer é conseguir obter o valor hexadecimal de uma cor RGB. Isto é necessário para que o utilizador consiga obter uma única string que representa uma cor. Uma cor RGB é uma cor representada por três canais de cor: vermelho, verde e azul. Cada canal de cor é representado por um número entre 0 e 255.

O valor hexadecimal de uma cor RGB é uma representação em string da cor em hexadecimal, primeiro com o canal de cor vermelho, depois o canal de cor verde e, por último, o canal de cor azul.

Implementa o método FotoFusionist.hex_value_from_rgb, que recebe três argumentos: red, green e blue, do tipo Int32. O método deve devolver o valor hexadecimal da cor RGB como uma String.

FotoFusionist.hex_value_from_rgb(255, 0, 0)
# => "ff0000"
Editar via GitHub A ligação abre numa nova janela ou separador
Crystal Exercism

Estás pronto para começar Foto Fusionista?

Inscreve-te no Exercism para aprenderes e dominares Crystal com 26 conceitos142 exercícios, e mentoria humana real, tudo grátis.